简体   繁体   English

java.rmi.UnmarshalException:java.lang.ClassNotFoundException。 无法使用RMI从另一个物理JVM访问类

[英]java.rmi.UnmarshalException: java.lang.ClassNotFoundException. Can't get acces to class from another physical JVM using RMI

I have client and server on different machines. 我在不同的机器上有客户端和服务器。

When i'm trying to deserialize object on client i get this exception. 当我试图在客户端上反序列化对象时,我得到了这个异常。

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: task.MyTask

Here's my server code: 这是我的服务器代码:

System.setProperty("java.security.policy", "all_policy.policy");
System.setSecurityManager(new RMISecurityManager());
        try
        {
            mngr = new Manager();
            registry = LocateRegistry.createRegistry(15120);

            TaskDistributor stub = (TaskDistributor) UnicastRemoteObject.exportObject(mngr, 0);
            registry.rebind("Manager", stub);
        }
catch (Exception e)
        {
            System.out.println ("Ошибка при инициалиазации RMI: " + e.getMessage() + "\n");
            e.printStackTrace();
        }
...

try
    {
        //when creating a new task
        mngr.setTask(task);
    }
    catch (Exception e)
    {
        System.out.println ("Ошибка при передаче задания: " + e.getMessage() + "\n");
        e.printStackTrace();
    }

And here's the client: 这是客户:

try
{
    //msg.getMessage() = MyTask.class.getClassLoader().getResource("").getPath() called on server machine
    System.setProperty("java.rmi.server.codebase", "file://" + server + msg.getMessage());
    Registry registry = LocateRegistry.getRegistry(server, 15120);
    TaskDistributor mngr = (TaskDistributor) registry.lookup("Manager");
    cg.append("Задание получено\n");

    MatrixMultiplier task = mngr.getTask(); //<------------Exception here
    task.multiply();

    mngr.setTask(task);

    client.sendMessage(new ChatMessage(ChatMessage.TASK_COMPLETED, ""));
}
catch (Exception e)
{
    System.out.println ("Ошибка: " + e.getMessage());
    e.printStackTrace();
}

It does work if i use it on the same local machine so i think remote client JVM can't get access to server class files or i'm using wrong path. 如果我在同一台本地计算机上使用它,它确实有效,所以我认为远程客户端JVM无法访问服务器类文件或我使用错误的路径。

msg.getMessage() returns this: /C:/Projects/IDEA/KachNetworkLab/out/production/server/ msg.getMessage()返回:/ C:/ Projects / IDEA / KachNetworkLab / out / production / server /

Any suggestions would be much appreciated. 任何建议将不胜感激。

Solution: 解:

This HttpServer worked for me. 这个HttpServer为我工作。 Maybe someone else will find this useful... 也许其他人会觉得这很有用......

HttpServer httpServer = HttpServer.create(address, 10);
httpServer.createContext("/", new HttpHandler() {
            @Override
            public void handle(HttpExchange t) throws IOException {
                try {
                File f = new File(t.getRequestURI().toString().substring(1).replace("\\", "/"));
                    System.out.println(t.getRequestURI().toString().substring(1).replace("\\", "/"));
                    if (!f.exists())
                    {
                        StringBuilder response = new StringBuilder().append("No luck :(");
                        t.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.toString().getBytes().length);
                        t.getResponseBody().write(response.toString().getBytes());
                        t.getResponseBody().close();
                        t.close();
                        return;
                    }

                    t.sendResponseHeaders(HttpURLConnection.HTTP_OK, f.length());
                    InputStream file = new FileInputStream(f);
                    sendFile(file, t.getResponseBody());
                    t.getResponseBody().close();
                    t.close();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });

        httpServer.setExecutor(null);
        httpServer.start();

Calling System.setProperty("java.rmi.server.codebase", "http://" + IP + ":8000" + project root path on server); 调用System.setProperty("java.rmi.server.codebase", "http://" + IP + ":8000" + project root path on server); on client will provide RMI with remote codebase path. 在客户端上将为RMI提供远程代码库路径。

You can get root path on server by calling MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath() for example. 您可以通过调用MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath()来获取服务器上的根路径。

You should be careful though. 你应该小心。 This way anyone can get access to any file on your server machine. 这样,任何人都可以访问服务器计算机上的任何文件。 It would be wise to write some security conditions in your handle or modify policy file. 在句柄中编写一些安全条件或修改策略文件是明智的。

The problem is that on the client, you're specifying a file: URI, which tells the JVM to look for classes in the local file system. 问题是在客户端上,您指定了一个file: URI,它告诉JVM在本地文件系统中查找类。 This works when you're running the client JVM on the same actual machine as the server, but if you want the client to be able to download the classes from a different machine, you have to give it some sort of URI it can access over the network. 当您在与服务器相同的实际计算机上运行客户端JVM时,这会起作用,但如果您希望客户端能够从另一台计算机上下载这些类,则必须为其提供某种可以访问的URI。网络。 You could use a mounted network share to do this, but the standard way is to make the jars (or bare class files) available via HTTP. 您可以使用已安装的网络共享来执行此操作,但标准方法是通过HTTP使jar(或裸类文件)可用。 The Oracle tech notes on dynamic code downloading have a thorough explanation and several examples. 关于动态代码下载Oracle技术说明有一个详尽的解释和几个例子。

If you're wanting the RMI server to be able to run "standalone" without talking to any other services, you could embed a Web server in it that binds to a random port, and then have an RMI method for the client to retrieve a URI from the server for downloading. 如果您希望RMI服务器能够在不与任何其他服务通信的情况下运行“独立”,您可以在其中嵌入一个绑定到随机端口的Web服务器,然后使用RMI方法让客户端检索来自服务器的URI用于下载。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 RMI 调用中的 java.rmi.UnmarshalException - java.rmi.UnmarshalException in RMI call java.rmi.UnmarshalException: 解组参数错误; 嵌套异常是:java.lang.ClassNotFoundException: ServicesTableau - java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.lang.ClassNotFoundException: ServicesTableau ResultSet错误java.rmi.UnmarshalException - ResultSet Error java.rmi.UnmarshalException RMI客户端无法查找服务器-java.rmi.UnmarshalException - RMI client cannot lookup server - java.rmi.UnmarshalException java.rmi.UnmarshalException:无法通过服务器提取客户端类 - java.rmi.UnmarshalException: unable to pull client classes by server 远程对象不支持RMI方法:java.rmi.UnmarshalException:无法识别的方法哈希 - RMI Method not supported by remote object: java.rmi.UnmarshalException: unrecognized method hash weblogic上下文查找错误:java.rmi.UnmarshalException:错误解组参数 - weblogic context lookup error : java.rmi.UnmarshalException: error unmarshalling arguments java.rmi.UnmarshalException:无法识别的方法hash:远程对象不支持的方法 - java.rmi.UnmarshalException: unrecognized method hash: method not supported by remote object 获取java.rmi.UnmarshalException:无法识别的方法哈希:远程对象不支持的方法 - Getting java.rmi.UnmarshalException: unrecognized method hash: method not supported by remote object java.lang.ClassNotFoundException :(无安全管理器:RMI类加载器已禁用) - java.lang.ClassNotFoundException: (no security manager: RMI class loader disabled)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM