Java 客户端的 RMI ClassNotFoundException
Java RMI ClassNotFoundException on the client side
同一个标题有几个问题,但是 none 帮助我解决了我的问题。
我一直在尝试按照此处的教程进行操作:
https://docs.oracle.com/javase/tutorial/rmi/overview.html
我把所有东西都放在一个项目中,快把自己逼疯了,所以我创建了 3 个独立的项目:
- Server -> 它有 Main (Driver),并且 class:ServerNode 实现了 Compute
- Client -> 它有 Main (Driver),并且 class:TestTask 实现了 Task
- 共享 -> 它有 interface:Task 和 interface:Compute
想法是...两个应用程序都需要了解接口任务(客户端发送到服务器的工作单元)和计算(客户端用来向服务器发出命令的服务器节点接口) ).
服务器代码:
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();
}
我被引导相信,从教程
只有 CLIENT 需要了解 TestTask...它不需要进入 Shared。服务器只需要知道接口 Task 并且客户端给它一个该接口的实现者......我相信在后台服务器从客户端代码库下载具体代码。
我的目录结构是
1. Documents/RMI_ServiceSide
2. Documents/RMI_ClientSide
3.Documents/RMI_Shared
现在我正在服务器代码中以编程方式启动 rmiregister,而不是 运行在命令行中启动它。我不认为那是我的问题,但此时(调试 4 小时后)我不知道。我可以使用该代码启动服务器。
问题出在客户端。当我尝试 运行 客户端代码时,我得到:
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.run(Transport.java:200)
at sun.rmi.transport.Transport.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[=13=](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.run(Transport.java:200)
at sun.rmi.transport.Transport.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[=13=](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/ 命令行参数 AND/OR System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
似乎没有任何效果...我不知道这是 rmiregistry 的问题还是我没有在我的代码库中找到正确的排列。这一切都在一台机器上,所以我不知道为什么它找不到它。
明确地说...需要的文件:
1. 客户端 -> 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
正如我所说,这是三个独立的项目,但包名称是相同的... package com.company;巧合的是,我在创建每个项目时都没有重命名默认名称。我也不知道这是否重要。将 RMI_Shared.jar 导入服务器和客户端项目时肯定没有……它们都编译得很好。
我发现的另一个答案给人的印象是 Shared 也需要包含 TestTask...但这没有意义,因为注册表应该在需要时将 class 定义拉到服务器。 .. 这样客户端就可以向服务器执行任意代码(这是在这个简单的不安全测试中的目的)。
我将不胜感激获得此 运行ning 的任何帮助。谢谢!
编辑:在我的代码库文件夹图像中添加了 link
Codebase directory
请注意,我的项目本身的目录只是 documents/。客户端、服务器和助手。
java.rmi.ServerException: RemoteException occurred in server thread
在服务器 找不到 class。 您发送了 com.company.TestTask
的实例,但服务器没有 class 在其 CLASSPATH 上,无法通过代码库功能找到它。
System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
您的代码库字符串有误。它不应包含 class 文件名或任何属于其包的目录。代码库是 URL 的列表,这些 URL 可以是 JAR 文件,也可以是作为包结构头部的目录。
同一个标题有几个问题,但是 none 帮助我解决了我的问题。
我一直在尝试按照此处的教程进行操作: https://docs.oracle.com/javase/tutorial/rmi/overview.html
我把所有东西都放在一个项目中,快把自己逼疯了,所以我创建了 3 个独立的项目:
- Server -> 它有 Main (Driver),并且 class:ServerNode 实现了 Compute
- Client -> 它有 Main (Driver),并且 class:TestTask 实现了 Task
- 共享 -> 它有 interface:Task 和 interface:Compute
想法是...两个应用程序都需要了解接口任务(客户端发送到服务器的工作单元)和计算(客户端用来向服务器发出命令的服务器节点接口) ).
服务器代码:
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();
}
我被引导相信,从教程 只有 CLIENT 需要了解 TestTask...它不需要进入 Shared。服务器只需要知道接口 Task 并且客户端给它一个该接口的实现者......我相信在后台服务器从客户端代码库下载具体代码。
我的目录结构是 1. Documents/RMI_ServiceSide 2. Documents/RMI_ClientSide 3.Documents/RMI_Shared
现在我正在服务器代码中以编程方式启动 rmiregister,而不是 运行在命令行中启动它。我不认为那是我的问题,但此时(调试 4 小时后)我不知道。我可以使用该代码启动服务器。
问题出在客户端。当我尝试 运行 客户端代码时,我得到:
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.run(Transport.java:200)
at sun.rmi.transport.Transport.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[=13=](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.run(Transport.java:200)
at sun.rmi.transport.Transport.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[=13=](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/ 命令行参数 AND/OR System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
似乎没有任何效果...我不知道这是 rmiregistry 的问题还是我没有在我的代码库中找到正确的排列。这一切都在一台机器上,所以我不知道为什么它找不到它。
明确地说...需要的文件: 1. 客户端 -> 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
正如我所说,这是三个独立的项目,但包名称是相同的... package com.company;巧合的是,我在创建每个项目时都没有重命名默认名称。我也不知道这是否重要。将 RMI_Shared.jar 导入服务器和客户端项目时肯定没有……它们都编译得很好。
我发现的另一个答案给人的印象是 Shared 也需要包含 TestTask...但这没有意义,因为注册表应该在需要时将 class 定义拉到服务器。 .. 这样客户端就可以向服务器执行任意代码(这是在这个简单的不安全测试中的目的)。
我将不胜感激获得此 运行ning 的任何帮助。谢谢!
编辑:在我的代码库文件夹图像中添加了 link Codebase directory
请注意,我的项目本身的目录只是 documents/。客户端、服务器和助手。
java.rmi.ServerException: RemoteException occurred in server thread
在服务器 找不到 class。 您发送了 com.company.TestTask
的实例,但服务器没有 class 在其 CLASSPATH 上,无法通过代码库功能找到它。
System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
您的代码库字符串有误。它不应包含 class 文件名或任何属于其包的目录。代码库是 URL 的列表,这些 URL 可以是 JAR 文件,也可以是作为包结构头部的目录。