无论我做什么,我都无法创建Serwer类的新实例。请帮助,不知何故构造函数是隐形的。我不明白为什么会这样。构造函数是公共的,所有内容都编码在一个文件中。
我得到这个:
java.rmi.StubNotFoundException: Stub class not found: Serwer_Stub; nested exception is:
java.lang.ClassNotFoundException: Serwer_Stub
at sun.rmi.server.Util.createStub(Unknown Source)
at sun.rmi.server.Util.createProxy(Unknown Source)
at sun.rmi.server.UnicastServerRef.exportObject(Unknown Source)
at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.exportObject(Unknown Source)
at javax.rmi.PortableRemoteObject.exportObject(Unknown Source)
at javax.rmi.PortableRemoteObject.<init>(Unknown Source)
at Serwer.<init>(Serwer.java:13)
at Serwer.main(Serwer.java:35)
Caused by: java.lang.ClassNotFoundException: Serwer_Stub
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
... 10 more
CLASS
import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.rmi.PortableRemoteObject;
public class Serwer extends PortableRemoteObject implements MyInterface {
public Serwer() throws RemoteException {
super();
try{
Serwer ref =
new Serwer();
Context ctx = new InitialContext();
ctx.rebind("myinterfaceimplementacja", ref);
}catch(Exception e){e.printStackTrace();}
}
@Override
public String echo(String napis) throws RemoteException {
return "echo" + napis;
}
@Override
public int dodaj(int wrt1, int wrt2) throws RemoteException {
return wrt1 + wrt2;
}
public static void main(String[] args){
try {
new Serwer();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
您的代码中有两个错误。第一个是Serwer
构造函数中明显的无限递归,您在这里一次又一次地调用构造函数。这可以通过从构造函数中删除该行来修复,并将ref
替换为以下行中的this
:
public class Serwer extends PortableRemoteObject implements MyInterface {
public Serwer() throws RemoteException {
super();
}
@Override
public String echo(String napis) throws RemoteException {
return "echo" + napis;
}
@Override
public int dodaj(int wrt1, int wrt2) throws RemoteException {
return wrt1 + wrt2;
}
public static void main(String[] args){
try {
Serwer ref = new Serwer();
// Context ctx = new InitialContext();
// ctx.rebind("myinterfaceimplementacja", ref);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
但是,此错误与您获得的ClassNotFoundException
无关。导致异常的原因是您使用PortableRemoteObject
作为远程实现的基类。通常在Java RMI中,导出(实例化)远程对象时会自动生成存根类(Serwer_Stub
)。但是PortableRemoteObject
是这种情况的一个例外。您可以通过以下两种方式解决:
正如库马尔建议的那样,将javax.rmi.PortableRemoteObject
替换为java.rmi.server.UnicastRemoteObject
。这样就可以自动创建存根对象,上面的代码将很快运行,我测试了它。
public class Serwer extends UnicastRemoteObject implements MyInterface {
如果由于某种原因你必须使用PortableRemoteObject
,那么你应该使用JDK附带的RMI编译器(rmic
)工具手动生成存根类。
首先,编译Serwer
类:
javac Serwer.java
这将生成Serwer.class
文件。然后调用RMIC工具生成存根类:
rmic Serwer
这将生成Serwer_Stub.class
文件。现在您可以运行服务器了:
java Serwer
我也对此进行了测试,它没有任何例外。
请注意,您的代码中存在另一个使用Java命名的错误,导致另一个异常(NoInitialContextException
),但这也与问题无关,这就是我在上面的代码中对其进行评论的原因。由于我不是javax.naming
的专家,因此由其他人来帮助你。
也许您打算使用RMI注册表而不是错误地使用Naming。 RMI注册表是在Java RMI中绑定和查找远程对象的本机方式。在这种情况下,您应该替换
Context ctx = new InitialContext();
ctx.rebind("myinterfaceimplementacja", ref);
带有相应RMI注册码的行:
Registry reg = LocateRegistry.createRegistry(1099);
reg.rebind("myinterfaceimplementacja", ref);
这将在标准端口(1099)上为您创建RMI注册表。如果运行程序,将创建注册表,并以给定名称导出和注册远程对象。
另一种方式是写
Registry reg = LocateRegistry.getRegistry();
这使您的程序可以找到已在运行的现有注册表。您必须在运行程序之前启动RMI注册表,方法是调用remiregistry
工具,该工具也是JDK的一部分:
rmiregistry
现在你可以编译并开始你的程序了:
javac Serwer.java
java Serwer
它将在注册表中启动并注册您的远程对象实现,使其可供客户端查找。