I have this strange problem. I'm trying to write a simple Hello World java program using RMI. Here are my files, all belonging to the same package:
Hello.java:
package com.something;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote{
String hello() throws RemoteException;
}
Server.java
package com.something;
import com.something.Hello;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class Server implements Hello{
@Override
public String hello() throws RemoteException {
return "hello world!!!!";
}
public static void main (String args[]) throws RemoteException{
//System.setProperty("java.rmi.server.hostname", "10.0.0.5");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
String name = "Hello";
Hello s = new Server();
Hello stub =
(Hello) UnicastRemoteObject.exportObject(s, 0);
Registry registry = LocateRegistry.getRegistry(8888);
registry.rebind(name, stub);
System.out.println("Hello bound");
} catch (Exception e) {
System.err.println("Hello exception:");
e.printStackTrace();
}
}
}
Client.java:
package com.something;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String args[]) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
String name = "Hello";
Registry registry = LocateRegistry.getRegistry("localhost");
Hello h = (Hello) registry.lookup(name);
System.out.println(h.hello());
} catch (Exception e) {
System.err.println("My exception:");
e.printStackTrace();
}
}
}
Before runnig the code, in the terminal, I run:
rmiregistry 8888
I run the java code with the following flag: -Djava.security.policy=/Users/nataliazon/Documents/workspace/SiecioweRMI/src/server.policy
And here's my server.policy file:
grant {
permission java.security.AllPermission;
};
When I run the Server program like that, the following exception is thrown:
Hello exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: com.something.Hello
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
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 com.something.Server.main(Server.java:30)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: com.something.Hello
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException: com.something.Hello
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:247)
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:238)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
... 12 more
And the Client program throws this:
My exception:
java.rmi.ConnectException: Connection refused to host: localhost; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at com.something.Client.main(Client.java:18)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
... 5 more
How can this problem be solved?
The Registry and the client don't have that class on their classpath.
In the case of the Registry the simplest solution is to start it in the server JVM. via
LocateRegistry.createRegistry()
: or else start it in such a way that the class is on its classpath; there are several ways to accomplish that.That is caused by specifying "localhost" instead of the server host when calling
Naming.lookup()
or when callingLocateRegistry.getRegistry()
prior to callingRegistry.lookup()
. The Registry isn't ubiquitous, it is located at the server host.NB you don't need the
SecurityManager
unless you are using the RMI codebase feature or you have some other requirement for it.