Java: no security manager: RMI class loader disabled

Hi I have RMI application and now I try to invoke some methods at server from my client. I have following code:

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();
    }
}

server Is correctly loaded, but when I am trying to call server.registerOHLCProvider(provider); I get these errors:

     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$1.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$1.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$2.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

I have added my policy file as VM argument, here is how it looks like:

grant {
    permission java.security.AllPermission;
}

It keeps saying something about disabled classloading, so I guess problem is somewhere there ... Thanks!


Remote class loading can be tricky.

The original post doesn't include any information about the code base. It may be that the client's security configuration is correct, but it has no access to the remote code. The classes are loaded directly from the "code base" by the client. They are not presented to the client by the service over the RMI connection. The service merely references an external source for the classes.

The server should specify the system property java.rmi.server.codebase. The value must be a URL that is accessible to the client, from which the necessary classes can be loaded. If this is a file: URL, the file system must be accessible to the client.

And the other way around: If the server should be able to load classes from the client (like here), the client must set the code base property to a URL that is accessible to the server.


Every time you invoke a method on an RMI dynamic proxy, the MarshalInputStream (which extends ObjectInputStream to override resolveClass and resolveProxyClass) delegates to LoaderHandler to look in 3 places for the ClassLoader to use:

  1. The ClassLoader of the proxy that is being invoked (technically, it uses a hack called latestUserDefinedLoader(): it walks up the stack, looking for the first method on the stack that is not part of JRE).
  2. Thread-local contextClassLoader of the caller
  3. Codebase ClassLoader if SecurityManager is enabled
    1. If System property java.rmi.server.useCodebaseOnly=false, then the codebase ClassLoader uses URLs in the remote java.rmi.server.codebase. Note that the default value of useCodebaseOnly changed in JDK 7u21 so that remote codebase is not used anymore unless you change it!
    2. Otherwise, the codebase ClassLoader uses URLs in the local java.rmi.server.codebase.

So there are a few possible reasons that you would get a ClassNotFoundException when invoking a Remote method:

  • If stack contains “no security manager: RMI class loader disabled”, then make sure to set a SecurityManager as described by others if you need remote class loading for both sides to get all the Remote interfaces and serializable classes.
  • If you are using remote class loading and it stopped working when you upgraded to JRE 7u21, then either set -Djava.rmi.server.useCodebaseOnly=true to match previous behavior, or set -Djava.rmi.server.codebase to a space-separated list of URLs on both the local and the remote sides. And make sure that computer can access those URLs.
  • If you are using a custom ClassLoader locally whose parent classloader defines some Remote interfaces, then make sure to call Thread.setContextClassLoader(ClassLoader) so that RMI will use that ClassLoader. (This was my problem: I had a SwingWorker that happened to be scheduled onto a worker thread that was created before the contextClassLoader was set on the EventDispatchThread). For example, A and C belong to your custom ClassLoader but B belongs to the parent ClassLoader, then when you call a.getB().getC(), the getB() call will use the custom classloader, but the getC() call will fail to find C in the latestUserDefinedClassLoader and will have to fall back to the contextClassLoader.

All of this is a cautionary tale on poor API design of ObjectInputStream. ObjectInputStream should have required you to pass a ClassLoader parameter, not try to find one haphazardly using latestUserDefinedLoader, contextClassLoader, and codebase.