動的クラスローディングメカニズムがどのように機能するかについて、少し混乱しています。以下のクラスを実装し、それらがすべて同じ 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);
}
}