我看过文档,测试过,调试过......但仍然很难过。stackOverflow 的时间到了!我会做好准备,然后描述我的错误。
背景
我有一个 RMI 客户端/服务器设置,当客户端、服务器和 rmiregistry 都位于 localhost 上时,它可以正常工作。所以然后我在 serverHost 上启动 rmiregistry,并打开 rmi.server.logCalls 跟踪(下面称为 RegistryTrace)。服务器代码的重要部分:
String hostname = "//serverHost.local/project"
String codeBase = "file:/home/rik/Code/eclipse/project/bin/"
System.setProperty("java.rmi.server.hostname", hostname);
System.setProperty("java.rmi.server.codebase", codeBase);
Driver server = new Driver();
Naming.rebind(hostname, server);
当我启动服务器时,我看到 rebind() 调用成功(通过查看 RegistryTrace)。此外,查看 Naming.list() 生成的列表显示它包含“//serverHost.local:1099/project”
启动我的客户端,它成功完成 Naming.lookup():
server = (ServerInterface)Naming.lookup(serverHost);
查看 RegistryTrace,我能够确认此 lookup() 查询到达服务器端。
第一个 RMI 错误
但现在:我的下一条语句试图调用服务器的方法之一
boolean status = server.initConnection(username);
生成 IllegalArgumentException:
java.lang.IllegalArgumentException: protocol = socket host = null
at sun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:151)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:424)
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)
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.invoke(UnicastRef.java:110)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.initConnection(Unknown Source)
at project.client.View2.main(View2.java:651)
我已经将其追溯到 Java 源代码到对 java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod() 的调用
private Object invokeRemoteMethod(Object proxy,
Method method,
Object[] args)
throws Exception
{
try {
if (!(proxy instanceof Remote)) {
throw new IllegalArgumentException(
"proxy not Remote instance");
}
// EXCEPTION OCCURS WITHIN CALL TO ref.invoke() BELOW
//
return ref.invoke((Remote) proxy, method, args,
getMethodHash(method));
} catch (Exception e) {
if (!(e instanceof RuntimeException)) {
Class<?> cl = proxy.getClass();
try {
method = cl.getMethod(method.getName(),
method.getParameterTypes());
} catch (NoSuchMethodException nsme) {
throw (IllegalArgumentException)
new IllegalArgumentException().initCause(nsme);
}
Class<?> thrownType = e.getClass();
for (Class<?> declaredType : method.getExceptionTypes()) {
if (declaredType.isAssignableFrom(thrownType)) {
throw e;
}
}
e = new UnexpectedException("unexpected exception", e);
}
throw e;
}
}
然后我在源跟踪中丢失了它。(有人知道关于 sun.rmi.server.UnicastRef 之类的源可用性的故事吗?)跟踪的其余部分使 RMI 似乎无法创建套接字?
我敢肯定这段代码的许多部分可能会更干净;任何建议表示赞赏。我还需要将其转换为 jar 文件分发,所以如果现在为 java.rmi.server.codebase 指定它们会更容易......?
感谢您的任何建议,里克