- 浏览: 103482 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
chifanbua:
我基本上在iteye上很少留言的 不过你的这个写的确实不错 用 ...
Oracle decode函数说明 -
shaoxuexue86:
谢谢啊
RMI 开发步骤 -
huxiaojun_198213:
RMIRegistHelper只是负责注册远程对象,与客户端所 ...
RMI 开发步骤 -
shaoxuexue86:
请问客户端程序ClientTest 与 RMIRegistHe ...
RMI 开发步骤 -
huxiaojun_198213:
本章节可能有一些细节方面翻译得不是很好,有出入的地方,还请各 ...
RMI动态类加载
RMI运行时环境在客户端和服务端都扮演了重要的角色.在这种架构中,stub达到了三种目的:
1.它是序列化的,通过网络可以从服务端向客户端发送.也可以包含数据使其可以稳定地向服务端发送消息.
2.它是服务端的代理,客户端可以把stub当作是服务器.
3.它可以池化socket.每次方法调用的时候,stub就向RMI运行时请求一个特别服务的连接.这使得RMI可以在多个请求之间重用sockets(即可以共享socket).
在多个请求之间重用socket,可能会导致下面的问题:
如果一个socket被多个客户端的stubs重用,它们每一个都向不同的服务器发送了消息,那么这些消息之间应该有某种意义上的区别.那么应该如何来区分呢?
在RMI中,这种区分是通过使用java.rmi.server包下的ObjID类来进行的.
ObjID在javadoc中是这样定义的:
ObjID被唯一用来标识远程对象.每一个标识符都包含一个对象数(类型为long)和一个地址空间标识符(类型为UID,对于特定主机是唯一的).
对象标识符是在远程对象被导出时分配的.如果java.rmi.server.randomIDs属性设置为true的话,通过无参构造函数创建的ObjID对象的64位对象树将包含一个加密的强随机数.
因此,ObjID的实例可以唯一地标识服务器JVM中的特定服务.同时,ObjID类实现了序列化接口,因此,在每个远程方法调用时,其实例都可以被序列化.
在服务端,RMI运行时使用ObjID的反序列化来找出远程方法调用将要调用的skeleton.
RMI是怎样解决引导问题的?
大部分服务器在过去的使用中都是通过随机分配ObjID的实例来处理的.在其实例中有三种保留的标识符:ACTIVATOR_ID(),DGC_ID和REGISTRY_ID.
这三种IDs分别对应RMI提供的三种服务:激活构架,分布式垃圾收集和RMI注册表.
为了能够完全解决引导问题,RMI注册表需要预知的一个唯一标识符.
当一个客户端第一次试图连接RMI注册表的时候,除非它知道与服务器相关的对象标识符,否则此客户端就不能向服务器端发送消息.
也就是说,因为服务器端的RMI运行时需要一个ObjID的实例来决定使用哪个合适的服务器来响应客户端的请求,客户端为了能连接注册表,它必须要知道运行在服务器JVM中注册表的ObjID.
为了解决这个问题,RMI的设计者们定义了ObjID的保留实例-如果一个注册表运行在一个虚拟机中,它就使用REGISTRY_ID.否则,不允许任何服务器使用REGISTRY_ID.
这解决了RMI引导问题.Naming的静态方法接受一个主机和端口;构建stub时仅需的附加信息是stub连接服务器的Object ID.
由于注册表总是使用REGISTRY_ID,注册表的stub在连接注册表之前总是能在客户端被完全地构建.
这种策略也意味着,一个JVM只能导出一个注册表,这是因为不能在多个服务器间共享ObjID.
分布式垃圾收集
另一个固定的标识符是DGC_ID.这是内置于RMI中的关于分布式垃圾收集的对象标识符.
垃圾收集的基本想法是定义一系列的可到达对象,并丢弃那么不可达对象.可达对象是递归定义的:
1.每个活动线程当前都处在一个方法中或处在未知对象的实例中.那么线程所在的实例就是可到达的.
2.每个线程能够立即找到被方法级变量和实例字段引用的对象,这些对象也是可到达的.
3.从这些立即可访问的对象(此对象引用了其他对象),能够访问到其他可到达的对象.
诸如此类,一般来说,如果一个线程,从它当前位置开始,能够最终找到某个对象,那么此对象就是可达的.
在单个JVM中垃圾收集机制工作得很好.但在分布式系统中,stub问题将会出现.如果一个客户端拥有一个服务器端的引用 ,那么服务器应该是可到达的.
由于所有的stub真正拥有的是一个ObjId的实例,这意味着RMI运行时必须保持所有活动服务器的引用.为了垃圾回收,客户端的RMI运行时必须以某种方法让服务端运行时知道stub何时不再被使用.
最明显的方式是使用分布式引用计数.也就是,强制客户端stub发送两条额外的信息给服务器.
当stub被实例化发送一条消息,以便让服务器知道有一个活动的客户端(计数器加1).当stub释放的时候,再发送一条消息,以通知服务器客户端已经使用完了服务端(计数器减1).
在这种方案中,最脆弱的是第一步.下面的每一个问题都可能增加计数的困难度:
1.客户端垃圾收集算法不能保证立即回收stub.如果客户端的内存充裕,且正忙于处理具有高优先级的任务,那么垃圾收集暂时可能不会发生.在这段时期之内,客户端将隐含地强制服务端保持那些没有必要的资源.
2.客户端可能会崩溃(crash).假设一个客户端崩溃了的话,那么第二条消息将无法发送,这样就会导致服务端引用计数无法变为0,且RMI运行时将永远保持服务对象为活动状态.
3.可能会出现网络问题.即使客户端是好的,且能发送消息,但网络问题也可能出现.在这种情况下, RMI运行时决不将服务端引用减为0,这样就导致了服务端对象一直处于活动状态.
在这三个问题中,第一个问题是不可能解决的.Java语言规范明确的表明本地垃圾收集是不可依赖的.垃圾收集将来可能发生,但没有一种方式来强制它在某一时间段内发生.
在垃圾收集运行之前,没有一种方法知道一个stub变成了不可引用,因此任何一个分布式引用计数架构将不得不接受第一问题的现实.
第二和第三个问题可以通过将所有分布式引用作为临时引用来消除.其基本思想被称为租赁.基本算法如下:
1.客户端调用服务器并请求一段时间的租期.
2.服务端响应,并同意一段时间的租期(不一定与客户端请求的租期相同)
3.在这段时间之内,分布式引用计数将包含客户端(即增加计数1)
4.当租期期满的时候,如果客户端请求没有延长期限的话,则分布式应用计数将会自动减少(即减少计数1).
只要stub没有被垃圾回收的话,客户端就会自动尝试续期租赁.通过这种算法,可以灵巧地解决第二,第三个问题.
如果客户端崩溃了的话,即客户端就不再运行了,那么客户端就不能再续期租赁,结果就会导致服务器最终将其回收掉.
相似地,如果因网络问题阻止了客户端程序连接服务器,客户端也不会续期到租赁,因此服务端最终也会对其进行垃圾回收.
默认地租期为10分钟,可以通过java.rmi.dgc.leaseValue属性进行设置,时间单位为毫秒.
真实的分布式垃圾收集器
分布式垃圾收集器是一个RMI服务器程序,它实现java.rmi.dgc.DGC接口(此接口继承自java.rmi.Remote接口).此接口只包含两个方法声明:
public void clean(ObjID[] ids,long sequenceNum,VMID vmid,boolean strong)
public Lease dirty(ObjID[] ids,long sequenceNum,Lease lease)
clean()方法是由客户端在不需要服务端引用的时候,由它的运行时调用的.严格来讲,调用clean()方法是没有必要的-客户端运行时可能不续期租赁而达到相同的目的.
但是,租赁应该看作是服务器清理机制的最后一道防线(通过它可以在适当的位置减少网络和客户端失败造成的损害).
客户端运行时可以通过调用dirty()方法来获得一个租赁.不需要直接传递一个VMID(虚拟机ID,即一个JVM的唯一标识符)给dirty()方法,因Lease的实例已经传递了VMID(通过其构造函数可以看出).
注意:对于一个特定的JVM来说,它只能有一个分布式垃圾回收器,其对象标识符为DGC_ID.
Unreferecnced接口
分布式垃圾回收器负责维持租赁.在服务器端,当特定服务器的所有未解决租赁过期的时候,分布式垃圾回收器确保RMI运行时不再保留服务端引用.
因此服务端就可以被回收.在此处理过程中,如果服务端(远程对象)实现了Unreferenced接口,那么服务端在没有多个引用该对象的客户机时接收通知.Unreferenced接口只包含一个方法:
public void unreferenced()
当服务器需要立即释放资源而不是等待垃圾回收发生时,此接口非常重要.同时,它也是一个持久化代码的便利钩子-因为服务端知道不再有远程方法调用,所以它能将状态安全地存储到一个持久化介质(如,一个关系型数据库).
RMI日志
除了分布式垃圾回收之外,RMI运行时也包含广泛的日志,这些日志可以让你跟踪应用程序的行为.RMI中有三种不同的日志类型:标准日志,专门日志(包含5种类型),调试日志
标准日志
标准日志用于在服务端记录方法调用和异常信息.标准日志的使用是很容易的,可以通过设置java.rmi.server.logCalls系统属性(值为boolean类型)来启用或关闭.此属性可通过命令行或程序进行设置.如:
命令行:
程序:
一旦你启用了日志,你可以配置日志的输出目的地.可以通使用java.rmi.server.RemoteServer类的静态方法进行设置:
public static PrintStream getLog()
用于获取当前的日志的流
public static void setLog(OutputStream out)
设置日志的输出流.
缺省情况下,日志系统使用System.err.也就是说,如果你没有设置标准日志输出目的地的话,它将会在System.err上显示.
专门日志
RMI有五种类型的专门日志用于记录运行时的特定方面.这些日志是transport log(传输日志),proxy log(代理日志),loader log(负载日志),DGC log(分布式垃圾回收日志)以及TCP log(tcp日志).
它们均为java.rmi.server.LogStream(此类从JDK1.3版本时已经被废弃)的实例.为了得到与日志相关的LogStream,可以调用其静态方法:public static LogStream log(String name).
一旦你有了LogStream的实例,就可以使用其 setOutputStream()来设置其输出目的地.如:
这些日志通过6个系统属性来操作,每一个属性都接受三个设置:silent(不记录信息),brief(记录少量信息),verbose(记录大量信息),可以使用s,b,v是上述三个值的简写形式.
此6个属性如下:(以下属性因为已被废弃,且属sun公司专有属性,具体含义可查看参考资料)
sun.rmi.server.dgcLevel
sun.rmi.server.logLevel
sun.rmi.loader.logLevel
sun.rmi.transport.logLevel
sun.rmi.transport.tcp.logLevel
sun.rmi.transport.proxy.logLevel
调试日志
同标准日志一样,可以通过设置系统属性sun.rmi.log.debug的boolean值来开启或禁用此功能.但不同于标准日志的是,调试日志总是将信息显示在System.err上.调试日志被用于激活框架的守护线程中.
基本RMI参数
java.rmi.server.randomIDS
其属性值为boolean型.当设置为true时,它强制RMI运行时为新导出的服务对象生成加密的安全对象标识.默认为false.
sun.rmi.server.exceptionTrace
其属性值为boolean型.当其设为true的时候(默认为false),所有的异常将会被打印到System.err上.反之,则不打印.
传输层参数
传输层是底层参数,它能够直接影响RMI底层的sokets的使用和TCP/IP的配置.有三个传输层参数:
sun.rmi.transport.connectionTimeout
用于设置在RMI关闭之前,socket的休眠时间.默认为15秒,在较慢的网络中,应该加大此值。
必须在客户端和服务器端同时设定此值,因为两端都试图重用同一个socket.如果服务端设为60秒的话,客户端设为15秒的话,那么实际上服务端设置的参数将会被客户端参数所否决。
sun.rmi.transport.tcp.readTimeout
设置底层socket读取超时时间,此参数的值实际上只能通过直接传递给socket的方式进行设值(通过socket的setSoTimeOut()).此参数的默认值为2个小时(7200,000毫秒)。
sun.rmi.transport.proxy.connectTimeout
用于设置在两个JVM建立连接时RMI等待的时间。默认为15秒。
注:上述参数的值单位均为毫秒
影响垃圾回收的参数
java.rmi.dgc.leaseValue
此参数只影响服务端,它被用来设置标准的租赁时间。时间单位为毫秒,默认为10分钟。
sun.rmi.dgc.client.gcInterval
此参数用于配置客户端运行时行为。即RMI检测stub是否活动的时间周期。当stub不再被引用的时候,客户端运行时就会发送一个clean()消息给服务端运行时。单位为毫秒,默认为1分钟。
sun.rmi.dgc.server.gcInterval
服务端对于分布式垃圾回收的刷新频率。此参数用于控制检查客户端clean()的动作频率,并试图决定是否调用unreferenced()方法。此值单位为毫秒,缺省为1分钟。
sun.rmi.dgc.checkInterval
用于指定RMI检查过期租赁的频率。此值单位为毫秒,缺省为5分钟。
sun.rmi.dgc.cleanInterval
此参数是客户端的重试参数。当客户端调用clean()时,如果操作失败(如,网络问题),此参数将设定重新调用clean()时,客户端应该等待的时间。此值单位为毫秒,缺省为3分钟。
参考资料
1.O’Reilly <<Java RMI>> Chapter 16.The RMI Runtime
2.Java RMI 规范
1.它是序列化的,通过网络可以从服务端向客户端发送.也可以包含数据使其可以稳定地向服务端发送消息.
2.它是服务端的代理,客户端可以把stub当作是服务器.
3.它可以池化socket.每次方法调用的时候,stub就向RMI运行时请求一个特别服务的连接.这使得RMI可以在多个请求之间重用sockets(即可以共享socket).
在多个请求之间重用socket,可能会导致下面的问题:
如果一个socket被多个客户端的stubs重用,它们每一个都向不同的服务器发送了消息,那么这些消息之间应该有某种意义上的区别.那么应该如何来区分呢?
在RMI中,这种区分是通过使用java.rmi.server包下的ObjID类来进行的.
ObjID在javadoc中是这样定义的:
ObjID被唯一用来标识远程对象.每一个标识符都包含一个对象数(类型为long)和一个地址空间标识符(类型为UID,对于特定主机是唯一的).
对象标识符是在远程对象被导出时分配的.如果java.rmi.server.randomIDs属性设置为true的话,通过无参构造函数创建的ObjID对象的64位对象树将包含一个加密的强随机数.
因此,ObjID的实例可以唯一地标识服务器JVM中的特定服务.同时,ObjID类实现了序列化接口,因此,在每个远程方法调用时,其实例都可以被序列化.
在服务端,RMI运行时使用ObjID的反序列化来找出远程方法调用将要调用的skeleton.
RMI是怎样解决引导问题的?
大部分服务器在过去的使用中都是通过随机分配ObjID的实例来处理的.在其实例中有三种保留的标识符:ACTIVATOR_ID(),DGC_ID和REGISTRY_ID.
这三种IDs分别对应RMI提供的三种服务:激活构架,分布式垃圾收集和RMI注册表.
为了能够完全解决引导问题,RMI注册表需要预知的一个唯一标识符.
当一个客户端第一次试图连接RMI注册表的时候,除非它知道与服务器相关的对象标识符,否则此客户端就不能向服务器端发送消息.
也就是说,因为服务器端的RMI运行时需要一个ObjID的实例来决定使用哪个合适的服务器来响应客户端的请求,客户端为了能连接注册表,它必须要知道运行在服务器JVM中注册表的ObjID.
为了解决这个问题,RMI的设计者们定义了ObjID的保留实例-如果一个注册表运行在一个虚拟机中,它就使用REGISTRY_ID.否则,不允许任何服务器使用REGISTRY_ID.
这解决了RMI引导问题.Naming的静态方法接受一个主机和端口;构建stub时仅需的附加信息是stub连接服务器的Object ID.
由于注册表总是使用REGISTRY_ID,注册表的stub在连接注册表之前总是能在客户端被完全地构建.
这种策略也意味着,一个JVM只能导出一个注册表,这是因为不能在多个服务器间共享ObjID.
分布式垃圾收集
另一个固定的标识符是DGC_ID.这是内置于RMI中的关于分布式垃圾收集的对象标识符.
垃圾收集的基本想法是定义一系列的可到达对象,并丢弃那么不可达对象.可达对象是递归定义的:
1.每个活动线程当前都处在一个方法中或处在未知对象的实例中.那么线程所在的实例就是可到达的.
2.每个线程能够立即找到被方法级变量和实例字段引用的对象,这些对象也是可到达的.
3.从这些立即可访问的对象(此对象引用了其他对象),能够访问到其他可到达的对象.
诸如此类,一般来说,如果一个线程,从它当前位置开始,能够最终找到某个对象,那么此对象就是可达的.
在单个JVM中垃圾收集机制工作得很好.但在分布式系统中,stub问题将会出现.如果一个客户端拥有一个服务器端的引用 ,那么服务器应该是可到达的.
由于所有的stub真正拥有的是一个ObjId的实例,这意味着RMI运行时必须保持所有活动服务器的引用.为了垃圾回收,客户端的RMI运行时必须以某种方法让服务端运行时知道stub何时不再被使用.
最明显的方式是使用分布式引用计数.也就是,强制客户端stub发送两条额外的信息给服务器.
当stub被实例化发送一条消息,以便让服务器知道有一个活动的客户端(计数器加1).当stub释放的时候,再发送一条消息,以通知服务器客户端已经使用完了服务端(计数器减1).
在这种方案中,最脆弱的是第一步.下面的每一个问题都可能增加计数的困难度:
1.客户端垃圾收集算法不能保证立即回收stub.如果客户端的内存充裕,且正忙于处理具有高优先级的任务,那么垃圾收集暂时可能不会发生.在这段时期之内,客户端将隐含地强制服务端保持那些没有必要的资源.
2.客户端可能会崩溃(crash).假设一个客户端崩溃了的话,那么第二条消息将无法发送,这样就会导致服务端引用计数无法变为0,且RMI运行时将永远保持服务对象为活动状态.
3.可能会出现网络问题.即使客户端是好的,且能发送消息,但网络问题也可能出现.在这种情况下, RMI运行时决不将服务端引用减为0,这样就导致了服务端对象一直处于活动状态.
在这三个问题中,第一个问题是不可能解决的.Java语言规范明确的表明本地垃圾收集是不可依赖的.垃圾收集将来可能发生,但没有一种方式来强制它在某一时间段内发生.
在垃圾收集运行之前,没有一种方法知道一个stub变成了不可引用,因此任何一个分布式引用计数架构将不得不接受第一问题的现实.
第二和第三个问题可以通过将所有分布式引用作为临时引用来消除.其基本思想被称为租赁.基本算法如下:
1.客户端调用服务器并请求一段时间的租期.
2.服务端响应,并同意一段时间的租期(不一定与客户端请求的租期相同)
3.在这段时间之内,分布式引用计数将包含客户端(即增加计数1)
4.当租期期满的时候,如果客户端请求没有延长期限的话,则分布式应用计数将会自动减少(即减少计数1).
只要stub没有被垃圾回收的话,客户端就会自动尝试续期租赁.通过这种算法,可以灵巧地解决第二,第三个问题.
如果客户端崩溃了的话,即客户端就不再运行了,那么客户端就不能再续期租赁,结果就会导致服务器最终将其回收掉.
相似地,如果因网络问题阻止了客户端程序连接服务器,客户端也不会续期到租赁,因此服务端最终也会对其进行垃圾回收.
默认地租期为10分钟,可以通过java.rmi.dgc.leaseValue属性进行设置,时间单位为毫秒.
真实的分布式垃圾收集器
分布式垃圾收集器是一个RMI服务器程序,它实现java.rmi.dgc.DGC接口(此接口继承自java.rmi.Remote接口).此接口只包含两个方法声明:
public void clean(ObjID[] ids,long sequenceNum,VMID vmid,boolean strong)
public Lease dirty(ObjID[] ids,long sequenceNum,Lease lease)
clean()方法是由客户端在不需要服务端引用的时候,由它的运行时调用的.严格来讲,调用clean()方法是没有必要的-客户端运行时可能不续期租赁而达到相同的目的.
但是,租赁应该看作是服务器清理机制的最后一道防线(通过它可以在适当的位置减少网络和客户端失败造成的损害).
客户端运行时可以通过调用dirty()方法来获得一个租赁.不需要直接传递一个VMID(虚拟机ID,即一个JVM的唯一标识符)给dirty()方法,因Lease的实例已经传递了VMID(通过其构造函数可以看出).
注意:对于一个特定的JVM来说,它只能有一个分布式垃圾回收器,其对象标识符为DGC_ID.
Unreferecnced接口
分布式垃圾回收器负责维持租赁.在服务器端,当特定服务器的所有未解决租赁过期的时候,分布式垃圾回收器确保RMI运行时不再保留服务端引用.
因此服务端就可以被回收.在此处理过程中,如果服务端(远程对象)实现了Unreferenced接口,那么服务端在没有多个引用该对象的客户机时接收通知.Unreferenced接口只包含一个方法:
public void unreferenced()
当服务器需要立即释放资源而不是等待垃圾回收发生时,此接口非常重要.同时,它也是一个持久化代码的便利钩子-因为服务端知道不再有远程方法调用,所以它能将状态安全地存储到一个持久化介质(如,一个关系型数据库).
RMI日志
除了分布式垃圾回收之外,RMI运行时也包含广泛的日志,这些日志可以让你跟踪应用程序的行为.RMI中有三种不同的日志类型:标准日志,专门日志(包含5种类型),调试日志
标准日志
标准日志用于在服务端记录方法调用和异常信息.标准日志的使用是很容易的,可以通过设置java.rmi.server.logCalls系统属性(值为boolean类型)来启用或关闭.此属性可通过命令行或程序进行设置.如:
命令行:
Java -Djava.rmi.server.logCalls=true
程序:
System.getProperties().put("java.rmi.server.logCalls","true");
一旦你启用了日志,你可以配置日志的输出目的地.可以通使用java.rmi.server.RemoteServer类的静态方法进行设置:
public static PrintStream getLog()
用于获取当前的日志的流
public static void setLog(OutputStream out)
设置日志的输出流.
缺省情况下,日志系统使用System.err.也就是说,如果你没有设置标准日志输出目的地的话,它将会在System.err上显示.
专门日志
RMI有五种类型的专门日志用于记录运行时的特定方面.这些日志是transport log(传输日志),proxy log(代理日志),loader log(负载日志),DGC log(分布式垃圾回收日志)以及TCP log(tcp日志).
它们均为java.rmi.server.LogStream(此类从JDK1.3版本时已经被废弃)的实例.为了得到与日志相关的LogStream,可以调用其静态方法:public static LogStream log(String name).
一旦你有了LogStream的实例,就可以使用其 setOutputStream()来设置其输出目的地.如:
FileOutputStream transportLogFile = new FileOutputStream("d:/log/transportFlogFile"); LogStream.log("transport").setOutputStream(transportLogFile):
这些日志通过6个系统属性来操作,每一个属性都接受三个设置:silent(不记录信息),brief(记录少量信息),verbose(记录大量信息),可以使用s,b,v是上述三个值的简写形式.
此6个属性如下:(以下属性因为已被废弃,且属sun公司专有属性,具体含义可查看参考资料)
sun.rmi.server.dgcLevel
sun.rmi.server.logLevel
sun.rmi.loader.logLevel
sun.rmi.transport.logLevel
sun.rmi.transport.tcp.logLevel
sun.rmi.transport.proxy.logLevel
调试日志
同标准日志一样,可以通过设置系统属性sun.rmi.log.debug的boolean值来开启或禁用此功能.但不同于标准日志的是,调试日志总是将信息显示在System.err上.调试日志被用于激活框架的守护线程中.
基本RMI参数
java.rmi.server.randomIDS
其属性值为boolean型.当设置为true时,它强制RMI运行时为新导出的服务对象生成加密的安全对象标识.默认为false.
sun.rmi.server.exceptionTrace
其属性值为boolean型.当其设为true的时候(默认为false),所有的异常将会被打印到System.err上.反之,则不打印.
传输层参数
传输层是底层参数,它能够直接影响RMI底层的sokets的使用和TCP/IP的配置.有三个传输层参数:
sun.rmi.transport.connectionTimeout
用于设置在RMI关闭之前,socket的休眠时间.默认为15秒,在较慢的网络中,应该加大此值。
必须在客户端和服务器端同时设定此值,因为两端都试图重用同一个socket.如果服务端设为60秒的话,客户端设为15秒的话,那么实际上服务端设置的参数将会被客户端参数所否决。
sun.rmi.transport.tcp.readTimeout
设置底层socket读取超时时间,此参数的值实际上只能通过直接传递给socket的方式进行设值(通过socket的setSoTimeOut()).此参数的默认值为2个小时(7200,000毫秒)。
sun.rmi.transport.proxy.connectTimeout
用于设置在两个JVM建立连接时RMI等待的时间。默认为15秒。
注:上述参数的值单位均为毫秒
影响垃圾回收的参数
java.rmi.dgc.leaseValue
此参数只影响服务端,它被用来设置标准的租赁时间。时间单位为毫秒,默认为10分钟。
sun.rmi.dgc.client.gcInterval
此参数用于配置客户端运行时行为。即RMI检测stub是否活动的时间周期。当stub不再被引用的时候,客户端运行时就会发送一个clean()消息给服务端运行时。单位为毫秒,默认为1分钟。
sun.rmi.dgc.server.gcInterval
服务端对于分布式垃圾回收的刷新频率。此参数用于控制检查客户端clean()的动作频率,并试图决定是否调用unreferenced()方法。此值单位为毫秒,缺省为1分钟。
sun.rmi.dgc.checkInterval
用于指定RMI检查过期租赁的频率。此值单位为毫秒,缺省为5分钟。
sun.rmi.dgc.cleanInterval
此参数是客户端的重试参数。当客户端调用clean()时,如果操作失败(如,网络问题),此参数将设定重新调用clean()时,客户端应该等待的时间。此值单位为毫秒,缺省为3分钟。
参考资料
1.O’Reilly <<Java RMI>> Chapter 16.The RMI Runtime
2.Java RMI 规范
发表评论
-
RMI中的安全策略
2012-07-13 15:58 3564以下翻译来自Java RMI的Ch ... -
RMI动态类加载
2012-07-13 15:14 1508以下翻译自Java RMI的Chapter 19.Dynami ... -
RMI中的属性说明
2012-07-03 18:06 1370服务端属性 下面的表 ... -
O'reilly<<Java RMI>> 第18章:使用定制Socket (翻译)
2012-06-30 16:15 1530以下翻译来自:o'reilly ... -
RMI规范--第一章
2012-06-29 10:52 919原文网址: http://docs.or ... -
RMI规范--第十章
2012-06-29 10:50 757RMI 通信协议 10.1 概述 ... -
RMI规范--第九章
2012-06-29 10:29 843本章中的接口和类用于 ... -
RMI规范--第八章
2012-06-29 10:13 610本章包含 rmic stub 编译 ... -
RMI规范--第七章
2012-06-29 09:38 863远程对象激活 主题: 概述 激活协议 “可激活 ... -
RMI规范--第六章
2012-06-28 00:17 900注册服务程序接口 RMI 系统使用 java.rmi.re ... -
RMI规范--第五章
2012-06-28 00:16 904服务器接口 java.rmi.server 包包含通常用于 ... -
RMI规范--第四章
2012-06-28 00:15 838客户机接口 程序员在编写使用远程对象的 applet 或应 ... -
RMI规范--第三章
2012-06-28 00:14 800主题: Stub 与 skeleton ... -
RMI规范--第二章
2012-06-28 00:13 977Java 分布式对象模型 2.1 分布式对象应用程序 ... -
J2SE1.6 RMI官方指南翻译四
2012-06-27 18:20 1015Compiling and Running the Examp ... -
J2SE1.6 RMI官方指南翻译三
2012-06-27 18:16 825Creating a Client Program The c ... -
J2SE1.6 RMI官方指南翻译二
2012-06-27 18:13 1108Implementing a Remote Interface ... -
J2SE1.6 RMI官方指南翻译一
2012-06-27 16:37 880最近在学习分布式 ... -
RMI 开发步骤
2012-06-25 18:36 1425开发RMI步骤: 1.编写服务接口,此接口须直接或间接继承至R ... -
JDK1.6 rmic命令使用
2012-06-25 18:24 1459rmic称为rmi编译命令,用于生成rmi远程实现类的stub ...
相关推荐
- 启动和运行的说明文档 通过分析这些文件,你可以学习到如何创建、配置和运行一个完整的RMI应用程序,这对于理解和应用Java的分布式计算能力非常有帮助。同时,这也是一个很好的实践项目,可以帮助你加深对RMI工作...
如果远程对象需要在运行时根据需要创建,可以使用激活框架。 6. **安全性**:RMI支持标准的Java安全模型,可以控制客户端对远程对象的访问权限。通过策略文件,可以设定远程方法调用的安全策略。 7. **异常处理**...
- **动态导出和导入**:服务器可以在运行时动态地导出或导入远程对象,提供更大的灵活性。 学习和理解Java RMI对于开发分布式Java应用至关重要,它可以帮助你构建可扩展、高性能的应用程序,尤其适用于服务器集群和...
6. **说明.txt**:这个文件可能包含了项目运行的步骤、配置信息或者使用说明,对于理解和运行此项目至关重要。 7. **www.pudn.com.txt**:这可能是一个链接或引用源文件的文本,表明项目是从pudn.com这样的资源分享...
- **运行指南**:提供如何编译、运行服务器和客户端的说明,帮助初学者理解RMI的工作流程。 学习这个RMI实例,你需要了解以下步骤: 1. **创建远程接口**:定义一个继承自Remote的接口,声明要进行远程调用的方法...
7. **readMe.txt**: 通常包含项目的简要说明,如如何构建和运行程序,以及任何特定的注意事项或指导。 在实际开发中,RMI适用于那些需要跨越网络边界,但又希望像本地调用一样简单、透明的场景。然而,RMI也有其...
6. **部署和运行**:使用RMI时,需要将远程对象导出(`java.rmi.Naming.rebind()`),然后客户端可以通过`java.rmi.Naming.lookup()`查找并调用远程对象。在实际应用中,还需要配置JVM的RMI端口和其他网络参数。 在...
RMI是Java中的一种机制,允许一个Java对象调用另一个在网络中不同 JVM(Java虚拟机)上运行的对象的方法。RMI-IIOP则是在RMI的基础上添加了对CORBA IIOP协议的支持,使得Java对象可以透明地与非Java的CORBA对象进行...
在提供的文件列表中,"RMI规范说明X.txt"很可能是RMI规范的详细文档,涵盖了RMI的各个方面,包括如何创建和部署远程对象,以及如何处理异常和优化性能。"www.pudn.com.txt"可能是下载资源的来源信息。 学习和理解...
7. **异常处理**:RMI调用可能会遇到各种网络和运行时异常,例如`java.rmi.RemoteException`,因此在调用远程方法时应进行适当的异常处理。 通过“rmi.rar”中的源代码,你可以学习如何定义和实现远程接口,创建和...
5. **编写一次,到处运行**:遵循Java的哲学,“编写一次,到处运行”,RMI确保了应用的可移植性和兼容性。 6. **分布式垃圾收集**:RMI具备分布式垃圾收集机制,能够自动回收不再被任何客户端引用的远程服务对象,...
RMI(Remote Method Invocation,远程方法调用)是Java中的一种技术,用于构建分布式系统,使得在一台机器上的对象能够调用另一台机器上对象的方法,就像它们在同一个进程中一样。RMI使得开发者可以创建跨网络的、...
2. **客户端代码**:说明了如何查找并调用远程对象,可能包括异常处理,如`java.rmi.ConnectException` 和 `NotBoundException`。 3. **配置文件**:如`server.properties` 或 `client.properties`,可能包含了RMI...
它允许Java对象在不同的Java虚拟机(JVM)之间进行交互,仿佛它们都在同一台机器上运行。这个"java_in_rmi.rar"压缩包包含了学习和精通RMI的基础资料,非常适合初学者深入理解这一主题。 首先,RMI的核心概念是远程...
具体到实验文件"rmi",这可能是RMI相关代码或者教程的集合,可能包含了服务器端和客户端的示例代码,以及如何在Java中设置和运行RMI服务的说明。"cs"可能代表"Client-Server",也就是客户端-服务器相关的文件,可能...
RMI在企业级应用中,尤其是在构建大型分布式系统时,有着广泛的应用,如EJB(Enterprise JavaBeans)中的远程bean就是基于RMI实现的。因此,掌握RMI对于提升你的Java编程技能和理解分布式系统的设计至关重要。
- `Classes`:编译后的class文件,用于运行RMI服务器和客户端。 通过学习和使用这个通用的JAVA RMI服务器框架,开发者可以更快地搭建分布式应用,减少重复工作,并提高系统的可扩展性和可靠性。同时,深入理解RMI的...
文件列表中的“程序说明.doc”可能是对整个RMI实现的详细说明,包括代码示例和步骤解释。而“RMILab”可能是一个包含实验代码的文件夹,可能包含了服务器端和客户端的Java源代码,以及运行和测试RMI应用程序所需的...
RMI规范说明中的多个文件可能涵盖了RMI的详细配置、性能优化、故障排查、以及与其他Java技术如EJB、CORBA的集成等内容。通过深入学习这些文档,开发者可以更好地理解RMI的工作原理,从而在实际项目中有效地利用这一...
`www.pudn.com.txt`文件可能是项目介绍或者示例代码的说明文档,提供了更多关于如何运行和理解代码的上下文信息。 在实际应用中,RMI被广泛用于构建分布式系统,如分布式数据库、负载均衡服务、分布式缓存等。虽然...