客户端上的Java RMI ClassNotFoundException [英] Java RMI ClassNotFoundException on the client side

查看:69
本文介绍了客户端上的Java RMI ClassNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用相同的标题存在多个问题,但是没有一个问题可以帮助我解决我的问题。

There have been several questions with this same Title, but none of them have helped me solve my issue.

我一直在尝试按照此处的教程进行操作:
https://docs.oracle.com/javase/tutorial/rmi/ overview.html

I have been trying to follow the tutorial here: https://docs.oracle.com/javase/tutorial/rmi/overview.html

我将所有内容放到一个项目中使自己发疯,所以我创建了3个独立的项目:

I was driving myself crazy by putting everything in one project, so I've created 3 separate projects:


  1. 服务器->具有Main(驱动程序),并且class:ServerNode实现Compute

  2. Client->它具有Main(驱动程序) ),并且class:TestTask实现了Task

  3. Shared->它具有interface:Task和interface:Compute

这个想法是...两个应用程序都需要知道Interfaces Task(客户端发送到服务器的工作单元)和Compute(哪个是ServerNode的接口,客户端用来向其发送命令) )。

The idea is... both applications need to know about the Interfaces Task (The unit of work the client sends to the server), and Compute (Which is the interface of ServerNode that the client uses to give commands to).

服务器代码:

System.setProperty("java.security.policy","file:server.policy");
    System.out.println(System.getProperty("java.security.policy"));

    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }
    int port = 1099;
    try {
        LocateRegistry.createRegistry(port);
        String name = "Compute"; // Name of the interface
        Compute engine = new ServerNode(); // Implementor of Compute interface, ComputeEngine
        Compute stub =
                (Compute) UnicastRemoteObject.exportObject(engine, 0); // Create the stub the client will use
        Registry registry = LocateRegistry.getRegistry(port);
        registry.bind(name, stub);   // Bind the "Compute" to the stub, so client can access it by "Compute"
        System.out.println("ComputeEngine bound");
    } catch (Exception e) {
        System.err.println("ComputeEngine exception:");
        e.printStackTrace();
    }

客户代码:

System.out.println("Entering client");
    String lookupName = "localhost";
    System.setProperty("java.security.policy","file:client.policy");
    System.out.println(System.getProperty("java.security.policy"));
    System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
    System.out.println(System.getProperty("rmi.server.codebase"));
    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }
    try {
        String name = "Compute";



        Registry registry = LocateRegistry.getRegistry("localhost", 1099);

        Compute comp99 = (Compute)registry.lookup("Compute");

        System.out.println(comp99.executeTask(new TestTask()));

    } catch (Exception e) {
        System.err.println("ComputePi exception:");
        e.printStackTrace();
    }

在教程
中,我被认为是客户需要了解TestTask ...不需要/不需要进入共享。服务器只需要了解Task的接口,客户端就为它提供了该接口的实现者...我相信服务器会在后台从客户端代码库中下载具体代码。

I am led to believe, from the tutorial That only the CLIENT needs to know about TestTask... It doesn't/shouldn't need to go in Shared. The server just needs to know about the interface Task and the client gives it an implementor of that interface... I believe in the background the server downloads the concrete code from the clients codebase.

我的目录结构为
1. Documents / RMI_ServiceSide
2. Documents / RMI_ClientSide
3. Documents / RMI_Shared

My directory structure is 1. Documents/RMI_ServiceSide 2. Documents/RMI_ClientSide 3. Documents/RMI_Shared

现在,我以编程方式在服务器代码中启动rmiregister,而不是在命令行上运行它。我不认为这是我的问题,但是目前(经过4个小时的调试)我还是不知道。我可以用该代码启动服务器。

Right now I am programmatically starting up the rmiregister in the server code, instead of running it on the command line. I don't think that's my problem, but at this point (after 4 hours of debugging) I have no idea. I am able to start the server though with that code.

问题出在客户端。当我尝试运行客户端代码时,我得到:

The problem is on the client side. When I try to run the client code, I get:

