很久以前写了基于rmi的分布式java程序,现在基本都忘记了,只有一个大概印象。今天写了个小例子复习了下,比较简单,主要在于使自己熟悉下api和部署过程。一共有4个java文件。
第一步 生成stub文件 class都编译好后,要生成stub文件,我测试的时候,class编译到我的工程下的bin目录,我在bin目录下执行命令“rmic TestRemoteImpl”,rmic后面完整路径的Remote接口的实现类,如果TestRemoteImpl在包com.test里,那么命令就是“rmic com.test.TestRemoteImpl”,后面不要带上java后缀。执行完后,TestRemoteImpl.class所在的目录(就是bin目录)就会出现一个TestRemoteImpl_Stub.class文件。
第二步 准备java安全策略文件 在bin目录下新建一个名为“mypolicy”的文件,写入内容如下 grant { permission java.security.AllPermission "", ""; };
第三步 启动rmi注册程序 在命令行下,执行命令:rmiregistry。特别要主意的是,这个命令一定要在class所在的根目录执行,比如class文件全部编译到myproject/bin目录里,那么这个命令就一定在 myproject/bin目录下执行,否则在注册远程对象的时候,就会报以下异常:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.lang.ClassNotFoundException 。。。。。。
网上有很多人碰到这个问题,这是一定要主意的。
第四步 启动rmi服务器 在bin目录下,执行"java -Djava.security.policy=mypolicy Server",主要mypolicy是上面建立的安全策略文件。如果运行正确,命令行会输出:RMI服务器正在运行。。。。。。
第五步 启动客户端验证rmi 在bin目录下,执行“java Client”,如果运行正确,命令行会输出:Hello Word
我因为粗心犯的错误 1:本来是TestRemote s = (TestRemote) Naming.lookup("rmi://localhost:1099/server");我写成了TestRemote s = (TestRemoteImpl) Naming.lookup("rmi://localhost:1099/server"); 造成程序报ClassCaseException,因为lookup出来的是rmi框架自己实现了TestRemote接口的代理类,转成TestRemoteImpl当然不行。
2:在命令行下执行rmi服务器程序时,老是报ClassNotFoundException,检查了好半天,最后发现,是CLASSPATH被公司的一个工具给改写了,CLASSPATH环境变量里没有当前路径“.”,于是我在命令行里执行export $CLASSPATH=./$CLASSPATH,结果当然悲剧啊,唉,粗心阿,应该是执行export CLASSPATH=./$CLASSPATH。
3:接着是rmiregistery,linux下是rmiregistery,而windows下是start rmiregistery,而我在linux下,一开始就输入命令start rmiregistery
4:java安全问题 默认情况下,rmi在服务器端是被java安全策略限制的,要解决这个问题,可以通过两种途径。一种解决方法是自己建立一个java安全策略文件,然后执行程序时带上这个参数;另一种解决方法是自己在jre的安全策略文件里加入内容: grant { permission java.security.AllPermission "", ""; };
5:总结
(1)勿以事小而不为,再简单的东西,知道归知道,实践归实践,实践过程中,总会碰到一些实际的问题,从而使经验得以成长。
(2)如果只是报ClassNofFoundException,那么要检查CLASSPATH环境变量是否正确。
(3)如果报以下异常:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.lang.ClassNotFoundException
那就要特别注意,这是因为在将远程对象注册到rmi注册管理器的时候,注册管理器找不到要绑定的对象的class信息。
如在命令行下执行:rmiregistry 那么rmi注册管理器在默认端口1099监听,在执行“Naming.rebind("rmi://localhost:1099/server", testRemote); ”的时候,告诉rmi注册管理器,我要绑定这个对象,rmi注册管理器就会寻找这个对象的class信息,但是很奇怪的是,rmi注册管理器并不关心系统的CLASSPATH,它只是在当前目录中寻找class定义,所以这是为什么要在class所在的根目录执行rmiregistry命令。
import java.rmi.Remote; import java.rmi.RemoteException; public interface TestRemote extends Remote { public String add(String a, String b) throws RemoteException; public String add() throws RemoteException; }
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class TestRemoteImpl extends UnicastRemoteObject implements TestRemote { private static final long serialVersionUID = 1L; public TestRemoteImpl() throws RemoteException { super(); } public String add(String a, String b) throws RemoteException { return a + b; } public String add() throws RemoteException { return "Hello Word"; } }
import java.rmi.Naming; public class Server { public static void main(String[] args) throws Exception { try { // 创建远程对象 TestRemote testRemote = new TestRemoteImpl(); // 奖名称绑定到对象 Naming.rebind("rmi://localhost:1099/server", testRemote); System.out.println("RMI服务器正在运行。。。。。。"); } catch (Exception e) { e.printStackTrace(); } } }
import java.rmi.Naming; public class Client { public static void main(String args[]) { try { TestRemote s = (TestRemote) Naming.lookup("rmi://localhost:1099/server"); System.out.println(s.add()); } catch (Exception e) { e.printStackTrace(); } System.exit(0); } }
第一步 生成stub文件 class都编译好后,要生成stub文件,我测试的时候,class编译到我的工程下的bin目录,我在bin目录下执行命令“rmic TestRemoteImpl”,rmic后面完整路径的Remote接口的实现类,如果TestRemoteImpl在包com.test里,那么命令就是“rmic com.test.TestRemoteImpl”,后面不要带上java后缀。执行完后,TestRemoteImpl.class所在的目录(就是bin目录)就会出现一个TestRemoteImpl_Stub.class文件。
第二步 准备java安全策略文件 在bin目录下新建一个名为“mypolicy”的文件,写入内容如下 grant { permission java.security.AllPermission "", ""; };
第三步 启动rmi注册程序 在命令行下,执行命令:rmiregistry。特别要主意的是,这个命令一定要在class所在的根目录执行,比如class文件全部编译到myproject/bin目录里,那么这个命令就一定在 myproject/bin目录下执行,否则在注册远程对象的时候,就会报以下异常:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.lang.ClassNotFoundException 。。。。。。
网上有很多人碰到这个问题,这是一定要主意的。
第四步 启动rmi服务器 在bin目录下,执行"java -Djava.security.policy=mypolicy Server",主要mypolicy是上面建立的安全策略文件。如果运行正确,命令行会输出:RMI服务器正在运行。。。。。。
第五步 启动客户端验证rmi 在bin目录下,执行“java Client”,如果运行正确,命令行会输出:Hello Word
我因为粗心犯的错误 1:本来是TestRemote s = (TestRemote) Naming.lookup("rmi://localhost:1099/server");我写成了TestRemote s = (TestRemoteImpl) Naming.lookup("rmi://localhost:1099/server"); 造成程序报ClassCaseException,因为lookup出来的是rmi框架自己实现了TestRemote接口的代理类,转成TestRemoteImpl当然不行。
2:在命令行下执行rmi服务器程序时,老是报ClassNotFoundException,检查了好半天,最后发现,是CLASSPATH被公司的一个工具给改写了,CLASSPATH环境变量里没有当前路径“.”,于是我在命令行里执行export $CLASSPATH=./$CLASSPATH,结果当然悲剧啊,唉,粗心阿,应该是执行export CLASSPATH=./$CLASSPATH。
3:接着是rmiregistery,linux下是rmiregistery,而windows下是start rmiregistery,而我在linux下,一开始就输入命令start rmiregistery
4:java安全问题 默认情况下,rmi在服务器端是被java安全策略限制的,要解决这个问题,可以通过两种途径。一种解决方法是自己建立一个java安全策略文件,然后执行程序时带上这个参数;另一种解决方法是自己在jre的安全策略文件里加入内容: grant { permission java.security.AllPermission "", ""; };
5:总结
(1)勿以事小而不为,再简单的东西,知道归知道,实践归实践,实践过程中,总会碰到一些实际的问题,从而使经验得以成长。
(2)如果只是报ClassNofFoundException,那么要检查CLASSPATH环境变量是否正确。
(3)如果报以下异常:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.lang.ClassNotFoundException
那就要特别注意,这是因为在将远程对象注册到rmi注册管理器的时候,注册管理器找不到要绑定的对象的class信息。
如在命令行下执行:rmiregistry 那么rmi注册管理器在默认端口1099监听,在执行“Naming.rebind("rmi://localhost:1099/server", testRemote); ”的时候,告诉rmi注册管理器,我要绑定这个对象,rmi注册管理器就会寻找这个对象的class信息,但是很奇怪的是,rmi注册管理器并不关心系统的CLASSPATH,它只是在当前目录中寻找class定义,所以这是为什么要在class所在的根目录执行rmiregistry命令。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2302
- 用户1336
- 访客10970171
每日一句
Qingming Festival invites us to honor ancestors with quiet reflection and respect.
清明节邀请我们以静思与敬意祭奠祖先。
清明节邀请我们以静思与敬意祭奠祖先。
新会员