RMI UnmarshalException仅限ClassNotFoundException服务器

时间:2013-11-20 00:04:23

标签: java rmi classnotfoundexception

我已经学习了几个关于运行RMI应用程序的教程。但是,我似乎无法使它工作,因为我一直陷入同样的​​例外。

此时我只运行服务器,因此不涉及客户端通信。

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

  1. 服务器类SortServer
  2. 界面ISortFactory<T>
  3. 实施QuickSortFactory<T>
  4. RMIUtils班级
  5. 政策文件allpermissions.policy
  6. 政策文件内容

    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");
    }
    

    SortServer

    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,其方法抛出RemoteExceptionQuickSort扩展SortLogic并实施ISorter。它的方法抛出RemoteException s。 SortLogic延伸UnicastRemoteObject。它的方法抛出RemoteException s。

    因为我使用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类路径中包含这些类。

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

1 个答案:

答案 0 :(得分:2)

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。