gpt4 book ai didi

java.rmi.NoSuchObjectException : no such object exception

转载 作者:行者123 更新时间:2023-12-02 09:15:13 26 4
gpt4 key购买 nike

已经有几个与此相关的问题,但他们的答案表明导出的对象已在服务器端进行 GC,这解决了问题。然而,这似乎不是这里的问题。

提到的异常仅在单台机器上抛出:

PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"

使用java:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

这也发生在装有 OpenJDK 7something 的同一台机器上。

根据其他答案,我应该保留对处理对象的强引用。我现在就在做,还能做什么呢?

相同的代码可以在 Windows 上运行,也可以在装有 java 7 的不同远程 Linux 机器上运行。有什么想法吗?

我已经为连接的类实现了一些终结器,但没有一个被调用。

正如建议的那样,我正在使用静态引用。对于我来说,没有办法让导出的对象 GC 合格。 对象查找后立即调用远程方法会引发异常。

类(class)的一部分

public class Client{
//some fields
private final int RMI_PORT;
private static SearchTestServiceImpl searchTestService;
private static Remote stub;
private Registry registry;
//and starting service
public void startService() throws RemoteException {
createRegistry();
searchTestService = new SearchTestServiceImpl(name);
stub = UnicastRemoteObject.exportObject(searchTestService, RMI_PORT + 1);
registry.rebind(SearchTestService.class.getName(), stub);
log.info("Binding {} to port {}", SearchTestService.class.getName(), RMI_PORT + 1);
}

private void createRegistry() throws RemoteException {
log.info("Starting RMI registry on port {}", RMI_PORT);
registry = LocateRegistry.createRegistry(RMI_PORT);
}

(...)
}

和引导代码

public class Bootstrap {

private Logger log = LoggerFactory.getLogger(Bootstrap.class);
private static Client c;

public static void main(String[] args) throws NumberFormatException,
// some preparations
c = new Client(Integer.valueOf(port), name);
c.startService();
System.gc();
System.runFinalization();
synchronized (c) {
c.wait();
}

}
}

和堆栈跟踪

java.rmi.NoSuchObjectException: no such object in table
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) ~[na:1.7.0_65]
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) ~[na:1.7.0_65]
at sun.rmi.server.UnicastRef.invoke(Unknown Source) ~[na:1.7.0_65]
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) ~[na:1.7.0_65]
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) ~[na:1.7.0_65]
at com.sun.proxy.$Proxy0.getName(Unknown Source) ~[na:na]
at call to a method of remote lookedup object #getName in this example.

请求的代码段 - 查找和调用抛出异常

//somewhere

SearchTestService c = getClient(address); // this returns nice stub
String name = c.getName(); // this is throwing exception

private SearchTestService getClient(String string) throws NumberFormatException, RemoteException, NotBoundException {
String[] parts = string.split(":");
Registry registry = LocateRegistry.getRegistry(parts[0], Integer.parseInt(parts[1]));
SearchTestService client = (SearchTestService) registry.lookup(SearchTestService.class.getName());
return (SearchTestService) client;
}

运行“监听”客户端代码(使用 RMI 注册表)后的控制台输出

10:17:55.915 [main] INFO  pl.breeze.searchtest.client.Client - Starting RMI registry on port 12097
10:17:55.936 [main] INFO p.b.s.client.SearchTestServiceImpl - Test agent Breeze Dev staging is up and running
10:17:55.952 [main] INFO pl.breeze.searchtest.client.Client - Binding pl.choina.searchtest.remote.SearchTestService to port 12098

这会等到手动关闭 - 经过测试。

最佳答案

NoSuchObjectException

Javadoc :

A NoSuchObjectException is thrown if an attempt is made to invoke a method on an object that no longer exists in the remote virtual machine.

这意味着您正在调用方法的 stub 所引用的远程对象尚未导出,即 stub 已“过时”。发生这种情况的唯一方法是手动或通过 GC 取消导出对象。

As suggested I am using static references.

不,你不是。您需要将 Registry 引用设为静态。否则,您只是在 ClientRegistry 之间形成一个可以一次性进行垃圾收集的循环。

为什么要调用服务器 Client 是另一个谜。

编辑一些评论:

stub = UnicastRemoteObject.exportObject(searchTestService, RMI_PORT + 1);

此处无需使用第二个端口。只需重新使用注册表端口即可。

log.info("Binding {} to port {}", SearchTestService.class.getName(), RMI_PORT + 1);

这是误导性的。您已经完成了这两件事,但您所做的是:

  1. 导出端口上的对象,并且
  2. 将对象绑定(bind)到名称

分两个单独的步骤。

System.gc();
System.runFinalization();

在这里,甚至在任何地方,都会发生奇怪的事情。

synchronized (c) {
c.wait();
}

这不可靠。这里您实际上不需要任何东西,因为只要 JVM 导出了远程对象,RMI 就应该保持 JVM 打开,但您可以执行注册表所做的操作:

while (true)
{
Thread.sleep(Integer.MAX_VALUE);
}

具有适当的异常处理。

我无法重现您的问题,但我使用的是 Windows 7。

关于java.rmi.NoSuchObjectException : no such object exception,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30593765/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com