Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Rmi客户端未使用代码库_Java_Rmi_Codebase - Fatal编程技术网

Java Rmi客户端未使用代码库

Java Rmi客户端未使用代码库,java,rmi,codebase,Java,Rmi,Codebase,我为rmi编程已经有一段时间了,大约一个月后,我仍然被一个棘手的问题所困扰。我想从服务器向客户机发送一个序列化对象,并希望客户机从服务器代码库下载该对象的类。如果客户机的类路径中没有对象的类,我就无法实现这一点。以下是我一直在做的事情: 我有一个ClientLoader请求一个ClientPlayer到AuthServer。ClientLoader还应下载ClientPlayer的类,并动态加载 这是身份验证服务器,它应该创建一个对象ClientPlayer(或ClientAdmin),并将其返

我为rmi编程已经有一段时间了,大约一个月后,我仍然被一个棘手的问题所困扰。我想从服务器向客户机发送一个序列化对象,并希望客户机从服务器代码库下载该对象的类。如果客户机的类路径中没有对象的类,我就无法实现这一点。以下是我一直在做的事情:

我有一个
ClientLoader
请求一个
ClientPlayer
AuthServer
ClientLoader
还应下载
ClientPlayer
,并动态加载

这是身份验证服务器,它应该创建一个对象
ClientPlayer
(或
ClientAdmin
),并将其返回给
ClientLoader
。 (为了简洁起见,我省略了接口;无论如何,
AlfaBetaInt
意味着
Beta
实现它并
Alfa
使用它)

这是
ClientLoader
,它应该从服务器下载
ClientPlayer
(对象和类)并运行它

public class ClientLoader{

    public static void main(String[] args){
        if(System.getSecurityManager() == null)
        System.setSecurityManager(new RMISecurityManager());

    Console console = System.console();

    String host = args[0];

    try{
                    //check to see if Server is registered in rmiregistry
        String[] lista = Naming.list("//" + host );
        for( int i = 0; i < lista.length; i = i+1)
            System.out.println(lista[i]);
            //look up the client
        LoaderAuthInt authServer = (LoaderAuthInt)Naming.lookup("//" + host + "/authServer");
        System.out.println("Lookup succesful.");
        if( authServer != null)
            System.out.println("authServer != null.");
        //RUN THE CLIENT!
        Runnable client = authServer.login(console.readLine("Username: "), new String(console.readPassword("Password: ")));

        if(client == null)
            System.err.println("Login not valid");
        else
            client.run();

        System.out.println("Bye bye");
    }catch(Exception e){
        System.err.println(e);
        System.exit(1);
    }
}
}
下面是启动服务器的脚本:请注意,我确实指定了代码库,并且将属性
useCodeBaseOnly
设置为
false

if [ "$1" == "" -o "$2" == "" ]; then
    echo "usage: $0 <ip> <port number>"
else
java    -Djava.rmi.server.codebase=http://$1:8000/ \
        -Djava.rmi.server.hostname=$1 \
        -Djava.security.policy=policy \
        -Djava.rmi.server.useCodebaseOnly=false \
        card.AuthServer $2
fi
服务器运行正常;我在8000端口有一个http服务器,在2378端口有一个RMI注册表。客户端加载程序正在运行。。。准精细:rmiregistry上的方法
list()
显示绑定的服务器,服务器的查找工作正常,我可以从服务器下载客户端,但当我运行它时,我得到一个
ClassNotFoundException

    java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: card.ClientPlayer (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:196)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at com.sun.proxy.$Proxy0.login(Unknown Source)
at card.ClientLoader.main(ClientLoader.java:26)
Caused by: java.lang.ClassNotFoundException: card.ClientPlayer (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:395)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:185)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:222)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1610)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:324)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
... 4 more
我怀疑
ClientLoader
没有使用正确的代码库。。。非常感谢您的帮助

编辑:根据建议,我在客户端启动脚本中添加了
-Djava.security.manager
。。。但这导致了这些安全例外:

Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "writeFileDescriptor")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
at java.security.AccessController.checkPermission(AccessController.java:559)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkWrite(SecurityManager.java:954)
at java.io.FileOutputStream.<init>(FileOutputStream.java:244)
at java.io.Console.<init>(Console.java:566)
at java.io.Console.<init>(Console.java:92)
at java.io.Console$2.console(Console.java:540)
at java.lang.System.console(System.java:211)
at card.ClientLoader.main(ClientLoader.java:14)

