0

我对动态类加载机制的工作原理有点困惑。我实现了下面的类,当它们都在同一个 src 目录中时,我从我的 ide、服务器和客户端工作中启动它们。但是当我将它们分开时,我无法使其工作。有许多指南解释了 RMI 的工作原理等,但他们没有解释我应该如何分离文件并启动它们,一切都很好。

所以我做了什么:编译所有类并获得相应的 .class 文件。然后我创建了一个文件夹和子文件夹来分隔客户端、服务器和公共类:

home/
|-myuser/
  |--rmitest/
     |--server/ 
     |   Server.class
     |-- client/
     |   Client.class, client.policy
     |-- common/
         NotifyEventImpl.class, NotifyEventInterface.class, ServerImpl.class, ServerInterface.class

这是一个家庭作业问题服务器和客户端都将在 localhost 上工作。无论如何,然后当我启动服务器时

$ java -Djava.rmi.server.codebase=/home/myuser/rmitest/common/ Server .

它找不到课程

Exception in thread "main" java.lang.NoClassDefFoundError: ServerImpl
    at Server.main(Server.java:15)
Caused by: java.lang.ClassNotFoundException: ServerImpl
    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:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 1 more

那么我应该怎么做才能让它工作呢?我的分类正确吗?我应该如何启动服务器和客户端?谢谢。

您可以在下面找到我的课程:

public interface ServerInterface extends Remote{
    void registerForCallback(NotifyEventInterface clientInterface) 
                                                throws RemoteException;
}

public class ServerImpl extends UnicastRemoteObject implements ServerInterface {
        private List<NotifyEventInterface> clients;

        public ServerImpl() throws RemoteException{
            super();
            clients = new ArrayList<NotifyEventInterface>();
        }

        public synchronized void registerForCallback(NotifyEventInterface ClientInterface) throws RemoteException{
            if(!clients.contains(ClientInterface)){
                clients.add(ClientInterface);
                System.out.println("New client registered");
            }
        }


        public void update(int value) throws RemoteException {
            doCallbacks(value);
        }

        private synchronized void doCallbacks(int value) throws RemoteException {
            System.out.println("Starting callbacks");
            Iterator i = clients.iterator();
            while(i.hasNext()){
                NotifyEventInterface client = (NotifyEventInterface) i.next();
                client.notifyEvent(value);
            }
            System.out.println("Callbacks complete");
        }

}

public class Server {
        public static void main(String[] args) {

                ServerImpl serverObj = new ServerImpl();
                int portNum = 39000;
                startRegistry(portNum);
                String registryUrl = "//:" + portNum + "/common";
                Naming.rebind(registryUrl, serverObj);
                System.out.println("Server is ready");


                while(true){
                    int val = (int) (Math.random() * 1000);
                    System.out.println("New update " + val);
                    serverObj.update(val);
                    Thread.sleep(1500);
                }

        }

        private static void startRegistry(int rmiPortNum) throws RemoteException{
            try {
                Registry registry = LocateRegistry.getRegistry(rmiPortNum);
                registry.list( );
            } catch (RemoteException ex) {
                System.out.println("RMI registry is not located at port " + rmiPortNum);
                Registry registry = LocateRegistry.createRegistry(rmiPortNum);
                System.out.println("RMI registry created at port " + rmiPortNum);
            }
        }

}

public interface NotifyEventInterface extends Remote {
    void notifyEvent(int value) throws RemoteException;
}

public class NotifyEventImpl implements NotifyEventInterface{
        public NotifyEventImpl() throws RemoteException{
            super();
        }


        @Override
        public void notifyEvent(int value) throws RemoteException {
            String returnMessage = "Update event received " + value;
            System.out.println(returnMessage);
        }
}
4

1 回答 1

0

编译所有类,得到对应的.class文件。然后我创建了一个文件夹和子文件夹来分隔客户端、服务器和公共类

错误的。您应该首先在源代码级别将它们与源代码中的相应包语句分开。然后编译。然后编译器会将 .class 文件放入与包层次结构相对应的目录结构中。

NBServerImpl不是一个普通的类。它仅由服务器使用。

于 2016-07-03T02:22:16.103 回答