[英]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.