Java: pas de gestionnaire de sécurité: RMI chargeur de classe désactivé [dupliquer]

cette question a déjà une réponse ici:

  • de java.rmi.ServerException: RemoteException s'est produite dans le thread du serveur (ClassNotFoundException) 3 réponses

Salut j'ai l'application RMI et maintenant j'essaie d'invoquer certaines méthodes au serveur de mon client. J'ai code suivant:

public static void main(final String[] args) {
    try {
        //Setting the security manager

        System.setSecurityManager(new RMISecurityManager());
        IndicatorsService server = (IndicatorsService) Naming
                .lookup("rmi://localhost/" + IndicatorsService.SERVICE_NAME);
        DataProvider provider = new OHLCProvider(server);
        server.registerOHLCProvider(provider);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (RemoteException e) {
        e.printStackTrace();
    } catch (NotBoundException e) {
        e.printStackTrace();
    }
}

le serveur Est correctement chargé, mais quand j'essaie d'appeler server.registerOHLCProvider(provider); , j'obtiens ces erreurs:

     java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:336)
    at sun.rmi.transport.Transport.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
    at sk.fri.statistics.service.impl.IndicatorsServiceImpl_Stub.registerOHLCProvider(Unknown Source)
    at sk.fri.statistics.service.Client.main(Client.java:61)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:296)
    at sun.rmi.transport.Transport.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
    at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:375)
    at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
    at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:620)
    at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
    at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:290)
    ... 9 more

j'ai ajouté mon fichier policy comme argument VM, voici à quoi il ressemble:

grant {
    permission java.security.AllPermission;
}

il n'arrête pas de dire quelque chose à propos du téléchargement de classe désactivé, donc je suppose que le problème est quelque part là ... Merci!

24
demandé sur Mark 2011-06-12 17:07:58

4 réponses

Le chargement de la classe à distance

peut être délicat.

Le post original (ne pas inclure toutes les informations sur le code de base. Il se peut que la configuration de sécurité du client soit correcte, mais il n'a pas accès au code à distance. Les classes sont chargées directement à partir de la "base de code" par le client. Ils ne sont pas présentés au client par le service sur la connexion RMI. Le service renvoie simplement à une source externe pour les classes.

le le serveur doit spécifier la propriété du système java.rmi.server.codebase . La valeur doit être une URL qui est accessible au client, à partir de laquelle les classes nécessaires peuvent être chargées. S'il s'agit d'une URL file: , le système de fichiers doit être accessible au client.

et l'inverse: si le serveur doit être capable de charger des classes à partir du client (comme ici), le client doit définir la propriété de base de code à une URL qui est accessible à serveur.

23
répondu erickson 2011-06-14 19:58:33

chaque fois que vous invoquez une méthode sur un proxy RMI dynamic, le MarshalInputStream (qui étend ObjectInputStream pour remplacer resolveClass et resolveProxyClass ) délégués à LoaderHandler pour chercher dans 3 endroits pour le ClassLoader à utiliser:

  1. le ClassLoader du proxy qui est invoqué (techniquement, il utilise un hack appelé latestUserDefinedLoader() : il remonte la pile, recherche de la première méthode sur la pile qui ne fait pas partie de JRE).
  2. Thread-local contextClassLoader de l'appelant
  3. Codebase ClassLoader si SecurityManager est activé
    1. si la propriété du système java.rmi.server.useCodebaseOnly=false , alors le codebase ClassLoader utilise les URLs dans le remote java.rmi.server.codebase . Notez que la valeur par défaut de useCodebaseOnly a changé en JDK 7u21 de sorte que la distance codebase n'est plus utilisé sauf si vous le changez !
    2. sinon, le codebase ClassLoader utilise les URLs dans le local java.rmi.server.codebase .

il y a donc quelques raisons possibles pour lesquelles vous obtiendriez un ClassNotFoundException en invoquant une méthode À Distance:

  • si la pile contient "pas de gestionnaire de sécurité: chargeur de classe RMI désactivé", alors assurez-vous de définissez un SecurityManager comme décrit par d'autres si vous avez besoin d'un chargement de classe à distance pour les deux côtés pour obtenir toutes les interfaces À Distance et les classes sérialisables.
  • si vous utilisez le chargement de classe à distance et qu'il s'est arrêté de fonctionner lorsque vous êtes passé à JRE 7u21, alors mettez -Djava.rmi.server.useCodebaseOnly=true pour correspondre au comportement précédent, ou mettez -Djava.rmi.server.codebase à une liste d'URL séparées par l'espace sur les côtés local et distant. Et assurez-vous que l'ordinateur peut accéder à ces Url.
  • si vous utilisez un ClassLoader personnalisé localement dont le classloader parent définit quelques" interfaces À Distance "1519550920, alors assurez-vous d'appeler Thread.setContextClassLoader(ClassLoader) pour que RMI utilise ce ClassLoader. (C'était mon problème: j'ai eu un SwingWorker qui s'est avéré être programmé sur un thread worker qui a été créé avant que le classloader context soit mis sur le EventDispatchThread). Par exemple, A et C appartiennent à votre ClassLoader personnalisé mais B appartient au ClassLoader parent, puis, quand vous appelez un.getB().getC (), l'appel getB() utilisera le classloader personnalisé, mais l'appel getC () ne trouvera pas C dans le latestUserDefinedClassLoader et devra retomber dans le contextClassLoader.

tout ceci est une mise en garde sur la mauvaise conception de L'API ObjectInputStream. ObjectInputStream aurait dû vous demander de passer un paramètre ClassLoader, pas d'essayer d'en trouver un au hasard en utilisant latestUserDefinedLoader, contextClassLoader, et codebase.

7
répondu yonran 2013-07-29 18:29:12

vous avez besoin du gestionnaire de sécurité Côté Serveur, pas seulement côté client.

sans cela, le moteur RMI du serveur refuse de charger les classes du client, car il ne peut pas garantir que celles-ci ne feront pas de mauvaises choses sur le serveur.

avez-vous besoin du chargement de la classe RMI? Le serveur ne pourrait-il pas déjà avoir les classes que le client essaie d'envoyer?

4
répondu Paŭlo Ebermann 2011-06-14 18:18:53

je sais pourquoi ça arrive. par exemple, vous lancez un serveur dans le projet A, mais vous utilisez le Client du projet B pour demander ce serveur,c'est mal. Donc, vous devriez mettre le serveur et le client dans le même projet.

-3
répondu user3556213 2014-04-21 11:09:58