Entering client
file:client.policy
file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class
ComputePi 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.company.TestTask
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:355)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:162)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179)
    at com.sun.proxy.$Proxy0.executeTask(Unknown Source)
    at com.company.Main.main(Main.java:46)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.company.TestTask
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:315)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.company.TestTask

好的,看来当我尝试执行TestTask时,注册表会回来,它可以找不到。我已经尝试了-Djava.rmi.server.codebase = file:/ c:/ Users / Brian / Documents / RMI_ClientSide /命令行参数和/或System.setProperty( rmi.server.codebase ,文件:/ c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class);

Alright, it appears that when I try to execute the TestTask, the Registry comes back that it can't find it. I have tried every possible combination of paths for the -Djava.rmi.server.codebase=file:/c:/Users/Brian/Documents/RMI_ClientSide/ command line argument AND/OR the System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");

绝对没有任何作用……我不知道这是rmiregistry的问题,还是我只是没有在我的代码库中找到正确的排列。这一切都在一台机器上,所以我不知道为什么它在找到它时会遇到问题。

Absolutely nothing seems to work... I don't know if this is an issue with the rmiregistry or if I just didn't hit the correct permutation on my codebase. This is all on one machine, so I don't know why it is having problems finding it.

要明确...需要的文件:
1. Client-> RMI_ClientSide / bin /.../ Main.class和TestTask .class
2.服务器-> RMI_ServerSide / bin / .. Main.class和ServerNode.class
3.共享-> RMI_Shared / bin /.../ RMI_Shared.jar->包含Task.class和Compute.class

To be explicit... The files that would be necessary: 1. Client -> RMI_ClientSide/bin/.../Main.class and TestTask.class 2. Server -> RMI_ServerSide/bin/..Main.class and ServerNode.class 3. Shared -> RMI_Shared/bin/.../RMI_Shared.jar -> contains Task.class and Compute.class

正如我所说,这是三个独立的项目,但包名称是相同的...包com.company;碰巧的是,我在创建每个项目时都没有重命名默认值。我也不知道这是否重要。将RMI_Shared.jar导入服务器和客户端项目时肯定不是……它们都编译良好。

As I said, these are three separate projects, BUT the package name is the same... package com.company; Just by coincidence, I didn't rename the default when creating each project. I don't know if that matters either. Certainly didn't when importing RMI_Shared.jar into server and client projects... they both compiled fine.

我发现的另一个答案给人的印象是Shared也需要包含TestTask ...但是这没有意义,因为注册表应将类定义上移在需要时将其发送到服务器...这样,客户端可以执行任意代码,直到服务器为止(此简单的不安全测试中将使用此代码)。

One other answer I found gave the impression Shared would need to contain the TestTask too... but that doesn't make sense as the registry should pull the class definition up to the server when needed... That way a client can execute arbitrary code up to the server (Which is intended in this simple insecure test).

我非常感谢您提供帮助以使其运行。谢谢!

I would appreciate any help to get this running. Thanks!

编辑:添加了指向我的代码库文件夹图像
代码库目录

Added a link to my codebase folder image Codebase directory

请注意,我项目的目录本身只是document /。客户端,服务器和助手。

Note that the directories for my projects themselves are just documents/. Client, server, and helper.

推荐答案

java.rmi.ServerException: RemoteException occurred in server thread

在服务器上找不到该类。您发送了 com.company.TestTask ,但服务器的CLASSPATH上没有该类,因此无法通过代码库功能找到它。

The class is not found at the server. You sent an instance of com.company.TestTask but the server doesn't have that class on its CLASSPATH and cannot find it via the codebase feature.

System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");

您的代码库字符串错误。它不应包含类文件名或作为其软件包一部分的任何目录。代码库是URL列表,URL是JAR文件或作为包结构头的目录。

Your codebase string is wrong. It should not include the class file name or any directory that is part of its package. A codebase is a list of URLs that are either JAR files or directories that are heads of package structures.

这篇关于客户端上的Java RMI ClassNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