【问题标题】:Java RMI UnmarshalException and AWS EC2 ServerJava RMI UnmarshalException 和 AWS EC2 服务器
【发布时间】:2012-11-07 04:44:02
【问题描述】:

我正在尝试实施在 Sun/Oracle 网站 here 上找到的 RMI Compute PI 教程。该服务器位于 Amazon windows EC2 服务器上。客户端位于我家中的个人计算机上。为了简单起见,我禁用了服务器上的防火墙并打开了 EC2 安全组上的所有端口。我可以 ping 机器,可以访问文件等...我的目标只是让一个基本的 RMI 程序在 AWS 上运行。我稍后会监督安全问题。

启动服务器不是问题。它已正确绑定到 RMI 注册表。我正在使用以下命令来启动它:

java -Djava.security.manager -Djava.security.policy=C:\AWSTest\security.policy -Djava.rmi.server.codebase=file:/C:/AWS/Sources/sun-rmi-tutorial-server/bin/ file:/C:/AWS/Sources/sun-rmi-tutorial-common/bin/ -classpath C:\AWS\Sources\sun-rmi-tutorial-server\bin;C:\AWS\Sources\sun-rmi-tutorial-common\bin engine.ComputeEngine ec2-XX-XX-XX-XXX.ap-southeast-1.compute.amazonaws.com

  • RMI 注册表在服务器端启动。
  • 我已经在服务器端声明了一个新的安全管理器System.setSecurityManager(new RMISecurityManager())
  • 我正在使用一个security.policy 文件,在该文件中我获得了所有权限。

当我在本地计算机上启动客户端时,我以 UnmarshalException 结束:

ComputePi exception: error unmarshalling return; nested exception is: 
    java.lang.ClassNotFoundException: engine.ComputeEngine_Stub
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.lang.ClassNotFoundException: engine.ComputeEngine_Stub
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at java.rmi.Naming.lookup(Naming.java:101)
    at client.ComputePi.main(ComputePi.java:14)
Caused by: java.lang.ClassNotFoundException: engine.ComputeEngine_Stub
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:453)
    at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:184)
    at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
    at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
    at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:216)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
    ... 3 more

你有什么错误的建议吗?为什么客户端找不到正确的 Stub ?我正在使用 Eclipse Juno、Genady RMI 插件和 Java 1.7.0_07。

感谢您的帮助

编辑 1:

Java 工作区围绕 3 个项目进行组织:客户端、服务器端和一个公共项目,其中服务器和客户端共享类。

  • 我可以从本地计算机读取远程注册表。 RMI 插件可以远程连接到服务器并检查注册表。

  • 如果我没有创建 3 个项目,而是将所有类放在同一个项目下,那么一切正常...但我注意到没有生成(或需要)存根。

  • 如果在客户端,我在类路径中添加对服务器类的引用(所有内容都在本地构建),我会遇到连接超时错误,而不是解组错误。

    ComputePi 异常:连接拒绝主机:XX.XXX.XX.XX;嵌套异常是: java.net.ConnectException:连接超时:连接 java.rmi.ConnectException:连接拒绝主机:XX.XXX.XXX;嵌套异常是: java.net.ConnectException:连接超时:连接 在 sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) 在 sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) 在 sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) 在 sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128) 在 engine.ComputeEngine_Stub.executeTask(ComputeEngine_Stub.java:35) 在 client.ComputePi.main(ComputePi.java:19) 引起:java.net.ConnectException:连接超时:连接 在 java.net.DualStackPlainSocketImpl.connect0(本机方法) 在 java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69) 在 java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) 在 java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) 在 java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) 在 java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157) 在 java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391) 在 java.net.Socket.connect(Socket.java:579) 在 java.net.Socket.connect(Socket.java:528) 在 java.net.Socket.(Socket.java:425) 在 java.net.Socket.(Socket.java:208) 在 sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) 在 sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146) 在 sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ... 5 更多

【问题讨论】:

    标签: java amazon-ec2 client-server rmi


    【解决方案1】:

    您尚未将存根类部署到客户端。

    【讨论】:

    • 感谢您的帮助。你能更明确一点吗?只是为了给我的问题增加一些精度。 Java 工作区围绕 3 个项目组织:客户端、服务器端和一个公共项目,服务器和客户端共享类。
    • @BlackLabrador 我不同意需要任何进一步的精度。要么你已经将你的存根类部署到客户端,要么你还没有,而且你还没有。它是一个二元状态。显然,存根类属于共享 JAR 文件,同样显然它不在其中。
    • 您好,谢谢您的回答。对于有经验的 Java RMI 程序员来说可能显而易见的事情对于新手来说可能并不明显。我不知道如何部署 RMI 程序......这可能解释了我的问题。客户端应该合并服务器 JAR 文件并不明显......我认为 RMI 的所有目的都是通过注册表使客户端可以使用它。只要存根在服务器端导出,客户端就应该找到它。当我查看示例附带的配置文件时,我在代码库上看不到任何对服务器 JAR 的引用。我在评论中添加了 Edit 2
    • @BlackLabrador 您已经发现您现在声称的内容并不明显,客户端和服务器之间必须有一些共同的类。你只是没有把它们弄好。错误消息足以告诉您。
    猜你喜欢
    • 2014-09-08
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 2016-11-06
    • 2015-07-04
    相关资源
    最近更新 更多