Java RMI新手无法获得基本的hello world应用程序

时间:2011-12-29 23:52:01

标签: java rmi

我写了一个简单的实现类:

public interface MyRemote extends Remote {
    public String sayHello() throws RemoteException;
}

然后是远程服务器类

public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{

    protected MyRemoteImpl() throws RemoteException {

    }

    public String sayHello() throws RemoteException {
        return "Server says 'Hello World!'";
    }

    public static void main(String args[]) {
        try {
            MyRemote service = new MyRemoteImpl();
            Naming.rebind("RemoteHello", service);
        } catch (RemoteException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (MalformedURLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }
}

现在我读到rmiregistry需要在原始类(和它们的存根)的相同路径中启动所以我只是使用intllij IDEA编译并自动生成Stub类,然后将所有类复制到我的java路径中有rmiregistry.exe文件,然后运行rmiregistry(我知道这必须是一个非常愚蠢的方法,但我只是想让它作为测试工作)。每当我尝试编译服务器文件时,我仍会收到本帖底部列出的错误。

我正在使用的书说使用java的rmic命令来生成存根和骨架,但我找不到这个文件(可能是来自旧版本的JAVA?)所以我只是使用Intellij IDEA来生成而不是存根文件...但是没有生成骨架文件。

我确定有一些关于RMI的事情我不明白,但是我在线查找了一些教程并且无法弄清楚它是什么,想想也许有人在stackoverflow上可能指出我正确的方向。任何帮助将不胜感激。

  

java.rmi.ServerError:服务器线程发生错误;嵌套   异常是:java.lang.UnsupportedClassVersionError:MyRemote:   不支持的major.minor版本51.0 at   sun.rmi.server.UnicastServerRef.oldDispatch(未知来源)at   sun.rmi.server.UnicastServerRef.dispatch(未知来源)at   sun.rmi.transport.Transport $ 1.run(未知来源)at   java.security.AccessController.doPrivileged(Native Method)at   sun.rmi.transport.Transport.serviceCall(未知来源)at   sun.rmi.transport.tcp.TCPTransport.handleMessages(未知来源)at   sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run0(未知   来源)at   sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run(未知   来源)at   java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(未知来源)     at java.util.concurrent.ThreadPoolExecutor $ Worker.run(Unknown Source)     在java.lang.Thread.run(未知来源)at   sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273)     在   sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251)     在sun.rmi.server.UnicastRef.invoke(UnicastRef.java:377)at   sun.rmi.registry.RegistryImpl_Stub.rebind(未知来源)at   java.rmi.Naming.rebind(Naming.java:177)at   MyRemoteImpl.main(MyRemoteImpl.java:27)at   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:601)at   com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,并花了很长时间试图弄清楚出了什么问题。从服务器线程抛出了相同的UnsupportedClassVersionError,让我困惑的是为什么在naming.rebind()行抛出了异常。我的RMI的实现和接口都使用与服务器应用程序相同的编译器和设置进行编译。

原来我使用的rmiregistry版本比我的jars(1.7)的编译版本低(1.6)。我甚至不知道如何/为什么在服务器线程中抛出异常而不是在运行rmiregistry的终端上显示异常。

结论:如果你从终端运行rmiregistry,输入“man rmiregistry”来确定你的默认rmiregistry的版本,确保rmiregistry的类路径中包含的类是在同一个版本中编译的。

答案 1 :(得分:3)

1)生成存根

After compiling we have two classes:

    d:\htdocs\java\NetBeansProjects\RMIserver\build\classes\rmi\

        MyRemote.class
        MyRemoteImpl.class
Run rmic

    rmic -classpath d:\htdocs\java\NetBeansProjects\RMIserver\build\classes\  
                 -d d:\htdocs\java\NetBeansProjects\RMIserver\build\classes\rmi\ 
                    rmi.MyRemoteImpl

The rmic tool creates a new class:

    /build/classes/rmi/rmi/MyRemoteImpl_Stub.class

2)启动rmiregistry

Be sure you start it from a directory that has access to your classes.

    cd d:\htdocs\java\NetBeansProjects\RMIserver\build\classes\

    %rmiregistry

5)启动服务(命令或IDE)

%java MyRemoteImpl

答案 2 :(得分:2)

错误基本上意味着您已经在比运行它们更高版本的Java中编译了类。确保您运行的是相同的JRE版本,或者确保根据要运行它们的版本对其进行编译(使用-target的{​​{1}}选项

阅读this article了解详情。