有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java RMI导致“NoSuchObjectException”

我对JavaRMI有一个问题

我有一个JavaEE应用程序正在运行,它使用rmi调用特定的方法,这些方法必须针对每个客户具体实现。 供应商给了我一个RMI接口实现示例,以说明如何运行特定的hostinterface。 原始代码片段看起来像发布的示例1。 该接口正在运行,但每隔2到3天就会停止工作,原因不明。接口日志看起来仍在运行。 调用接口的glassfish服务器显示如下日志条目:

[#|2015-10-01T16:27:53.446+0200严重glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | u ThreadID=106;| u ThreadName=Thread-2;| egatingMethodAccessorImpl.invoke(未知源) 在爪哇。朗。反思。方法调用(未知源) ...

应用程序错误日志显示如下条目:

2015-10-05 08:44:07819[http-thread-pool-8080(4)]错误medexter。阿登。服务器发动机DelegatingHostInterface-远程接口上的evaluateRead方法无法正常工作。 JAVA马绍尔群岛共和国。NoSuchObjectException:表中没有此类对象 在太阳下。马绍尔群岛共和国。运输StreamRemoteCall。从服务器接收的例外(未知源) ...

我发现了几个像这样的线程: java.rmi.NoSuchObjectException: no such object in table

这告诉我垃圾收集可能负责,注册表必须保持静态,以防止GC破坏对象。 与此同时,我尝试了不同的方法。我的最后一个例子(不知何故显示了我的失望——每24小时重新启动一次界面不应该是黄金解决方案)发布在示例2中。 目前,我生成了一个可执行的jar文件,并将其作为应用程序启动。我想让它以后作为一个服务运行,但首先它应该可以正常工作,没有任何错误

有没有人知道,所描述行为的原因是什么? 对给定代码的任何修改均应予以批准。我只是想让这些东西正常工作,而不是每隔几天就失去连接

多谢各位, 马丁

例1:

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class SampleRMIProvider {

  private static RmiRegistryThread thr;

  public static void main(String[] args) {
    SampleRMIProvider prv = new SampleRMIProvider();
    prv.init();
  }

  public void init(){
    SampleRMIProvider.thr = new RmiRegistryThread();
    thr.start();
  }

  public class RmiRegistryThread extends Thread {

    public boolean run = true;

    @Override
    public void run() {
      System.err.println("thread start");
      String name = "RMIHostInterface";
      int servicePorti = Integer.parseInt("18989");
      try {
        RmiHostInterface engine = new RmiHostInterfaceImpl();
        RmiHostInterface stub = (RmiHostInterface) UnicastRemoteObject.exportObject(engine, 0);
        Registry registry;
        try {
          registry = LocateRegistry.createRegistry(servicePorti);
        } catch (RemoteException e) {
          registry = LocateRegistry.getRegistry(servicePorti);
        }
        registry.bind(name, stub);
      } catch (RemoteException e) {
        e.printStackTrace();
      } catch (AlreadyBoundException e) {
        e.printStackTrace();
      }
      try {
        while (this.run) {
          Thread.sleep(10000);
        }     
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

例2:

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class SampleRMIProvider extends Thread{

    private static Registry r = null;

    @Override
    public void run() {
        String name = "RMIHostInterface";
        int servicePorti = Integer.parseInt("20002"); //18989

        try {
            RmiHostInterface engine = new SampleInterfaceImpl();
            RmiHostInterface stub = (RmiHostInterface) UnicastRemoteObject.exportObject(engine, 0);

            try {
                SampleRMIProvider.r = LocateRegistry.createRegistry(servicePorti);
            } catch (RemoteException e) {
                SampleRMIProvider.r = LocateRegistry.getRegistry(servicePorti);
            }
            SampleRMIProvider.r.bind(name, stub);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        } 
        System.err.println("RMI Interface created...");
        try{
            while(true){
                Thread.sleep(10000);
            }
        }
        catch (InterruptedException e) {
             e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        try {
            while (true) {
                //RMI Interface instanzieren
                SampleRMIProvider provider = new SampleRMIProvider();
                provider.start();
                //Ein Tag pause
                Thread.sleep(86400000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

14.10.2015 最后,这个最小的例子展示了一个对我有效的解决方案。谢谢你的建议

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class SampleRMIProvider{

private static Registry r = null;
private static SampleHostInterfaceImpl hif = null;
private static RmiHostInterface stub = null;

SampleRMIProvider(){
    try{
        SampleRMIProvider.r.bind("RMIHostInterface", SampleRMIProvider.stub);
    }
    catch(RemoteException | AlreadyBoundException e){
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    //setup static references to prevent from beeing collected by GC
    try {
        SampleRMIProvider.hif = new SampleHostInterfaceImpl();  
        SampleRMIProvider.stub = (RmiHostInterface) UnicastRemoteObject.exportObject(SampleRMIProvider.hif, 0);
        try {
            SampleRMIProvider.r = LocateRegistry.createRegistry(20002);
        } catch (RemoteException e) {
            SampleRMIProvider.r = LocateRegistry.getRegistry(20002);
        }

    } catch (RemoteException e) {
        e.printStackTrace();
    }
    new SampleRMIProvider();
}
}

共 (1) 个答案

  1. # 1 楼答案

    • 我不知道你所说的“未知原因”是什么意思,当原因记录在异常的Javadoc中时

    • 您说您已经读到注册表引用必须是静态的,但是您没有任何静态注册表引用

    尝试实现这一点