我遇到了JAVA RMI的问题。
我有一个运行的java ee应用程序,它使用rmi来调用特定的方法,这些方法必须专门为每个客户实现。 供应商给了我一个示例RMI接口实现,以展示如何运行特定的主机接口。 原始的codefragment看起来像发布了example1。 接口正在运行,但每隔2到3天就会停止工作,没有任何已知原因。接口'日志看起来仍然在运行。 调用接口的glassfish服务器显示如下日志条目:
[#| 2015-10-01T16:27:53.446 + 0200 |严重| glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | _ThreadID = 106; _ThreadName = Thread- 2; | egatingMethodAccessorImpl.invoke(未知来源) at java.lang.reflect.Method.invoke(Unknown Source) ...
应用程序错误日志显示如下条目:
2015-10-05 08:44:07,819 [http-thread-pool-8080(4)]错误medexter.arden.server.engine.DelegatingHostInterface - 远程接口上的evaluateRead方法无法正常工作。 java.rmi.NoSuchObjectException:表中没有这样的对象 at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) ...
我找到了几个像这样的线程: java.rmi.NoSuchObjectException: no such object in table
告诉我垃圾收集可能是负责任的,并且必须静态保存注册表以防止GC破坏对象。 与此同时,我尝试了不同的方法。我的最后一个(以某种方式显示我的解压 - 每24小时重新启动界面不应该是黄金解决方案)发布在example2中。 目前,我生成一个可执行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();
}
}
}
二〇一五年十月十四日 最后 - 这个最小的例子显示了一个对我有用的解决方案。感谢您提供有用的建议。
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();
}
}
答案 0 :(得分:0)
当异常的Javadoc中记录原因时,我不知道你的意思是什么,没有已知的原因。
您说您已经读过注册表引用必须是静态的,但您在任何地方都没有静态注册表引用。
尝试实施。