client - Java RMI and ClassNotFoundException -
i starting learn how use rmi, , have question. have following directory structure:
compute.jar client | org\examples\rmi\client |--> computepi // client main |--> pi // implements task org\examples\rmi\compute |--> compute // interface |--> task // interface server | org\examples\rmi\engine |--> computeengine // server main, implements compute org\examples\rmi\compute |--> compute // interface |--> task // interface here's main method in computepi class:
if (system.getsecuritymanager() == null) { system.setsecuritymanager(new securitymanager()); } try { string name = "compute"; // args[0] = 127.0.0.1, args[1] irrelevant registry registry = locateregistry.getregistry(args[0], 0); compute comp = (compute) registry.lookup(name); pi task = new pi(integer.parseint(args[1])); bigdecimal pi = comp.executetask(task); system.out.println(pi); } catch (exception e) { system.err.println("computepi exception:"); e.printstacktrace(); } here's main method in computeengine class:
if (system.getsecuritymanager() == null) { system.setsecuritymanager(new securitymanager()); } try { string name = "compute"; compute engine = new computeengine(); compute stub = (compute) unicastremoteobject.exportobject(engine, 0); registry registry = locateregistry.getregistry(); registry.rebind(name, stub); system.out.println("computeengine bound."); } catch (exception e) { system.err.println("computeengine exception: "); e.printstacktrace(); } here's executetask method, in computeengine class:
public <t> t executetask(task<t> task) throws remoteexception { if (task == null) { throw new illegalargumentexception("task null"); } return task.execute(); } the rmi registry , server start fine. here params server:
c:\users\public\rmi\server>set classpath= c:\users\public\rmi\server>start rmiregistry c:\users\public\rmi\server>java -djava.rmi.server.codebase="file:/c:/users/public/rmi/compute.jar" -djava.rmi.server.hostname=127.0.0.1 -djava.security.policy=server.policy org.examples.rmi.engine.computeengine here params client:
c:\users\public\rmi\client>java -djava.rmi.server.codebase="file:/c:/users/public/rmi/compute.jar" -djava.security.policy=client.policy org.examples.rmi.client.computepi 127.0.0.1 45 however, following exception when try run client:
java.rmi.serverexception: remoteexception occurred in server thread; nested exception is: java.rmi.unmarshalexception: error unmarshalling arguments; nested exception is: java.lang.classnotfoundexception: org.examples.rmi.client.pi @ sun.rmi.server.unicastserverref.dispatch(unknown source) @ sun.rmi.transport.transport$1.run(unknown source) @ sun.rmi.transport.transport$1.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ sun.rmi.transport.transport.servicecall(unknown source) @ sun.rmi.transport.tcp.tcptransport.handlemessages(unknown source) @ sun.rmi.transport.tcp.tcptransport$connectionhandler.run0(unknown source) @ sun.rmi.transport.tcp.tcptransport$connectionhandler.run(unknown source) @ java.util.concurrent.threadpoolexecutor.runworker(unknown source) @ java.util.concurrent.threadpoolexecutor$worker.run(unknown source) @ java.lang.thread.run(unknown source) @ sun.rmi.transport.streamremotecall.exceptionreceivedfromserver(unknown source) @ sun.rmi.transport.streamremotecall.executecall(unknown source) @ sun.rmi.server.unicastref.invoke(unknown source) @ java.rmi.server.remoteobjectinvocationhandler.invokeremotemethod(unknown source) @ java.rmi.server.remoteobjectinvocationhandler.invoke(unknown source) @ $proxy0.executetask(unknown source) @ org.examples.rmi.client.computepi.main(computepi.java:38) caused by: java.rmi.unmarshalexception: error unmarshalling arguments; nested exception is: java.lang.classnotfoundexception: org.examples.rmi.client.pi @ sun.rmi.server.unicastserverref.dispatch(unknown source) @ sun.rmi.transport.transport$1.run(unknown source) @ sun.rmi.transport.transport$1.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ sun.rmi.transport.transport.servicecall(unknown source) @ sun.rmi.transport.tcp.tcptransport.handlemessages(unknown source) @ sun.rmi.transport.tcp.tcptransport$connectionhandler.run0(unknown source) @ sun.rmi.transport.tcp.tcptransport$connectionhandler.run(unknown source) @ java.util.concurrent.threadpoolexecutor.runworker(unknown source) @ java.util.concurrent.threadpoolexecutor$worker.run(unknown source) @ java.lang.thread.run(unknown source) caused by: java.lang.classnotfoundexception: org.examples.rmi.client.pi @ java.net.urlclassloader$1.run(unknown source) @ java.net.urlclassloader$1.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ java.net.urlclassloader.findclass(unknown source) @ java.lang.classloader.loadclass(unknown source) @ java.lang.classloader.loadclass(unknown source) @ java.lang.class.forname0(native method) @ java.lang.class.forname(unknown source) @ sun.rmi.server.loaderhandler.loadclass(unknown source) @ sun.rmi.server.loaderhandler.loadclass(unknown source) @ java.rmi.server.rmiclassloader$2.loadclass(unknown source) @ java.rmi.server.rmiclassloader.loadclass(unknown source) @ sun.rmi.server.marshalinputstream.resolveclass(unknown source) @ java.io.objectinputstream.readnonproxydesc(unknown source) @ java.io.objectinputstream.readclassdesc(unknown source) @ java.io.objectinputstream.readordinaryobject(unknown source) @ java.io.objectinputstream.readobject0(unknown source) @ java.io.objectinputstream.readobject(unknown source) @ sun.rmi.server.unicastref.unmarshalvalue(unknown source) ... 11 more but if add pi.class file server directory:
server | org\examples\rmi\engine |--> computeengine // server main, implements compute org\examples\rmi\compute |--> compute // interface |--> task // interface org\examples\rmi\client |--> pi // same pi client the program works. question is, pi.class need on server program work? understanding (and please correct me if i'm wrong) send instance of class server, , server know it, i.e. doesn't care implementation. can explain how rmi working in case? appreciate it. thanks!
you trying send serialized object of class unknown server.
when execute:
pi task = new pi(integer.parseint(args[1])); bigdecimal pi = comp.executetask(task); the server doesn't know pi. , since pi class part of api, should loaded on server, too.
when have application needs execute remotely, using example rmi, spring remoting or similar, divide project in 3 projects: api, server , client. api project have interfaces , model classes relevant functionality (this project result in jar, , more or less computer jar). server import api jar, implement interfaces , make service available through remote layer (like did server), , client did client.
when work serialization, class must known both sides. transferred state of objects in order rebuild on other side.
serialization mechanism used rmi pass objects between jvms, either arguments in method invocation client server or return values method invocation.
a bit of serialization on rmi william grosso (october 2001). , here bit more info.
Comments
Post a Comment