我对动态类加载机制的工作原理有点困惑。我实现了下面的类,当它们都在同一个 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);
}
}