有什么想法吗?我真的很难让它正常工作…

如果你仔细观察堆栈跟踪,你会发现答案已经给出:

没有安全管理器:RMI类加载程序已禁用

为了支持通过RMI下载类,必须安装
SecurityManager
。最简单的方法是
System.setSecurityManager(新的SecurityManager())

但是,当然,您必须编辑策略,以允许您的代码执行您想要执行的操作

→编辑:我明白了,您似乎已经这样做了,但只是忘记了命令行上的
-Djava.security.manager
选项。使用此选项的效果与上面的代码片段相同,它使用策略文件安装默认的
SecurityManager



或者,您可以实现自己的
SecurityManager
。出于测试目的,很容易实现一个
SecurityManager
,只允许所有操作,尽管不建议将其用于生产代码。

正是如此。客户端需要安全管理器,即进行下载的安全管理器。服务器中不需要它,除非客户端有自己的代码库用于将类上载到服务器。哇,谢谢你的回复,我不知道这个选项。。。为什么教授没有告诉我们这件事。无论如何,现在它只在客户端和服务器在同一台机器上运行,如果它们不是,我会得到一个安全异常。请参阅编辑后的主要帖子。@EdoardoSchnell:也许这有帮助:@Holger:谢谢,我有该链接中指出的策略文件(事实上,我有更一般的:
grant{permission java.security.AllPermission};
),所以我不认为这是问题所在……看起来策略文件中有打字错误。现在我回到另一个
ClassNotFoundException
,设置
-Djava.security.manager
没有帮助。现在是时候验证这些类是否真的可以从
http://$1:8000/
下载了,就像您通过
java.RMI.server.codebase
属性告诉RMI的那样。并查看您的http服务器日志。@霍尔格:我很确定客户端可以访问服务器机器:我可以使用浏览器手动下载这些类。再过几个小时我就能拿到服务器日志了!那我们只能猜测了。我将尝试在运行时打印java.rmi.server.codebase`属性,以检查脚本中的
http://$1:8000/
变量替换是否按预期工作。此外,您可以尝试通过直接从客户机的预期URL下载类文件,以查看这是否有效。如果这一切都没有帮助,请进行逐步调试,以查看
类加载器
真正试图访问的内容。
if [ "$1" == "" -o "$2" == "" ]; then
    echo "usage: $0 <ip> <port>"
else
    java    -Djava.security.policy=policy \
        -Djava.rmi.server.useCodebaseOnly=true \
        -Djava.rmi.server.codebase=http://$1:8000/ \
        card.ClientLoader "$1:$2"
fi
    java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: card.ClientPlayer (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:196)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at com.sun.proxy.$Proxy0.login(Unknown Source)
at card.ClientLoader.main(ClientLoader.java:26)
Caused by: java.lang.ClassNotFoundException: card.ClientPlayer (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:395)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:185)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:222)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1610)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:324)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
... 4 more
Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "writeFileDescriptor")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
at java.security.AccessController.checkPermission(AccessController.java:559)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkWrite(SecurityManager.java:954)
at java.io.FileOutputStream.<init>(FileOutputStream.java:244)
at java.io.Console.<init>(Console.java:566)
at java.io.Console.<init>(Console.java:92)
at java.io.Console$2.console(Console.java:540)
at java.lang.System.console(System.java:211)
at card.ClientLoader.main(ClientLoader.java:14)
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: card.ClientPlayer
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:196)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at com.sun.proxy.$Proxy0.login(Unknown Source)
at card.ClientLoader.main(ClientLoader.java:25)
Caused by: java.lang.ClassNotFoundException: card.ClientPlayer
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.rmi.server.LoaderHandler$Loader.loadClass(LoaderHandler.java:1208)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at sun.rmi.server.LoaderHandler.loadClassForName(LoaderHandler.java:1221)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:454)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:185)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:222)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1610)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:324)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
... 4 more