Java RMI简单的Hello World程序抛出RemoteException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10752288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 02:23:33  来源:igfitidea点击:

Java RMI simple Hello World program throwing RemoteException

javarmiremoteexception

提问by Natalia Zoń

I have this strange problem. I'm trying to write a simple Hello World java program using RMI. Here are my files, all belonging to the same package:

我有这个奇怪的问题。我正在尝试使用 RMI 编写一个简单的 Hello World java 程序。这是我的文件,都属于同一个包:

Hello.java:

你好.java:

package com.something;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote{
    String hello() throws RemoteException;
}

Server.java

服务器端.java

package com.something;
import com.something.Hello;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class Server implements Hello{

    @Override
    public String hello() throws RemoteException {
        return "hello world!!!!";
    }
public static void main (String args[]) throws RemoteException{

        //System.setProperty("java.rmi.server.hostname", "10.0.0.5");
                 if (System.getSecurityManager() == null) {
                        System.setSecurityManager(new SecurityManager());
                    }
                    try {
                        String name = "Hello";
                        Hello s = new Server();
                        Hello stub =
                            (Hello) UnicastRemoteObject.exportObject(s, 0);
                        Registry registry = LocateRegistry.getRegistry(8888);



                        registry.rebind(name, stub);
                        System.out.println("Hello bound");
                    } catch (Exception e) {
                        System.err.println("Hello exception:");
                        e.printStackTrace();
                    }
    }        

}       

Client.java:

客户端.java:

package com.something; 


import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;



public class Client {
    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Hello";
            Registry registry = LocateRegistry.getRegistry("localhost"); 

            Hello h = (Hello) registry.lookup(name);
            System.out.println(h.hello());   
        } catch (Exception e) {
            System.err.println("My exception:");
            e.printStackTrace();
        }
    }    
}

Before runnig the code, in the terminal, I run:

在运行代码之前,在终端中,我运行:

rmiregistry 8888

I run the java code with the following flag: -Djava.security.policy=/Users/nataliazon/Documents/workspace/SiecioweRMI/src/server.policy

我使用以下标志运行 java 代码:-Djava.security.policy=/Users/nataliazon/Documents/workspace/SiecioweRMI/src/server.policy

And here's my server.policy file:

这是我的 server.policy 文件:

grant {
   permission java.security.AllPermission;
};

When I run the Server program like that, the following exception is thrown:

当我像这样运行服务器程序时,抛出以下异常:

Hello exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.something.Hello
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at com.something.Server.main(Server.java:30)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.something.Hello
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException: com.something.Hello
    at java.net.URLClassLoader.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:709)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:653)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:590)
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:628)
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    ... 12 more

And the Client program throws this:

而客户端程序抛出这个:

My exception:
java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: 
    java.net.ConnectException: Connection refused
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at com.something.Client.main(Client.java:18)
Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at java.net.Socket.<init>(Socket.java:375)
    at java.net.Socket.<init>(Socket.java:189)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
    ... 5 more

How can this problem be solved?

如何解决这个问题?

回答by user207421

java.lang.ClassNotFoundException: com.something.Hello

java.lang.ClassNotFoundException: com.something.Hello

The Registry and the client don't have that class on their classpath.

注册表和客户端的类路径上没有该类。

In the case of the Registry the simplest solution is to start it in the server JVM. via LocateRegistry.createRegistry(): or else start it in such a way that the class is on its classpath; there are several ways to accomplish that.

对于 Registry,最简单的解决方案是在服务器 JVM 中启动它。通过LocateRegistry.createRegistry(): 或者以类在其类路径上的方式启动它;有几种方法可以做到这一点。

java.rmi.ConnectException: Connection refused to host: localhost

java.rmi.ConnectException:连接拒绝主机:本地主机

That is caused by specifying "localhost" instead of the server host when calling Naming.lookup()or when calling LocateRegistry.getRegistry()prior to calling Registry.lookup(). The Registry isn't ubiquitous, it is located at the server host.

这是由于在调用时Naming.lookup()或在调用LocateRegistry.getRegistry()之前调用时指定“localhost”而不是服务器主机造成的Registry.lookup()。注册表并不是无处不在,它位于服务器主机上。

NB you don't need the SecurityManagerunless you are using the RMI codebase feature or you have some other requirement for it.

注意,SecurityManager除非您使用 RMI 代码库功能或者您有其他一些要求,否则您不需要。