RMI 动态 class 加载
RMI dynamic class loading
我正在尝试学习 RMI。设法启动了一个简单的示例,但我无法实现 类.
的动态加载
Hello.java
package com.example;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String greet(String name) throws RemoteException;
}
HelloImpl.java
package com.example;
public class HelloImpl implements Hello {
public String greet(String name) {
System.out.println("Call from " + name);
return "Hello " + name + "!";
}
}
Server.java
package com.example;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends HelloImpl {
public Server() {}
public static void main(String args[]) {
System.setSecurityManager(new SecurityManager());
try {
HelloImpl greeter = new HelloImpl();
Hello stub = (Hello) UnicastRemoteObject.exportObject(greeter, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Client.java
package com.example;
import java.rmi.Naming;
public class Client {
private Client() {}
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager());
try {
Hello stub = (Hello) Naming.lookup("//localhost/Hello");
System.out.println(stub.greet(args[0]));
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
rmi.policy
grant {
permission java.security.AllPermission;
};
我启动了 rmiregistry、web-server 并执行了 java -Djava.security.policy=rmi.policy com.example.Server
。当我尝试使用命令
启动客户端应用程序时
java -Djava.rmi.server.codebase=http://localhost:8000/ -Djava.security.policy=rmi.policy com.example.Client Hivemaster
网络服务器获取请求
127.0.0.1 - - [13/Dec/2017 14:06:45] "GET /com/example/Hello.class HTTP/1.1" 200
但程序出现异常
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/Hello
at com.example.Client.main(Client.java:17)
Caused by: java.lang.ClassNotFoundException: com.example.Hello
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
为什么?
如果客户端按名称使用 Hello
接口,则它必须存在于其类路径中。和编译时一样。
代码库功能适用于 类 派生自 远程接口中提到的那些。在这种情况下,根本不需要使用代码库功能:但如果这样做,则需要在发送那些 类.[=11 实例的 JVM 上设置代码库 属性 =]
我正在尝试学习 RMI。设法启动了一个简单的示例,但我无法实现 类.
的动态加载Hello.java
package com.example;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String greet(String name) throws RemoteException;
}
HelloImpl.java
package com.example;
public class HelloImpl implements Hello {
public String greet(String name) {
System.out.println("Call from " + name);
return "Hello " + name + "!";
}
}
Server.java
package com.example;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends HelloImpl {
public Server() {}
public static void main(String args[]) {
System.setSecurityManager(new SecurityManager());
try {
HelloImpl greeter = new HelloImpl();
Hello stub = (Hello) UnicastRemoteObject.exportObject(greeter, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Client.java
package com.example;
import java.rmi.Naming;
public class Client {
private Client() {}
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager());
try {
Hello stub = (Hello) Naming.lookup("//localhost/Hello");
System.out.println(stub.greet(args[0]));
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
rmi.policy
grant {
permission java.security.AllPermission;
};
我启动了 rmiregistry、web-server 并执行了 java -Djava.security.policy=rmi.policy com.example.Server
。当我尝试使用命令
java -Djava.rmi.server.codebase=http://localhost:8000/ -Djava.security.policy=rmi.policy com.example.Client Hivemaster
网络服务器获取请求
127.0.0.1 - - [13/Dec/2017 14:06:45] "GET /com/example/Hello.class HTTP/1.1" 200
但程序出现异常
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/Hello
at com.example.Client.main(Client.java:17)
Caused by: java.lang.ClassNotFoundException: com.example.Hello
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
为什么?
如果客户端按名称使用 Hello
接口,则它必须存在于其类路径中。和编译时一样。
代码库功能适用于 类 派生自 远程接口中提到的那些。在这种情况下,根本不需要使用代码库功能:但如果这样做,则需要在发送那些 类.[=11 实例的 JVM 上设置代码库 属性 =]