原文: http://blog.csdn.net/jackiezhw/archive/2007/05/30/1631846.aspx
在使用RMI编程的时候,有时会出现如下的错误:
java.rmi.ServerException: RemoteException occurred in server thread; nested excption is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested excetion is:
java.lang.ClassNotFoundException: cn.ac.ict.hla.rmi.HelloImpl_Stub
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:39)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:250)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
开始的时候以为在运行RMI Server部分的lauch Code时找不到类,即使指定了classpath还是不行。
其实不是lauch code找不到类定义,而是rmiregistry找不到类定义,这时有两种解决办法
1. 在类所在目录运行rmiregistry;
2. 在运行lauch code的时候使用java.rmi.server.codebase指定类路径;
第1种方案是有局限的,因为不可能所有的类都在一个目录下,所以比较好的方式还是使用第2种方法。不过在使用第2种方法的使用要注意格式问题,例如:
-Djava.rmi.server.codebase=http://YourServerName/YourPackagePathName/
-Djava.rmi.server.codebase=http://webline/public/mystuff.jar
-Djava.rmi.server.codebase=file:/d:\SomeSource\Testproject\java\rmi\Hello2\
使用本地文件目录时必须使用绝对路径,而且所有的codebase后面都需要有个 \ 或 / 来表示这是一个目录,也可以是一个jar文件。如果去掉它们就会报错。
A codebase can be defined as a source, or a place, from which to load classes into a virtual machine.
我们可以把CLASSPATH看作是local codebase,而RMI和applet中使用的是remote codebase。
Applet中codebase的使用方式:
1. 客户浏览器请求一个不做客户CLASSPATH中的类
2. applet的类定义被客户从服务器上使用HTTP下载下来
3. applet在客户机上执行
RMI中codebase的使用方式:
1. 远程对象服务器通过设定java.rmi.server.codebase 属性指定远程对象的codebase。RMI server向RMI registry注册了一个远程对象,绑定到一个name上,在server VM上设置的codebase被通知给了RMI registry;
2. RMI client请求一个特定名字的远程对象的引用,用来调用远程方法;
3. RMI registry返回一个到被请求类的引用。如果这个stub实例的类定义可以在client的CLASSPATH中找到,Client会本地加载这个类;如果client的CLASSPATH中没有类定义,client会尽量从远程对象的codebase中获取类定义;
4. client从codebase中请求类定义。
5. 对请求的stub的类定义被下载到client;
6. 这时,client就有了调用远程方法的所有信息。这个stub成为一个对Server上remote对象的代理,与Applet不同的是,Applet在本地执行,而RMI在remote VM中执行;
注意:在server向rmiregistry注册的时候,也会产生第4步和第5步,不过请求的角色不是client,而是rmiregistry
codebase不但可以用于加载stub的类定义,也可以用来加载任何其他的类定义,当远程方法的一个参数或者返回值对象的类定义在本地 CLASSPATH中找不到时,也可以使用codebase来加载,如图示:
客户发起一个包含Remote Server不知道的类的实例的远程调用,Remote从codebase中下载该类的定义。
注:一个典型的情况是一个方法的参数是个Interface,但实际传人的参数是某个实现了这个接口的类,这时即使Remote没有这个类定义,编译也可以通过,但是具体调用时会找不到类定义。
注:这种情况下的codebase要在client端指定,如果不指定,Server就会错用自己的codebase。
分享到:
相关推荐
远程接口定义了可以在远程对象上执行的操作,它继承了`java.rmi.Remote`接口。这个接口不包含任何方法,但它是所有远程接口的基类,用来标记这些接口为远程可调用。远程对象是实现了远程接口的具体类,它实现了接口...
2. **实现远程接口**:然后,创建一个实现远程接口的类,该类通常需要继承自`java.rmi.Remote`接口,并且抛出`java.rmi.RemoteException`。在这个实现类中,你需要实现远程接口中的所有方法。 3. **创建并注册远程...
错误: 代理抛出异常错误: java.rmi.server.ExportException: Port already in use: 1099; nested exception is: java.net.BindException: Address already in use: JVM_Bind 这里说的是1099端口被其它进程占用...
1. **远程接口(Remote Interface)**:这是定义远程方法的接口,需要继承java.rmi.Remote接口,并声明抛出java.rmi.RemoteException的异常。 2. **远程对象(Remote Object)**:实现了远程接口的类,这个类的对象...
此外,为了运行RMI程序,还需要配置Java的RMI运行环境,包括设置JVM的`-Djava.rmi.server.hostname`属性,确保服务器和客户端的RMI通信通道畅通。在实际开发中,可能还需要考虑异常处理、安全性、并发控制等高级话题...
- **导出远程对象**: 开发者需要使用`java.rmi.Naming`或`java.rmi.server.UnicastRemoteObject`类来导出远程对象到服务器JVM。 - **注册到注册表**: 将导出的远程对象注册到RMI注册表,以便客户端能够找到。 - *...
接下来,我们创建一个实现了 `HelloInterface` 的类 `Hello`,并继承 `java.rmi.server.UnicastRemoteObject`。这个类提供了远程方法的实现,并处理与远程通信相关的细节。在构造函数中,我们抛出了 `...
6. **部署和运行**:使用RMI时,需要将远程对象导出(`java.rmi.Naming.rebind()`),然后客户端可以通过`java.rmi.Naming.lookup()`查找并调用远程对象。在实际应用中,还需要配置JVM的RMI端口和其他网络参数。 在...
1. **远程对象(Remote Object)**:这是RMI的核心,它是一个实现了特定接口(继承自java.rmi.Remote)的对象,该接口中的方法声明抛出java.rmi.RemoteException。远程对象可以驻留在网络上的任何地方,并通过网络...
- **`java.rmi.server.RemoteServer`**:这是另一个抽象类,提供了与安全相关的实现。 - **`java.rmi.activation.Activable`**:这是一个抽象类,用于支持激活机制。 - **`java.rmi.server.UnicastRemoteObject`**:...
`java.rmi.server.UnicastRemoteObject`类帮助创建并导出远程对象。 4. **RMIClient**:客户端通过` LocateRegistry.getRegistry()`获取服务器的注册表,然后使用`lookup()`方法查找并获取远程对象的引用,从而调用...
4. 配置RMI服务端:在服务端的`java.rmi.server.codebase`属性中指定远程类的位置,确保客户端能够加载到这些类。这可以通过启动参数或JAR文件的MANIFEST.MF中的Class-Path属性来设置。 5. 启动服务端:运行`RMI...
import java.rmi.Remote; import java.rmi.RemoteException; public interface MyRemoteInterface extends Remote { String doSomething(String input) throws RemoteException; } ``` 远程对象是实现了远程接口...
import java.rmi.server.UnicastRemoteObject; public class Server { public Server() {} public static void main(String args[]) { try { PaymentImpl robj = new PaymentImpl(); Payment stub = (Payment...
做为java分布式计算的基础框架的RMI体系,是javaEE结构的基础技术. 本课件全面讲解了RMI的一般实现,特殊问题解决及与sping的组合应用. 1.分布式计算的起因及基本原理 2.RMI体系结构 3.RMI服务器实现及编码 4.RMI...
2. **远程实现(Remote Implementation)**:实现了远程接口的具体类,这个类通常继承自`java.rmi.server.UnicastRemoteObject`或其子类。这个类包含了远程方法的实际实现。 3. **注册(Registry)**:RMI注册表(`...
- 定义一个远程接口,该接口继承自`java.rmi.Remote`,并声明可能会抛出`java.rmi.RemoteException`的远程方法。 - 创建实现远程接口的类,实现接口中声明的方法。 - 使用Spring的`@Service`或`@Component`注解...
java -Djava.rmi.server.hostname=localhost -Djava.rmi.registry.port=1099 YourServerClass ``` 5. 创建RMI客户端:在客户端,通过查找注册表获取远程对象的引用,并调用其方法。 ```java String url = "rmi://...
这些对象必须通过`java.rmi.server.UnicastRemoteObject`的子类或`java.rmi.activation.Activatable`的子类进行导出,以使其可以跨网络访问。 3. **注册表(Registry)**:RMI系统的“黄页”,用于存储远程对象的...
- **`java.rmi.server.UnicastRemoteObject`**:实现了`java.rmi.server.RemoteObject`,用于创建远程对象的桩和框架。 - **`java.lang.Object`**:所有Java对象的基类。 - **`java.rmi.registry.LocateRegistry`**...