2

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.

I just get this:

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();
    }
}
}
4

1 回答 1

2

您的代码中有两个错误。第一个是Serwer构造函数中明显的无限递归,在这里你一次又一次地调用构造函数。这可以通过从构造函数中删除该行并替换refthis以下行来解决:

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是本案的一个例外。您可以通过两种方式解决此问题:

  1. 正如 Kumar 建议的那样,将 替换javax.rmi.PortableRemoteObjectjava.rmi.server.UnicastRemoteObject. 这样stub对象就自动创建了,上面的代码就可以愉快的运行了,我测试了一下。

    public class Serwer extends UnicastRemoteObject implements MyInterface {
    
  2. 如果出于某种原因必须使用PortableRemoteObject,则应使用rmicJDK 附带的 RMI 编译器 ( ) 工具手动生成存根类。

    首先,编译Serwer类:

    javac Serwer.java
    

    这将生成Serwer.class文件。然后调用 RMIC 工具生成存根类:

    rmic Serwer
    

    这将生成Serwer_Stub.class文件。现在你可以运行你的服务器了:

    java Serwer
    

    我也对此进行了测试,它开始时没有任何例外。

请注意,您的代码中存在另一个使用 Java 命名的错误,导致另一个异常 ( NoInitialContextException),但这也与问题无关,这就是我在上面的代码中将其注释掉的原因。由于我不是这方面的专家javax.naming,这取决于其他人来帮助您。

也许您打算使用 RMI 注册表而不是错误地使用命名。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

它将启动并在注册表中注册您的远程对象实现,使其可供客户端查找。

于 2012-05-18T07:42:11.647 回答