【问题标题】:Java RMI client tries to load implementation instead of interfaceJava RMI 客户端尝试加载实现而不是接口
【发布时间】:2015-04-16 08:41:31
【问题描述】:

我对 RMI 客户端类加载行为有疑问:

我的 RMI 服务器端应用程序使用单一方法导出 ISessionFactory 对象:

ISessionToken createSession(String username, String password) throw RemoteException;

ISessionFactory 扩展 RemoteISessionTokenSerializeable

我有三个项目:客户端、服务器(包含*Impl)和外观(包含ISession*)。

服务器启动正常,我可以查找ISessionFactory。出于测试目的,我添加了一个 doSomething 方法,该方法通过服务器端的 System.out 打印出一个字符串,这也可以正常工作。但是,对 createSession() 的调用不会,但会给出异常:

Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: rmiserver.SessionTokenImpl (no security manager: RMI class loader disabled)
   at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:198)
   at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
   at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
   at com.sun.proxy.$Proxy0.createSession(Unknown Source)
   at rmiclient.Client.main(Client.java:14)
 Caused by: java.lang.ClassNotFoundException: 
   rmiserver.SessionTokenImpl (no security manager: RMI class loader disabled)
   at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:396)
   at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:186)
   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:214)
   at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
   at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
   at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
   at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
   at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
   at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:326)
   at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:175)
   ... 4 more

我知道如果不导出ISessionToken,它将被序列化并传递给客户端,因此我必须验证传递给服务器的每个会话令牌。

我不明白的是,客户端感觉需要加载令牌的Impl类。就我而言,通过了解界面应该做得很好吗?我错过了什么?

【问题讨论】:

    标签: java rmi rpc


    【解决方案1】:

    我了解,如果不导出 ISessionToken,它将被序列化并传递给客户端。

    正确。

    我不明白的是,客户端感觉需要加载token的Impl类。

    因为你没有导出它,所以它会被序列化并传递给客户端。你自己也是这么说的。

    就我而言,通过了解界面应该可以做得很好?

    仅当您将其导出时。即使这样,客户端实际上也会收到一个实现接口的存根。如果没有实现它的东西,你不能只发送一个接口。

    我错过了什么?

    你没有导出它。

    【讨论】:

    • 谢谢,如果接口已知,我认为不需要 impl。那么,要么我导出 ISessionToken 并在服务器上执行它的方法,要么我看到 SessionTokenImpl 类对服务器和客户端都可用(通过项目设置或通过 RMI 类加载)?
    • 直接导出即可。这是一个远程接口:这肯定是你的意图吗?否则删除Remote 和名称的Impl 部分并使其可序列化。
    • ISessionToken 不是远程的,只是可序列化的,这就是我的意图(将会话令牌导出给用户)。我只是不想公开一些允许异常的令牌 API(如生成方法)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    相关资源
    最近更新 更多