为什么无法在其源文件Java中看到该类 [英] Why the Class cannot be seen in its source file Java
问题描述
无论我做什么,我都无法创建Serwer类的新实例。请帮助,以某种方式构造函数是不可见的。我不明白为什么会这样。构造函数是公共的,所有内容都编码在一个文件中。
Whatever I do I cannot create new instance of class Serwer. Please help, somehow constructor is invisible. I don't understand why is it so. The constructor is public and everything is coded in one file.
我刚刚得到这个:
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();
}
}
}
推荐答案
您的代码中有两个错误。第一个是 Serwer
构造函数中明显的无限递归,在这里您一次又一次地调用构造函数。可以通过从构造函数中删除该行并将 ref
替换为以下行中的 this
来解决此问题:
There are two bugs in your code. The first one is the obvious infinite recursion in the Serwer
constructor, where you are calling the constructor again and again. This can be fixed by removing that line from the constructor and replace ref
with this
on the following line:
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
是这种情况的例外。您可以通过以下两种方法解决:
However, this bug is unrelated to the ClassNotFoundException
you got. What causes the exception is that you use PortableRemoteObject
as the base class of your remote implementation. Normally in Java RMI, the stub class (Serwer_Stub
) is generated automatically when you export (instantiate) the remote object. But the PortableRemoteObject
is an exception to this case. You can solve this two ways:
-
按照Kumar的建议,替换
javax.rmi.PortableRemoteObject
和java.rmi.server.UnicastRemoteObject
。这样,便自动创建了存根对象,并且上面的代码将愉快地运行,我对其进行了测试。
As Kumar suggested, replace the
javax.rmi.PortableRemoteObject
withjava.rmi.server.UnicastRemoteObject
. This way the stub object gets created automatically, and the above code will run happily, I tested it.
public class Serwer extends UnicastRemoteObject implements MyInterface {
如果出于某些原因必须使用 PortableRemoteObject
,则应该使用JDK附带的RMI编译器( rmic
)工具手动生成存根类。
If for some reason you must use PortableRemoteObject
, then you should generate the stub class manually by using the RMI compiler (rmic
) tool that are shipped with the JDK.
首先,您编译 Serwer
类:
javac Serwer.java
这将生成 Serwer.class
文件。然后,您调用RMIC工具生成存根类:
This will generate the Serwer.class
file. Then you call the RMIC tool to generate the stub class:
rmic Serwer
这将生成 Serwer_Stub.class
文件。现在您可以运行服务器了:
This will generate the Serwer_Stub.class
file. Now you can run your server:
java Serwer
我也对此进行了测试,它的开始没有任何例外。
I also tested this, it starts without any exceptions.
请注意,您的代码中还有一个Java命名用法错误,导致另一个异常( NoInitialContextException
),但这与问题无关,这就是为什么我要评论在上面的代码中。由于我不是 javax.naming
的专家,因此需要其他人来帮助您。
Note that there is another bug in your code with the usage of the Java Naming, causing another exception (NoInitialContextException
), but that is also unrelated with the question, that's why I commented it out in the code above. Since I'm no expert in javax.naming
, it's up to someone else to help you with that.
也许您打算使用RMI注册表而不是错误地使用Naming。 RMI注册表是在Java RMI中绑定和查找远程对象的本机方法。在这种情况下,您应该替换
Maybe you intended to use RMI registry instead of using Naming by mistake. RMI registry is the native way to bind and lookup remote objects in Java RMI. In this case you should replace the
Context ctx = new InitialContext();
ctx.rebind("myinterfaceimplementacja", ref);
行以及相应的RMI注册表代码:
lines with the appropriate RMI registry code:
Registry reg = LocateRegistry.createRegistry(1099);
reg.rebind("myinterfaceimplementacja", ref);
这将在标准端口(1099)上为您创建RMI注册表。如果运行程序,将创建注册表,并以给定名称导出和注册远程对象。
This will create the RMI registry for you on the standard port (1099). If you run your program, the registry will be created and your remote object will be exported and registered under the given name.
另一种方法是编写
Registry reg = LocateRegistry.getRegistry();
这使您的程序可以找到已经运行的现有注册表。您必须在运行程序之前启动RMI注册表,方法是调用 remiregistry
工具,该工具也是JDK的一部分:
This makes your program to find an existing registry that is already running. You must start the RMI registry before running your program, by calling the remiregistry
tool, that is also part of the JDK:
rmiregistry
现在您可以编译并开始编译了程序:
Now you can compile and you start your program:
javac Serwer.java
java Serwer
它将启动并在注册表中注册您的远程对象实现,使其可供客户端查找。
It will start and register your remote object implementation in the registry, making it available to be looked up by the clients.
这篇关于为什么无法在其源文件Java中看到该类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!