EJB是什么Java使用EJB容器的详细概述

作者:EA视讯发布日期:2020-12-12 17:09

  最近项目中接触到EJB,但对EJB不是很了解,于是网上找了些资料参考,下面这篇是个人感觉讲的比较清晰的,遂转载一起参考,文章转自。

  既然说了EJB 是为了服务集群和企业级开发,那么,总得说说什么是所谓的服务集群和企业级开发吧!这个问题其实挺关键的,因为J2EE 中并没有说明白,也没有具体的指标或者事例告诉广大程序员什么时候用EJB 什么时候不用。于是大家都产生一些联想,认为EJB分布式运算指得是负载均衡提高系统的运行效率。然而,估计很多人都搞错了,这个服务群集和分布式运算并没有根本解决运行负载的问题,尤其是针对数据库的应用系统。为什么?

  我们先看一下,EJB 的官方解释:商务软件的核心部分是它的业务逻辑。业务逻辑抽象了整个商务过程的流程,并使用计算机语言将他们实现。……J2EE 对于这个问题的处理方法是将业务逻辑从客户端软件中抽取出来,封装在一个组件中。这个组件运行在一个独立的服务器上,客户端软件通过网络调用组件提供的服务以实现业务逻辑,而客户端软件的功能单纯到只负责发送调用请求和显示处理结果。在J2EE 中,这个运行在一个独立的服务器上,并封装了业务逻辑的组件就是EJB(EnterpriseJavaBean)组件。这其中我们主要关注这么几点,我们来逐条剖析:

  剖析1:所谓:业务逻辑我们注意到在EJB 的概念中主要提到的就是业务逻辑的封装,而这个业务逻辑到底是什么?说的那么悬乎,其实这个所谓的业务逻辑我们完全可以理解成执行特定任务的类。

  剖析2:所谓:将业务逻辑从客户端软件中抽取出来,封装在组件中……运行在一个服务器上既然我们知道了业务逻辑的概念就是执行特定任务的类,那么,什么叫从客户端软件中抽取出来?其实,这个就是把原来放到客户端的类,拿出来不放到客户端了,放到一个组件中,并将这个组件放到一个服务器上去运行。

  变成大白话就是,把你编写的软件中那些需要执行制定的任务的类,不放到客户端软件上了,而是给他打成包放到一个服务器上了。

  不管是用八股文说,还是用大白话说这个EJB 概念都提到了一个词--客户端软件。客户端软件?难道EJB 的概念中说的是C/S 软件?是的,没错!EJB 就是将那些类放到一个服务器上,用C/S 形式的软件客户端对服务器上的类进行调用。快崩溃了吧!EJB 和JSP 有什么关系?EJB 和JSP 有关系,但是关系还真不怎么大,至多是在JSP 的服务器端调用远端服务上的EJB 类,仅此而已。

  我们揭开了EJB八股概念的真谛,那么,再来分析EJB 的底层实现技术,通过底层实现技术来分析EJB 的工作方式。

  EJB 是运行在独立服务器上的组件,客户端是通过网络对EJB 对象进行调用的。在Java中,能够实现远程对象调用的技术是RMI,而EJB 技术基础正是RMI。通过RMI 技术,J2EE将EJB 组件创建为远程对象,客户端就可以通过网络调用EJB 对象了。

  名词1:对象的序列化对象的序列化概念:对象的序列化过程就是将对象状态转换成字节流和从字节流恢复对象。将对象状态转换成字节流之后,可以用java.io 包中的各种字节流类将其保存到文件中,或者通过网络连接将对象数据发送到另一个主机。上面的说法有点八股,我们不妨再用白话解释一下:对象的序列化就是将你程序中实例化的某个类的对象,比如,你自定一个类MyClass,或者任何一个类的对象,将它转换成字节数组,也就是说可以放到一个byte 数组中,这时候,你既然已经把一个对象放到了byte数组中,那么你当然就可以随便处置了它了,用得最多的就是把他发送到网络上远程的计算机上了。如图2 11所示。

  RPC 并不是一个纯粹的Java 概念,因为在Java 诞生之前就已经有了RPC 的这个概念,RPC是Remote Procedure Call的缩写,也就是远程过程调用。在Java 之前的大多数编程语言,如,Fortran、C、COBOL 等等,都是过程性的语言,而不是面向对象的。所以,这些编程语言很自然地用过程表示工作,如,函数或子程序,让其在网络上另一台机器上执行。说白了,就是本地计算机调用远程计算机上的一个函数。如图2 12所示。

  RMI 英文全称是Remote Method Invocation,它的中文名称是远程方法调用,它就是利用Java 对象序列化的机制实现分布式计算,实现远程类对象的实例化以及调用的方法。说的更清楚些,就是利用对象序列化来实现远程调用,也就是上面两个概念的结合体,利用这个方法来调用远程的类的时候,就不需要编写Socket 程序了,也不需要把对象进行序列化操作,直接调用就行了非常方便。远程方法调用是一种计算机之间对象互相调用对方函数,启动对方进程的一种机制,使用这种机制,某一台计算机上的对象在调用另外一台计算机上的方法时,使用的程序语法规则和在本地机上对象间的方法调用的语法规则一样。如图2 13所示。

  这种机制给分布计算的系统设计、编程都带来了极大的方便。只要按照RMI 规则设计程序,可以不必再过问在RMI 之下的网络细节了,如:TCP 和Socket 等等。任意两台计算机之间的通讯完全由RMI 负责。调用远程计算机上的对象就像本地对象一样方便。RMI 可将完整的对象作为参数和返回值进行传递,而不仅仅是预定义的数据类型。也就是说,可以将类似Java 哈西表这样的复杂类型作为一个参数进行传递。

  如果是较为简单的方法调用,其执行效率也许会比本地执行慢很多,即使和远程Socket机制的简单数据返回的应用相比,也会慢一些,原因是,其在网络间需要传递的信息不仅仅包含该函数的返回值信息,还会包含该对象序列化后的字节内容。

  通过RMI 技术,J2EE 将EJB 组件创建为远程对象,EJB 虽然用了RMI 技术,但是却只需要定义远程接口而无需生成他们的实现类,这样就将RMI 技术中的一些细节问题屏蔽了。但不管怎么说,EJB 的基础仍然是RMI,所以,如果你想了解EJB 的原理,只要把RMI的原理搞清楚就行了。你也就弄清楚了什么时候用EJB 什么时候不需要用EJB 了。

  既然已经知道了,RMI 是将各种任务与功能的类放到不同的服务器上,然后通过各个服务器间建立的调用规则实现分布式的运算,也就明白EJB 所谓的服务群集的概念。就是将原来在一个计算机上运算的几个类,分别放到其他计算机上去运行,以便分担运行这几个类所需要占用的CPU 和内存资源。同时,也可以将不同的软件功能模块放到不同的服务器上,当需要修改某些功能的时候直接修改这些服务器上的类就行了,修改以后所有客户端的软件都被修改了。如图2 14所示。

  图2 14所示的这个服务群集看似无懈可击,其实是它这个图没有画完整,我们来把这个图画完整,再来看看有什么问题没有。

  我们看看图2 15的结构图,现在如果想实现各个服务器针对同一个数据库的查询,那么,不管你部署多少个功能服务器,都需要针对一个数据库服务器进行查询操作。也就是说,不管你的计算有多么分布也同样需要从一台服务器中取得数据。虽然,看起来将各个功能模块分布在不同的服务器上从而分担了各个主计算机的CPU 资源,然而,真正的瓶颈并不在这里,而是,数据库服务器那里。数据库服务器都会非常忙的应付各个服务器的查询及操作请求。因此,通过这个结构图使我们了解到了EJB 根本不能完全解决负载的问题,因为,瓶颈并不在功能模块的所在位置,而是在数据库服务器这里。

  就是把每一个功能服务器后面都部署一个数据库,这样不就解决了上节所说的问题了吗?是的解决了数据库查询负载的问题,然而又出现了新的问题,就是数据共享的问题就又不容易解决了。

  我们再向前翻看看如图2 15所示的这种架构中存在两个网络,一个是A 网一个是B网,这两个网络是不同的。B 网往往是局域网,一般带宽是10M/100M,速度较快,因此到还好说,然而,A 网往往是互联网或者是利用电信网络互联VPN 网或称广域网。A 网的特点是带宽一般较窄,如ADSL 的网络仅仅有512K-2M 的带宽,由于广域网互联的成本较高,所以一般不会有较高的带宽。而在这个网络上恰恰跑的是功能模块和客户端软件之间交换的数据,而这部分数据恰恰优势非常占用带宽的。因此,这个应用架构其运行速度可以想见是多么的慢了。说句不夸张的话,有点想老牛拉破车一样的慢。一个如老牛的系统:目前在中国互联网做运营商网络管理系统的一个大公司,它的一个早期的网管软件就是采用了这种架构来做的C/S 结构的应用系统。有一次,我作为评估者来对其应用系统进行评估,将其部署到一个非运营商大型的网络中的时候,便出现了我们上述描述的情况,速度已经到了难以忍受的地步,打开一个流量图,有时候需要用15分钟的时间才能呈现完整。然而,该系统在开发阶段并没有发现这个问题,为什么呢?因为,他们没有考虑到应用的实际用户连接网络的复杂性,从而给该公司造成较大损失,以至于,这个开发架构被最终遗弃。

  通过上面小节的讲解似乎好像EJB 和开发Web 应用的B/S 结构的系统关系并不大,其实倒也不然。我们如果把客户端程序理解成某一台服务器,这样也是可以被应用的,而且,如果是服务器互相之间做EJB 的调用的话,也就不存在广域网带宽限制的问题了。但是,如下情况尽量就不要使用EJB 了:1、较为简单的纯Web 应用开发,不需要用EJB。2、需要与其他服务程序配合使用的应用,但调用或返回的自定义的网络协议可以解决的应用程序,不需要使用EJB。3、较多人并发访问的C/S 结构的应用程序,尽量不要使用EJB。

  a.EJB实现原理:就是把原来放到客户端实现的代码放到服务器端,并依靠RMI进行通信。

  c.服务器集群:就是通过RMI的通信,连接不同功能模块的服务器,以实现一个完整的功能。

  EJB的上层的分布式应用程序是基于对象组件模型的,低层的事务服务用了API技术。EJB技术简化了用 JAVA语言编写的企业应用系统的开发,配置,和执行。EJB的体系结构的规范由Sun Microsystems公司制定。 Inprise的EJB容器是基于1.1版的规范。

  EJB技术定义了一组可重用的组件:Enterprise Beans。你可以利用这些组件,象搭积木一样的建立你的分布式应用程序。当你把代码写好之后,这些组件就被组合到特定的文件中去。每个文件有一个或多个 Enterprise Beans,在加上一些配置参数。最后,这些Enterprise Beans被配置到一个装了EJB容器的平台上。客户能够通过这些Beans的home接口,定位到某个beans,并产生这个beans的一个实例。这样,客户就能够调用Beans的应用方法和远程接口。

  EJB服务器作为容器和低层平台的桥梁管理着EJB容器和函数。它向EJB容器提供了访问系统服务的能力。 例如:数据库的管理和事务的管理,或者对于其它的Enterprise的应用服务器。

  所有的EJB 实例都运行在EJB容器中。容器提供了系统级的服务,控制了EJB的生命周期。因为容器掌握了绝大多数系统级的issues(呵呵,不知道怎么翻译)。Enterprise Beans 的开发者不需要应用逻辑考虑进来。通常来说,EJB容器掌握了以下的系统级issues.

  1、Security–配置描述器(The Deployment descriptor)定义了客户能够访问的不同的应用函数。容器 通过只允许授权的客户访问这些函数来达到这个效果。

  2、Remote Connectivity–容器为远程链接管理着低层的通信issues,而且对Enterprise Beas的开发者和客户都隐藏了通信issues.Enterprise Beans的开发者在编写应用方法的时候,就象是在条用本地的平台一样的。客户也不清楚他们调用的方法可能是在远程被处理的。

  4、Trasction management—配置描述器定义了Enterprise beans 的事务处理的需求。容器管理着那些管理分布式事务处理的复杂的issues。这些事务可能要在不同的平台之间更新数据库。容器使这些事务之间互相独立,互不干扰。保证所有的更新数据库都是成功发生的,否者,就回滚到事务处理之前的状态。

  Session beans 是一种作为单个的client执行的对象。作为对远程的任务请求的相应,容器产生一个 Session beans 的实例。一个Session beans有一个client.从某种程度上来说,一个Session bean 对于服务器来说就代表了它的那个client.Session beans 也能用于事务,它能够更新共享的数据,但它不直接描绘这 些共享的数据。

  Session beans 的生命周期是相对较短的。典型的是,只有当client保持会话的时候,Session beans 才是活着的。一旦client退出了,Session beans 就不再与client相联系了。Session beans被看成是瞬时的,因为如果容器崩溃了,那么client必须重新建立一个新的Session对象来继续会话。

  一个Session bean也可能是一个无状态的 session bean.无状态的Session beans并不掌握它的客户的信息或者状态。Client能够调用beans的方法来完成一些操作。但是,beans只是在方法调用的时候才知道 client的参数变量。当方法调用完成以后,beans并不继续保持这些参数变量。这样,所有的无状态的 session beans的实例都是相同的,除非它正在方法调用期间。这样,无状态的Session beans就能够支持多个client.容器能够声明一个无状态的Session beans.能够将任何Session beans指定给任何client.

  Entity Beans对数据库中的数据提供了一种对象的视图。例如:一个Entity bean能够模拟数据库表中一行相关的数据。多个client能够共享访问同一个Entity bean.多个client也能够同时的访问同一个Entity bean.Entity beans通过事务的上下文来访问或更新下层的数据。这样,数据的完整性就能够被保证。

  Entity Beans能存活相对教长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。如果由容器控制着保证 Entity beans持续的issus。如果由 Beans自己管理,就必须写Entity beans的代码,包括访问数据库的调用。

  Entity Beans是由主键(primary key 一种唯一的对象标识符)标识的。通常,主键与标识数据库中的一 块数据,例如一个表中的一行,的主键是相同的。主键是client能够定位特定的数据块。

  EJB体系结构通过把编程的过程分为6个不同的角色而使开发复杂的的应用系统变的简单。6个不同的角色 ,每个都有特定的任务。6个角色包括下层的服务,应用程序的开发,配置和操作说明(issues)

  EJB体系结构能够简化应用程序开发人员的工作。在EJB体系结构中,容器和代理服务承担了很多在其他环 境中又程序设计人员承担的工作。这样的代理提供了很多原来需要程序设计人员编写代码的系统级的服务。

  EJB Server Providor服务提供者是典型的提供分布式低层服务的代理。EJB服务提供者提供了一个分布式 应用程序开发者需要的平台和设施。也提供了分布式程序的运行时环境。

  EJB Container Providor 容器提供者是分布式系统,事务处理,安全方面的专家容器提供者提供了一个 EJB的配置工具,和这些配置实例的运行时支持。

  一个容器对一个或多个EJB来说,是一个运行时系统。它将Enterprise Beans和EJB服务,包括事务服务,安全服务,分布式网络管理等胶合在一起。容器是既是一个定制的代码和对特定的 Enterprise beans产生详细代码的工具。容器也提供了一个配置Enterprise beans的工具和管理监视应用程序的方法。

  Enterprise beans Provider:Beans提供者在应用领域方面是专家。例如:Beans提供者可能是金融或电信方面的专家。Beans提供者提供了业务 tasks,Enterprise beans的业务方法,定义了beans的romote和home接口,还定义了beans的配置描述器。因为容器管理着系统级的任务,所以,Beans 提供者便不需要关心分布处理,事务处理,安全性能等从应用方面看来没什么关系的方面。

  这是一个将定制的Enterprise beans和其它的组件,例如,GUI client,applet,Servelet等组装成一个完整的应用程序的行家。在Enterprise的配置器下,组装器在组装成一个应用程序的时候,只关心beans的接口,包括romote接口和home接口。而不关心这些接口是怎么实现的。组装的结果就是一个一个的应用程序,或者由多个 Enterprise beans组合成的一个比较复杂的Enterprise beans.

  配置器为特定的Enterprise beans配置特殊的操作环境。配置器为了适应应用程序,将多个Enerprise beans 组合起来,通过修改Enterprise beans 的属性来达到配置相应的操作环境。例如,配置器通过设置配置描述符的相应的属性来设置事务和安全方针。配置器的另一个任务是将应用程序与现有的 Enterprise管理软件结合起来。

  是与配置应用有关的。管理者配置个管理Enterprise计算和网络服务的低层,包括EJB服务和容器。管理员监视着应用服务器的运行状况,当应用服务器不正常运行是就采取相应的措施。典型的说,管理员使用Enterprise管理工具来与应用程序打交道,通过由容器提供的hooks来配置。

  传统的应用程序开发者现在是Enterprise beans的提供者。也可能是应用程序的装配者。这样能使他们将主要精力放在应用问题或者应用逻辑上面。当安装Enterprise beans时,配置器定义了一系列的配置方针。机制的复杂性和执行配置的方针就交给了专门的代理。虽然分布式的应用程序还是比较复杂,可是,应用程序设计者的工作却变的简单了,因为所有复杂的工作都交给了EJB服务器和容器提供者了。

  通过大量的设计之前的定义和命名约定,EJB达到了前面提到的目的。这样的编程体系结构限制了一定的自由,但是,允许EJB服务器和容器提供者假定应用程序的设计,并以一种行之有效的方式来支持他们。

  有三种途径来建立一个基于对象的,多层的,分布式的系统:无状态服务的途径,基于会话的途径和持续对象的途径。

  无状态的服务是通过对象的操作提供一种功能的函数,但是,不保持会话的状态。当一个客户使用无状态的对象时,客户不能够提供上一次操作的信息。

  基于会话的设计产生了一个中间层的对象,称为一个会话(Session)。这个会话可以看成是这个客户的代理。典型的,会话的生命是由客户和所在的服务程序决定的。客户如果完成了会话就可以将对象移走。如果服务终止了,会话对象就会超时。会话对象就会变的无效了。

  持续对象设计模式绑定了存在数据库中的一块数据。提供了操作这块数据的一些个操作。持续对象是由多个客户共享的。起生命期是由存储数据的库所决定的。

  容器和服务提供者实现了EJB的基础构造。这些基础构造处理了EJB的分布式方面,事务管理,安全性方面。EJB规范定义了基础构造和J ava API的为了适应各种情况的要求。而没有去指定用什么技术,平台,协议来实现他们。

  Enterprise beans所有的数据的持续性必须被保证。EJB的低层结构必须提供在企业级的计算环境中与现存系统的结合能力。Beans的所有通信都是分布式事务的一部分,需要由EJB低层结构来管理对于一个成功的配置,EJB低层必须提供分布式应用管理工具的钩子(hooks)

  容器可能是EJB里面最重要的概念。因为它向程序开发人员提供了最大程度的方便。基于对象的中间层软件平台如CORBA或者远过程调用RMI是程序开发者从网络传输中解放出来,通过提供对象定位机制,数据重组机制等等。容器的概念则走的更远一点。通过简化分布式应用程序的那些复杂的方面,如:安全性,事务协调性,数据持久性。

  保证不同的Enterprise beans能够工作在一起。用名字服务来注册一个Enterprise Bean。通过EJB服务的通信系统提供访问EJB的入口。

  执行事务管理和安全方针。在一个EJB容器中可以又任意多个Enterprise beans.除了安装和执行以外,容器也提供了配置Enterprise beans的工具。为什么用Inprise的EJB 容器?Inprise EJB容器提供的完全的服务完全支持EJB1。1规范。一个有效的运行和管理EJBs的容器。提供命名服务,事务服务,植入Java RDBMS的内部。编程,配置简单充分的例子来演示怎样使用EJBs和EJB容器。对于Enterprise beans的开发者来说,EJB 容器是一个高级Enterprise类产品。因为它有如下优点:完整的,灵活的运行时环境:EJB容器完全实现了EJB1。1的规范,包括了它的所有功能。

  EJB容器能够进行单独配置,100%的纯JAVA服务,或者作为完全的分布式的配置。这样的灵活性意味着你能够根据你的要求调整你的应用程序。

  与其它的EJB服务不一样,Inprise 的EJB容器服务并没有限制一定要分开。而是任意个数的Enterprise beans可以放在任意个数的容器中,这些容器也可以放在任意个数机器上。并且支持分布式的事务协议,允许Enterprise beans的分别裁定。允许部分的配置你的应用,而将你的性能配置成最优化。Inprise 的EJB是建立在Vbroker和RMI—IIOP之上的。

  EJB容器是建立在Inprise的Vbbroker之上的。VisBroker是已经被证明的在各种条件下都是ORB的领导角色。无论在各大公司的联合测试下,或者在实际的应用环境中。VisiBroker提供了一个很好的的运行时的任务的完成。

  为了更好的性能,Vbroker使用了大量的运行时优化,高级的多路链接,链接池和管理,线程池和管理。

  客户和Enterprise beans,Enterprise benas之间,Enterprise beans 和其它的CORBA对象之间的通信都是通过用VisiBroker的IIOP方式进行的。VisiBroker完全适应CORBA2。3规范,RMI— IIOP通过值传递的方式来实现。这意味着,复杂的JAVA数据类型能够用新的IDL值类型写到IIOP里面去。就象在CORBA2。3规范中一样。数据和服务之间相互协调怎样传送复杂的数据类型是很重要的。否则,协同能力就会受到危及。EJB容器能够与其他的所有支持RMI-over-IIOP的进行协同工作。

  事务上下文也是由visibroker所有的。保证当CORBA客户开始一个事务时,并且访问EJB容器的服务时。事务上下文被传向服务,当服务需要调用环境中的各项资源时,就要使用事务上下文。

  事务的两段提交是由Inprise的ITS管理的。如果JDBC支持两阶段提交协议,EJB就支持两阶段提交协议。当时,如果JDBC不支持两阶段提交,两阶段提交就不能被完成。

  Inprise 的java2iiop编译器和EJB容器一样,都是与CORBA兼容的。EJB容器能够理解RMI调用,但是,它用IDL来存放接口定义。虽然 Java2iiop编译器从java接口产生了stub 和skeleton.也能够从java接口中产生IDL。然后在其他语言里面用。对于一个CORBA客户端,EJB容器是一个CORBA服务,EJB容器工具就是与控制EJB的功能相同的CORBA工具。

  使Inprise 的EJB容器不同的是:它支持许多当前的客户,包括如下两个方面:VisiBroler提供了连接管理,允许一个服务同时支持比TCP连接数多的客户连接。用最近最少使用算法来关闭连接。

  对于客户来说,容器本身是无状态的。意味着容器并没有为每一个新的Enterprise bean会话分配内存。这样,容器就能够支持任意多的无状态的Session Enterprise beans.配置的支持:

  Inprise 容器提供了产生代码的编译器。也提供了一个验证的工具来在配置之前检查你的Enterprise beans.支持EJB1。1的JNDI命名基于XML的配置描述器。

  事务管理者提供了事务管理的手段。包括分布式的两段提交的支持。遵从最新的SUN公司JTS规范。也支持最新的OMG的OTS规范。在开发时尽量少用JTS而在配置时使用健壮的ITS。

  所有JDBC访问数据库都是通过DataSource对象的实现来完成的。DataSource对象与数据库的池链接还有JTS管理的全局的事务处理和用JDBC管理的数据库事务处理。

  命名服务提供了分布式的命名管理。服务遵从JAVA的命名和目录规范(JNDS)。也遵从OMG的cosNaming规范。与事务服务类似,在配置的时候,你可以用JNS,也可以用更健壮的INS。JNDI提供的容器能够运行在其他的JNDI实现之上。这样就能够使用其他的命名服务,例如:LDAP。

  Java数据库提供了一个全关系型的高性能的数据库来存储Enterprise beans的状态。

  JAVA数据库既可以运行在同一个进程的容器中,或者,为了提高性能,也可以运行在一个单独的进程中。实际上,JAVA 数据库是即插即用的。意味着终端用户能够用一个另外的实现就取代了所有的JAVA版本。例如,能够实现一个用别的数据库来存储会话状态和Entiry Data的后台存储。

  Inprise 提供了一个CMP(Container-Managed Persistence)引擎来提供透明的对象关系映射和在纯JDBC上的持续框架。更进一步,第三方的工具可以通过开放的API插进来。

  后端服务:CORBA服务,用C++,Java ,Delphi实现,运行在任何兼容CORBA的ORB中。EJB服务,包括所有其他的inprise的服务,或者其他支持IIOP的代理商的服务。其它原来的服务,包括ERP系统,main-frame程序。等等。


EA视讯

上一篇:Servlet容器和容器到底是什么概念还有EJB能不能举

下一篇:BlogJava