RMI Einfaches Hello World mit Java6 + RMI, aber ClassNotFoundException

jee6learner

Mitglied
Problem: möchte ein einfaches Hello World mit Java 6 und RMI realisieren. Nutze Eclipse und habe folgenden Quellcodebaum
src/client/Client.java
src/server/Server.java
src/shared/Hello.java
src/shared/HelloImpl.java

Hello.java
Java:
public interface Hello extends Remote, Serializable {
	String sayHello() throws RemoteException;
}

HelloImpl.java
Java:
public class HelloImpl implements Hello {
    public HelloImpl() throws RemoteException {}
    public String sayHello() {
        return "Hello, world!";
    }
}

Server.java
Java:
public class Server {
	public static void main(String args[]) throws RemoteException {
		Registry registry = LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
		Hello stub = (Hello) UnicastRemoteObject.exportObject( new HelloImpl(), 0);
		registry.rebind("helloImpl", stub);
		while(true);
	}
}

Die rmiregistry läuft
Code:
tcp6       0      0 :::1099                 :::*                    LISTEN      1000       27869       2956/rmiregistry

aber trotzdem erhalte ich
Java:
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: shared.Hello
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:413)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
	at sun.rmi.transport.Transport$1.run(Transport.java:177)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:679)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:377)
	at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
	at server.Server.main(Server.java:35)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: shared.Hello
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:403)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
	at sun.rmi.transport.Transport$1.run(Transport.java:177)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:679)
Caused by: java.lang.ClassNotFoundException: shared.Hello
	at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:728)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:672)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:609)
	at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)
	at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
	at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:255)
	at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1548)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1510)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
	... 12 more

Kann den Fehler nicht wirklich nachvollziehen. shared.Hello liegt im gleichen Classpath wie auch der Server.
Fragen:
1. Wie löse ich das Problem?
2. Früher hatte man noch rmic benutzt, der Stub wird also nun on-the-fly erzeugt und geladen, danach aber wieder zerstört, so dass ich keinen permanenten Stub habe?
 
Zuletzt bearbeitet:

jee6learner

Mitglied
zunächst einmal natürlich danke für die antwort, einen laufenden rmi-server und -client habe ich nun. natürlich interessiert es mich, was die ursache für das nicht-funktionieren des codes ist.

zum einen nutzte ich
Code:
rmiregistry
und
Code:
LocateRegistry.getRegistry(Registry.REGISTRY_PORT)
und registrierte das objekt mit registry.rebind(). das schlug - wie ich oben schrieb, fehl.

erzeuge ich die registry nun programmatisch mit
Code:
createRegistry
und
Code:
Naming.rebind
, dann klappts ohne probleme. des interesses halber - ist obenstehend ein (denk)fehler? auch wenn der code etwas anders ist, entspricht er doch dem des rmi tutorial von oracle (Implementing a Remote Interface (The Java™ Tutorials > RMI)).

wäre dankbar, wenn man mir noch sagen könnte, warum obigens nicht klappt.
 

jee6learner

Mitglied
Die RMIRegistry hatte ich bisher aus unterschiedlichen Verzeichnissen gestartet nur nicht aus dem "richtigen". Wechselt man in das Classpath-Verzeichnis, kann ich auch mit
Code:
rmiregistry
und
Code:
registry.rebind()
meine Objekte registrieren. Danke!

Frage ist aber dann:
* Aus welchen Verzeichnissen kann die rmiregistry denn gestartet werden?
* Warum funktioniert es "nur", wenn ich in das Classpath-Verzeichnis wechsle?
 

mvitz

Top Contributor
Genau kann ich dir das auch nicht sagen, ich habe bisher zwei funktionierende Wege gefunden:
1. Starten von "rmiregistry" aus dem "Basis"-Classpath Verzeichnis
2. Setzen des Classpath Verzeichnisses über die Umgebungsvariable CLASSPATH und anschließendes starten von "rmiregistry" aus einem beliebigen Verzeichnis.
 

caesar2012

Neues Mitglied
Hallo liebe Gemeinde,

ich hole dieses Thema noch einmal hoch, da ich an diesem Wochenende nach einer funktionierenden RMI Server Client Lösung gesucht habe, und mich das Tutorial in Beitrag 2 dabei am weitesten gebracht hat.
Ich arbeite mit NetBeans und habe das Projekt nach Anleitung in diesem Beitrag erstellt und das funktioniert soweit auch alles.

Allerdings möchte ich für Server und Client unterschiedliche Java Anwendungen schreiben und ich weiß nicht, wie ich die Client Methoden in meine Client Anwendung, bzw. die Server Methoden in meine Server Anwendung integrieren muss.

Oder anders gefragt: Wie kann ich den obigen Code so kompilieren, dass ich den Client und den Server über die Shell aufrufen kann und die Kommunikation testen kann? (Also das, was Netbeans korrekt macht, mit einem "manuellen" Aufruf über die Shell nachbilden ;) )

Offensichtlich fehlt mir noch irgend ein wichtiger Zusammenhang beim Verständnis dieser Funktionalität.

Zum Hintergrund: Wenn ich es erstmal schaffe, dass das erste kleine Programm läuft, möchte ich langfristig die gleiche Java Applikation auf ClientA und ClientB laufen lassen. Diese sollen nach Benutzereingabe eine Variable auf dem Server setzen. Dort läuft eine andere Java Applikation. Der Server soll im Anschluss dann eine Methode auf den Clients starten.
Die Clients müssen untereinander nicht kommunizieren.

Über eine Antwort wäre ich wirklich sehr dankbar.


Hier nochmal der Link zu den Codes von z-mon:
Netzwerkkommunikation über Java RMI | IT blogging


JDK1.7.0_02
NetBeans 7.2
Windows XP SP3

Beste Grüße
Cäsar
 

Ähnliche Java Themen

Neue Themen


Oben