📄 rmi
字号:
UnicastRef2,该端点的线表示则包括一个格式字节,用来指定端点表示的其余
内容(允许将来扩充),后跟的是指定格式的数据。当前,这些数据可包含
UTF 格式的主机名、端口号及可选的(由端点格式字节指定)
RMIClientSocketFactory 对象序列化表示。它可被客户机用于在该端点生成
到远程对象的套接字连接。端点表示不包括在远程对象导出时指定的
RMIServerSocketFactory 对象。
当通过 UnicastRef2 类型的引用进行调用时,运行时将在创建远程对象的套
接字连接时使用端点中 RMIClientSocketFactory 对象的 createSocket 方
法。同样,当运行时为了特定远程对象进行 DGC "dirty" 和 "clean" 调用
时,它必须在远程虚拟机上调用 DGC,方法是使用远程引用中指定的同一
RMIClientSocketFactory 对象所生成的连接。服务器端的 DGC 实现应负责
验证结果是否正确。
如果远程对象是由老的构造函数或 UnicastRemoteObject 中没有将自定义套
接字工厂作为参数的方法导出,则和以前一样拥有 UnicastRef 和
UnicastServerRef 类型的 RemoteRef 和 ServerRef,并且其端点也将使用
老式线表示,即一个 UTF 格式的主机字符串跟一个指定端口号的整数。这样那
些不使用 JDK 1.2 新特性的 RMI 服务器可以与老式 RMI 客户机进行互操作。
5.8.1 RMISocketFactory 类
java.rmi.server.RMISocketFactory 抽象类提供一个接口来指定传输中如何
获得套接字。注意,下面的类使用 java.net 包中的 Socket 和 ServerSocket。
package java.rmi.server;
public abstract class RMISocketFactory
implements RMIClientSocketFactory, RMIServerSocketFactory
{
public abstract Socket createSocket(String host, int port)
throws IOException;
public abstract ServerSocket createServerSocket(int port)
throws IOException;
public static void setSocketFactory(RMISocketFactory fac)
throws IOException;
public static RMISocketFactory getSocketFactory();
public static void setFailureHandler(RMIFailureHandler fh);
public static RMIFailureHandler getFailureHandler();
}
静态方法 setSocketFactory 可用于设置套接字工厂,而 RMI 将从中获得套接字
。应用程序用自己的实例 RMISocketFactory 仅能调用该方法一次。例如,应用
程序定义的 RMISocketFactory 实现在所要求的连接上做一些基本的过滤并抛出
异常,或者返回其对 java.net.Socket 或 java.net.ServerSocket 类的扩展(
例如提供安全信道的扩展)。注意,只有在当前安全管理器允许设置套接字工厂
时才可设置 RMISocketFactory。如果不允许进行该项设置,则将抛出 Security
Exception。
静态方法 getSocketFactory 返回由 RMI 使用的套接字工厂。如果未设置套接字
工厂,则返回值为 null。
当传输需要创建套接字时,传输层将在 getSocketFactory 方法返回的 RMISock
etFactory 上调用 createSocket 和 createServerSocket 方法。例如:
RMISocketFactory.getSocketFactory().createSocket(myhost, myport)
方法 createSocket 应创建一个连接到指定 host 和 port 的客户机套接字。 c
reateServerSocket 方法应在指定 port 上创建服务器套接字。
缺省的 RMISocketFactory 传输实现使用 HTTP 通过防火墙提供透明的 RMI,如
下所述:
在 createSocket 中,工厂将自动尝试与无法用套接字直接联系的主机建立
HTTP 连接。
在 createServerSocket 中,工厂将返回用于自动检测新接受的连接是否为 HTT
P POST 请求的服务器套接字。如果是,则返回仅将请求主体透明地展示给传输然
后将其输出格式化为 HTTP 响应的套接字。
方法 setFailureHandler 设置失败句柄。在创建服务器套接字失败时,该句柄将
由 RMI 运行时调用。该句柄返回一个布尔值,用于指示是否应重试。缺省的失败
句柄返回值为 false,意味着缺省情况下运行时将不再尝试创建套接字。
方法 getFailureHandler 在套接字创建失败时返回当前句柄。失败句柄未设置时
将为 null。
5.8.2 RMIServerSocketFactory 接口
为了支持与远程对象的自定义通信,可以在导出远程对象时为其指定一个 RMISe
rverSocketFactory 实例。这一点既可通过相应的 UnicastRemoteObject 构造函
数或 exportObject 方法完成,也可通过相应的 java.rmi.activation.Activat
able 构造函数或 exportObject 方法完成。如果该服务器套接字工厂在导出远程
对象时与之关联,则 RMI 运行时将使用远程对象的服务器套接字工厂来创建 Se
rverSocket(使用 RMIServerSocketFactory.createServerSocket 方法),以接
受远程客户机的连接。
package java.rmi.server;
public interface RMIServerSocketFactory
{
public java.net.ServerSocket createServerSocket(int port)
throws IOException;
}
5.8.3 RMIClientSocketFactory 接口
要自定义与远程对象的通信,可在导出时远程对象为其指定一个 RMIClientSock
etFactory 的实例。这一点既可通过相应的 UnicastRemoteObject 构造函数或
exportObject 方法完成,也可通过相应的 java.rmi.activation.Activatable
构造函数或 exportObject 方法完成。如果该客户机套接字工厂在导出远程对象
时与之相关联,则客户机套接字工厂将同远程对象的引用一起下载到远程虚拟机
。随后,RMI 运行时将使用 RMIClientSocketFactory.createSocket 方法来建立
从客户机到远程对象的连接。
package java.rmi.server;
public interface RMIClientSocketFactory
{
public java.net.Socket createSocket(String host, int port)
throws IOException;
}
5.9 RMIFailureHandler 接口
java.rmi.server.RMIFailureHandler 接口提供一种方法指明服务器套接字创建
失败时指定 RMI 运行时如何响应(除非对象正在导出)。
package java.rmi.server;
public interface RMIFailureHandler
{
public boolean failure(Exception ex);
}
当出现了防止 RMI 运行时创建 java.net.Socket 的异常时将调用 failure 方法
。如果运行时试图重试,则该方法返回值为 true;否则将返回 false。
调用该方法前,需要通过调用 RMISocketFactory.setFailureHandler 来注册失
败句柄。如果该句柄未设置,则 RMI 运行时等待片刻后尝试再创建 ServerSock
et。
注意,当 ServerSocket 首次导出对象时如果创建 ServerSocket 失败,就不会
调用 RMIFailureHandler。而当 ServerSocket 接受请求失败后再创建该 Serve
rSocket 时,即调用 RMIFailureHandler。
5.10 LogStream 类
类 LogStream 提供一种记录错误的机制。对系统进行监控的人可能会对这些错误
感兴趣。该类在内部用于日志服务器调用。
package java.rmi.server;
public class LogStream extends java.io.PrintStream
{
public static LogStream log(String name);
public static synchronized PrintStream getDefaultStream();
public static synchronized void setDefaultStream(
PrintStream newDefault);
public synchronized OutputStream getOutputStream();
public synchronized void setOutputStream(OutputStream out);
public void write(int b);
public void write(byte b[], int off, int len);
public String toString();
public static int parseLevel(String s);
// 日志等级常数
public static final int SILENT = 0;
public static final int BRIEF = 10;
public static final int VERBOSE = 20;
}
----------------------------------------------------------------------
----------
注意 -JDK1.2 中不鼓励使用 LogStream 类
----------------------------------------------------------------------
----------
方法 log 返回由给定名称标识的 LogStream。如果某名称所对应的日志不存在,
即创建一个使用缺省流的日志。
方法 getDefaultStream 返回用于新日志的当前缺省流。
方法 setDefaultStream 为新日志设置缺省流。
方法 getOutputStream 返回当前日志输出到的流。
方法 setOutputStream 设置日志的输出流。
方法 write 的第一种形式将向该流写一个字节数据。如果不是新起一行,则将把
该字节添加到内部缓冲区。如果是新起一行,则当前缓冲区中的行将按相应的日
志前缀发送到日志的输出流中。方法 write 的第二种形式将写字节子数组。
方法 toString 以字符串形式返回日志名。
方法 parseLevel 将日志等级的字符串名转换为内部整型表示。
5.11 stub 和 skeleton 编译器
rmic 的 stub 和 skeleton 编译器用于为特定的远程对象实现编译相应的 stub
和 skeleton。该编译器将由远程对象类的类全名调用。该类必须在先前已成功
编译过。
导入类的位置由环境变量 CLASSPATH 或参数 -classpath 指定。
除非指定参数 -d,否则编译好的类文件将放在当前目录下。
参数 -keepgenerated (或 -keep)为 stub 和 skeleton 保留生成的 java 源
文件。
也可指定 stub 协议的版本:
- -v1.1 创建符合 JDK 1.1 stub 协议版本的 stub/skeleton
- -vcompat(JDK 1.2 中为缺省值)创建同时兼容 JDK 1.1 和 1.2 stub 协议
版本的 stub/skeleton
- -v1.2 创建仅符合 JDK 1.2 stub 协议版本的 stub(注意,JDK 1.2 stub
协议中并不需要 skeleton)
-show 选项为程序显示一个图形用户界面。
大多数 javac 命令行参数均可用(-O 除外)且可与 rmic 一起使用:
- -g 生成调试信息
- -depend 反复编译过期文件
- -nowarn 不生成警告信息
- -verbose 输出有关编译器所执行的操作的消息
- -classpath 指定查找输入源及类文件的位置
- -d 指定放置生成类文件的位置
- -J< runtime flag> 将参数传给 java 解释器
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -