다른 컴퓨터에 클라이언트와 서버가 있습니다.java.rmi.UnmarshalException : java.lang.ClassNotFoundException. RMI를 사용하여 다른 실제 JVM에서 클래스에 액세스 할 수 없음
클라이언트에서 개체를 deserialize하려고 할 때이 예외가 발생합니다.
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: task.MyTask
여기 내 서버 코드입니다 :
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();
}
그리고 여기 클라이언트 : 내가 같은 로컬 컴퓨터에서 사용할 경우
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();
}
그것은 작업 그래서 난 생각합니까 JVM이 할 수있는 원격 클라이언트 서버 클래스 파일에 액세스 할 수 없거나 잘못된 경로를 사용하고 있습니다./C :
msg.getMessage()이를 반환/프로젝트/IDEA/KachNetworkLab/출력/생산/서버/
어떤 제안이 많이 주시면 감사하겠습니다.
솔루션 :이 HttpServer에 나를 위해 일한
. 어쩌면 다른 사람이 원격 코드베이스 경로 RMI를 제공 할 것입니다 클라이언트 System.setProperty("java.rmi.server.codebase", "http://" + IP + ":8000" + project root path on server);
를 호출 ...이 유용
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();
을 찾을 수 있습니다.
예를 들어 MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath()
을 호출하여 서버에서 루트 경로를 가져올 수 있습니다.
그래도 조심해야합니다. 이렇게하면 누구든지 서버 컴퓨터의 모든 파일에 액세스 할 수 있습니다. 핸들에 보안 조건을 쓰거나 정책 파일을 수정하는 것이 좋습니다.
이 프로젝트에서 RMI를 사용한 전체 점은 클라이언트가 로컬 코드베이스에'task.MyTask' 클래스가 없으므로'RMIClassLoader'를 사용하여 서버에서 다운로드하는 것입니다. – Sknictik
@Sknictik 좋아요, 당신이 지금하려는 일을 이해하고 있다고 생각합니다. 다시 쓰기. – chrylis