【问题标题】:RMI UnmarshalException ClassNotFoundException server onlyRMI UnmarshalException ClassNotFoundException 仅服务器
【发布时间】:2013-12-03 18:57:16
【问题描述】:

我已经学习了几个关于运行 RMI 应用程序的教程。但是,我似乎无法让它工作,因为我一直卡在同一个异常上。

我目前只运行一个服务器,因此不涉及客户端通信。

我有一个简单的 RMI 程序,其中包括:

  1. 一个服务器类SortServer
  2. 一个接口ISortFactory<T>
  3. 一个实现QuickSortFactory<T>
  4. RMIUtils
  5. 策略文件allpermissions.policy

政策文件内容

grant { 
    permission java.security.AllPermission;
};

RMIUtils

static {
    // Set policy
    setPolicy();

    // Set Security manager if not present
    if(System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }

    setHost("127.0.0.1");
}

public static void addCodeBaseFor(Class<?> clazz) {
    System.setProperty("java.rmi.server.codebase", clazz.getProtectionDomain().getCodeSource().getLocation().toString());
}

public static void setPolicy() {
    System.setProperty("java.security.policy", PolicyFileLocator.getLocationOfPolicyFile());
}

public static void setHost(String hostAddress) {
    System.setProperty("java.rmi.server.hostname", hostAddress);
}

public static String getHost() {
    return System.getProperty("java.rmi.server.hostname");
}

排序服务器

public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {
    RMIUtils.addCodeBaseFor(ISortFactory.class);

    ISortFactory<String> strQSFactory = new QuickSortFactory<String>();
    // Same error: Naming.bind("rmi://"+RMIUtils.getHost()+"/quicksortfactory", strQSFactory);

    Registry registry = LocateRegistry.getRegistry();
    registry.rebind("quicksortfactory-string", strQSFactory);
}

ISortFactory

public interface ISortFactory<T> extends Remote {
    public ISorter<T> createSorter() throws RemoteException;
}

实施 QuickSortFactory

public class QuickSortFactory<T> extends UnicastRemoteObject implements ISortFactory<T> {
    private static final long serialVersionUID = -4856366323843718656L;

    public QuickSortFactory() throws RemoteException {
        super();
    }

    @Override
    public ISorter<T> createSorter() throws RemoteException {
        return new QuickSort<T>();
    }
}

ISorter、QuickSorter 和引用对象 ISorter 扩展 Remote 及其方法抛出 RemoteExceptions。 QuickSort 扩展 SortLogic 并实现 ISorter。它的方法抛出RemoteExceptions。 SortLogic 扩展 UnicastRemoteObject。它的方法抛出RemoteExceptions。

由于我使用的是 JDK 1.5+,我不需要担心存根。 rmir​​egistry 运行良好,否则我会遇到不同的错误。

文字控制台输出

2013-11-20 00:57:00 DEBUG RMIUtils:33 - Policy file path changed to 'C:\Users\Mark\AppData\Local\Temp\rmi-sorter5248481413010560777.policy'
2013-11-20 00:57:00 DEBUG RMIUtils:38 - RMI hostname set to 127.0.0.1
2013-11-20 00:57:00 DEBUG RMIUtils:27 - Codebase path added: file:/F:/Development/Git/Personal/parallel-sorter/bin/
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at nl.marktielemans.rmisorter.server.SortServer.main(SortServer.java:42)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:249)
    at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:709)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:653)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:590)
    at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:242)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1535)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1491)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1748)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
    ... 12 more

无代码库参数

我尝试过不使用 codebase 参数,但不确定如何在 RMI 类路径中包含我应该阅读的类。

我已经尝试使用上面的RegistryLocator.getRegistry()SortServer 中的代码启动注册表,以及从在我的bin 目录中打开的命令行启动它。不过,我会得到同样的错误。

【问题讨论】:

    标签: java rmi classnotfoundexception


    【解决方案1】:
    java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
    ...
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    

    注册表的 CLASSPATH 中没有该类。

    如果您使用java.rmi.server.codebase 属性,则需要在导出任何远程对象之前设置它,并且代码库需要是注册表和客户端可以使用的东西。

    public static void addCodeBaseFor(Class<?> clazz) {
        System.setProperty("java.rmi.server.codebase", clazz.getProtectionDomain().getCodeSource().getLocation().toString());
    }
    

    这行不通。从客户端无法看到包含 JAR 文件在服务器上的位置。一般是 http: 或 ftp: URL。

    【讨论】:

    • 但是,我在启动服务器时收到此错误。无论如何,我应该如何使这条路径可用呢?我看到的所有示例都只是使用 abspath 进行开发。
    • 将服务器绑定到注册表时出现此错误。查看堆栈跟踪。我引用的部分证明了这一点。我已经回答了你的另一个问题:HTTP 或 FTP。如果这就是他们所做的,那么您所看到的所有示例都是错误的。它只能在同一主机内工作。
    • 使用的主机是127.0.0.1。本地主机。一切都在本地运行,所以应该可以工作,不是吗?
    • 可能,但有什么意义呢?我的建议是在你有一个可以工作的应用程序之前严格保留代码库功能,然后将其视为一个部署选项。让这样一个不切实际的配置发挥作用是零实际用途或兴趣。
    • 我现在通过从二进制文件夹启动 RMI 让它工作了。当我开始部署时,我将不得不考虑修复代码库。感谢您提供帮助我解决此问题的见解。
    猜你喜欢
    • 2014-09-08
    • 2012-11-07
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 2013-12-09
    • 2011-11-15
    相关资源
    最近更新 更多