Java RMI 远程服务器接口上的 ClassNotFound 异常
Java ClassNotFound Exception on RMI remote Server Interface
这是我的服务器主代码
public static void main(String Args[]){
try {
masterDAO = MasterDAO.getInstance();
} catch (MasterException e) {
e.printStackTrace();
LOGGER.log(Level.SEVERE,e.getMessage() + "MASTER SHUTDOWN");
System.exit(1);
}
final int REGISTRYPORT = 1499;
String registryHost = "localhost";
String serviceName = "MasterService";
try {
String completeName = "//" + registryHost + ":" + REGISTRYPORT + "/" + serviceName;
System.out.println(completeName);
MasterInterface master = (MasterInterface) new Master();
registry = LocateRegistry.createRegistry(REGISTRYPORT);
registry.rebind(completeName, master);
System.out.println("Master Bound ");
}
catch (Exception e) {
System.err.println("Master exception: ");
e.printStackTrace();
}
}
这是客户端的方法:
public FileLocation getFileLocation(String fileName, String operation){
final int REGISTRYPORT = 1499;
String serviceName = "MasterService";
String completeName = "//" + "localhost" + ":" + REGISTRYPORT + "/" + serviceName;
try {
System.out.println(completeName);
Registry masterRegistry = LocateRegistry.getRegistry(1499);
System.out.println(globalInformation.getHost() + " "+REGISTRYPORT);
MasterInterface master = (MasterInterface) masterRegistry.lookup(completeName);
//System.out.println("Get File Location - Result: " + fileLocation.isResult() + " - Port: "+ fileLocation.getFilePositions());
return master.checkFile(fileName,operation);
}
catch (NotBoundException | IOException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("ERROR 404 FILE NOT FOUND");
} catch (MasterException e) {
System.out.println("ERROR 500 INTERNAL SERVER ERROR");
}
return null;
}
我遇到了这个异常
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: MasterInterface (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:127)
at com.sdcc_project.cloudlet.controller.CloudLetController.getFileLocation(CloudLetController.java:125)
at com.sdcc_project.cloudlet.controller.CloudLetController.writeToMaster(CloudLetController.java:149)
at com.sdcc_project.cloudlet.CloudletApplication.run(CloudletApplication.java:126)
Caused by: java.lang.ClassNotFoundException: MasterInterface (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:556)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:646)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:265)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1800)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1748)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:123)
... 3 more
服务器在本地执行启动它的 main ,客户端像在 tomcat 服务器上的 spring 应用程序一样执行。
在 spring 上部署之前,我曾经像普通应用程序一样 运行 客户端并且一切正常,所以我认为问题可能出在 tomcat 类路径上?
这是项目的包 -->
服务器端应用程序与客户端应用程序的共享 类 和接口(例如 MasterInterface
)具有不同的包名称可能会导致此问题。
检查这两个项目并确保它在两个项目中具有相同的命名。尝试实现相同的层次结构,例如:
package com.xx.yy.server_intarface; // same in server and client application
public interface MasterInterface { ...
这解决了问题,但不仅 "package" 值必须相同,所有导入路径也必须相同。
这是我的服务器主代码
public static void main(String Args[]){
try {
masterDAO = MasterDAO.getInstance();
} catch (MasterException e) {
e.printStackTrace();
LOGGER.log(Level.SEVERE,e.getMessage() + "MASTER SHUTDOWN");
System.exit(1);
}
final int REGISTRYPORT = 1499;
String registryHost = "localhost";
String serviceName = "MasterService";
try {
String completeName = "//" + registryHost + ":" + REGISTRYPORT + "/" + serviceName;
System.out.println(completeName);
MasterInterface master = (MasterInterface) new Master();
registry = LocateRegistry.createRegistry(REGISTRYPORT);
registry.rebind(completeName, master);
System.out.println("Master Bound ");
}
catch (Exception e) {
System.err.println("Master exception: ");
e.printStackTrace();
}
}
这是客户端的方法:
public FileLocation getFileLocation(String fileName, String operation){
final int REGISTRYPORT = 1499;
String serviceName = "MasterService";
String completeName = "//" + "localhost" + ":" + REGISTRYPORT + "/" + serviceName;
try {
System.out.println(completeName);
Registry masterRegistry = LocateRegistry.getRegistry(1499);
System.out.println(globalInformation.getHost() + " "+REGISTRYPORT);
MasterInterface master = (MasterInterface) masterRegistry.lookup(completeName);
//System.out.println("Get File Location - Result: " + fileLocation.isResult() + " - Port: "+ fileLocation.getFilePositions());
return master.checkFile(fileName,operation);
}
catch (NotBoundException | IOException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("ERROR 404 FILE NOT FOUND");
} catch (MasterException e) {
System.out.println("ERROR 500 INTERNAL SERVER ERROR");
}
return null;
}
我遇到了这个异常
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: MasterInterface (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:127)
at com.sdcc_project.cloudlet.controller.CloudLetController.getFileLocation(CloudLetController.java:125)
at com.sdcc_project.cloudlet.controller.CloudLetController.writeToMaster(CloudLetController.java:149)
at com.sdcc_project.cloudlet.CloudletApplication.run(CloudletApplication.java:126)
Caused by: java.lang.ClassNotFoundException: MasterInterface (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:556)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:646)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:265)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1800)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1748)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:123)
... 3 more
服务器在本地执行启动它的 main ,客户端像在 tomcat 服务器上的 spring 应用程序一样执行。 在 spring 上部署之前,我曾经像普通应用程序一样 运行 客户端并且一切正常,所以我认为问题可能出在 tomcat 类路径上? 这是项目的包 -->
服务器端应用程序与客户端应用程序的共享 类 和接口(例如 MasterInterface
)具有不同的包名称可能会导致此问题。
检查这两个项目并确保它在两个项目中具有相同的命名。尝试实现相同的层次结构,例如:
package com.xx.yy.server_intarface; // same in server and client application
public interface MasterInterface { ...
这解决了问题,但不仅 "package" 值必须相同,所有导入路径也必须相同。