我已经编写了一个简单的 RMI 应用程序,但我无法将我的远程对象绑定到 RMI 注册表。RMI 注册表正在从单独的 cmd 窗口运行 [我在 Windows 10 上]。远程界面非常简单:
package matram;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteInterface extends Remote {
public String sayHello() throws RemoteException;
}
实现也很简单:
package matram;
import java.rmi.RemoteException;
public class Test1 extends java.rmi.server.UnicastRemoteObject implements RemoteInterface {
/**
*
*/
private static final long serialVersionUID = 1L;
public Test1() throws RemoteException {
super();
}
@Override
public String sayHello() throws RemoteException {
{ return "Hello world!"; }
}
}
这是服务器,其中包含 main 方法:
package matram;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.Naming;
public class RemoteDCmain {
public static Test1 dc;
public static void main(String[] args) throws InterruptedException {
if (System.getSecurityManager() == null) { System.setSecurityManager(new SecurityManager()); }
try {
String name = "DCregistry";
dc = new Test1();
Naming.rebind(name, dc);
print("dc bound");
}
catch (java.rmi.RemoteException ex) {
print("Remote Exception");
ex.printStackTrace();;
}
catch (Exception e) {
print("Naming.rebind exception:");
e.printStackTrace();
}
try {
final InetAddress localaddr = InetAddress.getLocalHost();
print("Local IP Address : " + localaddr);
} catch (UnknownHostException e) {
print("Can't detect localhost : " + e);
}
init();
} // main
private static void init() {
try {
// (new Thread((Runnable) dc)).start();
Thread.sleep(1200);
} catch (Exception e) {
print(String.format("Could not connect to account W"));
e.printStackTrace();
}
} // init()
public static void print(Object o) {
System.out.println("DC server: " + o);
}
}
当我[从Eclipse中]运行它时,我得到
DC server: Naming.rebind exception:java.lang.IllegalArgumentException
at sun.net.www.ParseUtil.decode(Unknown Source)
at sun.net.www.protocol.file.Handler.openConnection(Unknown Source)
at sun.net.www.protocol.file.Handler.openConnection(Unknown Source)
at java.net.URL.openConnection(Unknown Source)
at sun.rmi.server.LoaderHandler.addPermissionsForURLs(Unknown Source)
at sun.rmi.server.LoaderHandler.getLoaderAccessControlContext(Unknown Source)
at sun.rmi.server.LoaderHandler.lookupLoader(Unknown Source)
at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source)
at java.rmi.server.RMIClassLoader$2.loadProxyClass(Unknown Source)
at java.rmi.server.RMIClassLoader.loadProxyClass(Unknown Source)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(Unknown Source)
at java.io.ObjectInputStream.readProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at java.rmi.Naming.rebind(Unknown Source)
at matram.RemoteDCmain.main(RemoteDCmain.java:16)
我真的不知道这是从哪里来的。而且我什至还没有调用客户端...
at sun.net.www.protocol.file.Handler.openConnection(Unknown Source)
您在某处使用file:
URL。
at sun.rmi.server.LoaderHandler.lookupLoader(Unknown Source)
您正在使用类装入器。
结论:您在java.rmi.serve.codebase
系统属性中指定了无效的 file:
URL。
我还会问你为什么使用file:
URL。除非客户端位于同一主机上,否则它对客户端没有任何用处,在这种情况下,您实际上根本不需要代码库功能。
为了更好地练习Java中的集成组件,要记住的一件事是使用CMD。我并不是因为使用日食而劝阻你,但RMI是一个不同的情况。在Java RMI中,你需要使用命令rmiregistry 4545
显式地在某个自由端口(比如4545)上启动RMI注册表,你还需要编译服务器类,而不是用javac
而是用rmic
。最后一件事;对 RMI 服务器地址使用完全限定的 URL。例如 : rmic://localhost:4545/myServer