`
longgangbai
  • 浏览: 7234260 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java中的几个问题

阅读更多

1. EJB是以RMI为基础的

          通过RMI技术,J2EE将EJB组件创建为远程对象,EJB虽然用了RMI技术,但是却只需要定义远程接口而无需生成他们的实现类,这样就将RMI技术中的一些细节问题屏蔽了。

但不管怎么说,EJB的基础仍然是RMI,所以,如果你想了解EJB的原理,只要把RMI的原理搞清楚就行了。你也就弄清楚了什么时候用EJB什么时候不需要用EJB了。
         RMI是将各种任务与功能的类放到不同的服务器上,然后通过各个服务器间建立的调用规则实现分布式的运算,也就明白EJB所谓的"服务群集"的概念。

就是将原来在一个计算机上运算的几个类,分别放到其他计算机上去运行,以便分担运行这几个类所需要占用的CPU和内存资源。同时,也可以将不同的软件功能模块放到不同的服务器上,当需要修改某些功能的时候直接修改这些服务器上的类就行了,修改以后所有客户端的软件都被修改了

 2 分布式计算与RPC

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

 

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

 优点

这种机制给分布计算的系统设计、编程都带来了极大的方便。只要按照RMI规则设计程序,可以不必再过问在RMI之下的网络细节了,如:TCP和Socket等等。任意两台计算机之间的通讯完全由RMI负责。调用远程计算机上的对象就像本地对象一样方便。

RMI可将完整的对象作为参数和返回值进行传递,而不仅仅是预定义的数据类型。也就是说,可以将类似Java哈西表这样的复杂类型作为一个参数进行传递。

 缺点

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

JVM使用的是分代垃圾回收的方式,主要是因为在程序运行的时候会有如下特点:

大多数对象在创建后很快就没有对象使用它了。

大多数在一直被使用的对象很少再去引用新创建的对象。

因此就将Java对象分为"年轻"对象和"年老"对象,JVM将内存堆(Heap)分为两个区域,一个是"年轻"区,另一个是"老"区,Java将这两个区域分别称作是"新生代"和"老生代"。

"新生代"区域中,绝大多数新创建的对象都存放在这个区域里,此区域一般来说较小而且垃圾回收频率较高,同时因为"新生代"采用的算法和其存放的对象的特点,使该区域垃圾回收的效率也非常高。

而"老生代"区域中存放的是在"新生代"中生存了较长时间的对象,这些对象将被转移到"老生代"区。这个区域一般要大一些而且增长的速度相对于"新生代"要慢一些,"老生代"垃圾回收的执行频率也会低很多。

由于JVM在垃圾回收处理时会消耗一定的系统资源,因此有时候通过JVM启动的时候添加相关参数来控制"新生代"区域的大小,来调整垃圾回收处理的频率非常有用。以便于我们更合理的利用系统资源。

"新生代"区域设置参数是"-Xmn",用这个参数可以制定"新生代"区域的大小。

我们来举一个例子说明:

我们就用系统自带的程序作为例子,在命令行上键入如下指令:

CD C:\java\demo\jfc\SwingSet2[回车]
C:\java\demo\jfc\SwingSet2>java -jar -verbose:gc
-Xmn4m XX:+PrintGCDetails SwingSet2.jar[回车]
上面加入了一个新的参数"XX:+PrintGCDetails",这个参数能够打印出GC的详细信息。屏幕输出如下(节选):
[GC [DefNew: 3469K->84K(3712K), 0.0007778 secs] 
23035K->19679K(28728K), 0.0009191 secs]
[GC [DefNew: 3284K->171K(3712K), 0.0007283 secs] 
22878K->19766K(28728K), 0.0008669 secs]
[GC [DefNew: 3476K->260K(3712K), 0.0008504 secs] 
23071K->19855K(28728K), 0.0009862 secs]
[GC [DefNew: 3502K->87K(3712K), 0.0009267 secs] 
23096K->19682K(28728K), 0.0010610 secs]

我们需要解释一下输出的详细内容的意思,拿第一行输出来说:

"DefNew: 3469K->84K(3712K), 0.0007778 secs"是指"新生代"的垃圾回收情况,这里的意思是从占用3469K内存空间变为84K内存空间,用时0.0007778秒。

"23035K->19679K(28728K), 0.0009191 secs"是指总体GC的回收情况,整体堆空间占用从23035K降低到19679K的水平,用时0.0009191秒。

那么,这时候我们在将"新生代"的内存设为8M,并把堆的最大可控值设定为32M,再去执行,键入如下指令:

java -jar -verbose:gc -Xmn8m -Xmx32m 
XX:+PrintGCDetails SwingSet2.jar[回车]
得到的结果如下(节选):
[GC [DefNew: 6633K->6633K(7424K), 0.0000684 secs]
[Tenured: 18740K->18820K(24576K), 0.0636505 secs] 
25374K->18820K(32000K), 0.0639274 secs]
[GC [DefNew: 6646K->6646K(7424K), 0.0002581 secs]
[Tenured: 18820K->18884K(24576K), 0.0651957 secs] 
25467K->18884K(32000K), 0.0658804 secs]
[GC [DefNew: 6611K->6611K(7424K), 0.0000668 secs]
[Tenured: 18884K->18505K(24576K), 0.0931406 secs] 
25496K->18505K(32000K), 0.0934295 secs]

这个结果说明:

"[DefNew: 6633K->6633K(7424K), 0.0000684 secs]"是指"新生代"的垃圾回收情况,这里的意思是从占用6633K内存空间变为6633K内存空间,用时0. 0000684秒。
"25374K->18820K(32000K), 0.0639274 secs"是指总体GC的回收情况,整体堆空间占用从25374K降低到18820K的水平,用时0. 0639274秒。
"[Tenured: 18740K->18820K(24576K), 0.0636505 secs]"是指"老生代"GC的回收情况,整体堆空间占用从18740K降低到18820K的水平,用时0.0009012秒。

通过这些参数的调整我们可以看到在处理垃圾收集问题时,从垃圾回收的频率是时间方面的变化,我们可以根据不同程序的不同情况予以调整。

最后有必要提一下GC的相关参数:

-XX:+PrintGCDetails 显示GC的详细信息
-XX:+PrintGCApplicationConcurrentTime 打印应用执行的时间
-XX:+PrintGCApplicationStoppedTime 打印应用被暂停的时间
注:":"后的"+"号表示开启此选项,如果是"-"号那么表示关闭此选项。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics