Dear Team,

I am Using Eclipse to Run my java programs. But when I try to run a Simple hello world program from Command prompt, I get the below error

"Could not find or load main class Test"

Test.class resides inside C:\

I Went inside C:\ in Cmd and typed java Test, above said error came . But when i typed java -cp . Test, it showed the output.

Why is the error coming when simply typing "java Test" . I have checked the classpath in the environment Variable under "Path" for both System as well as User defined, it has the following address C:\Program Files\Java\jdk1.7.0_21\bin\ but still error is coming.
Please advice

The classpath should contain a list of all the locations where your .class files may be found. That is completely different from the path environment variable that tells the systen where to look for .exe files.
If it works with cp . then this imples that the .class file is correctly in the current directory, but you have a classpath environment variable that does not include .

Edited 3 Years Ago by JamesCherrill

Hi James,

Thanks for the advise. That worked.
I tired to run the RMIServer class i have using the same command after updating the classpath with the directory of RMIServer.class and RMI interface.class, it throwed below error.
Please advise

C:\>java RMIServer
Exception in thread "main" java.lang.NoClassDefFoundError: RMIServer (wrong nam
: com/rm/server/RMIServer)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

My RMIServer.Java for your reference is below

package com.rm.server;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import com.rm.RMIInterface.*;

public class RMIServer  implements RMIInterface{
    static Registry registry;




    public RMIServer() throws RemoteException{
        // TODO Auto-generated constructor stub

        //super();
        try{


            //Naming.rebind("test.server", this);
            System.setProperty("java.rmi.server.codebase", RMIInterface.class.getProtectionDomain().getCodeSource().getLocation().toString());

            try {
                 File tempFile = File.createTempFile("rmi-base", ".policy");
                 BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
                 final String POLICY_FILE_CONTENT = "grant {\n"
                         + "permission java.security.AllPermission;\n" + "};\n";
                 writer.write(POLICY_FILE_CONTENT);
                 writer.close();
                 tempFile.deleteOnExit();
                 System.setProperty("java.security.policy", tempFile.getAbsolutePath());
                 System.out.println("inside 2nd try");
                 if (System.getSecurityManager() == null) {
                    System.setSecurityManager(new SecurityManager());
                 }
              } catch (IOException e) {
                  System.out.println("inside ist change");
                 e.printStackTrace();
              }


        }catch(Exception e){
            System.out.println("inside 2nd change");
            System.out.println(e.getMessage());
        }


          try {
              registry = null;
             registry = LocateRegistry.createRegistry(1099);
             System.out.println("inside 3rd try");
          } catch (RemoteException e) {
              System.out.println("Create failed, locating pre-existing registry");
          }
             try {
                 System.out.println("inside 4th try"); 
                registry = LocateRegistry.getRegistry();

             } catch (RemoteException e1) {
                 System.out.println("inside 4th change");
                e1.printStackTrace();
             }
          }







    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        RMIInterface stub=null;
        try {

            RMIServer reference = new RMIServer();





              stub = (RMIInterface) UnicastRemoteObject.exportObject(reference, 0);
        registry.rebind("server", stub);
        System.out.println("set");
        }catch(Exception e){
            System.out.println("inside main change");
            System.out.println(e.getMessage());
        }

        try {
            registry.rebind("server", stub);

        }catch(Exception e){

            System.out.println("inside main 2 change");
            System.out.println(e.getMessage());
        }
    }

    @Override
    public String query(String input) {
        // TODO Auto-generated method stub
        return "123";
    }

}

RMIInterFace is below .

package com.rm.RMIInterface;

import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;


public interface RMIInterface extends java.rmi.Remote{

    public String query(String input) throws java.rmi.RemoteException;

}

The class name for java.exe must be fully-qualifed (ie have the complete package names as well as the class name). Your RMIServer class is in a package com.rm.server, so its fully-qualified name is com.rm.server.RMIServer
Java searches the classpath locations looking for a directory structure that matches the fully-qualified name, ie your classpath should contain the location of a com directory, which contains an rm directory, which contains a server directory, which contains RMIServer.class

see
http://docs.oracle.com/javase/tutorial/java/package/managingfiles.html

Edited 3 Years Ago by JamesCherrill

Thanks James !, RMI Server and Client worked. I understand.
One last question before closing this post,
The thing is i have the above class files in the same machine.

RMI client means i can Run the RMI client on a different machine and still get the response from RMI server which is on another machine right ?

How to achieve this, Simply copy the RMIClient.class file to another machine and run both Server and Client in two different machines ?

Yes (although you may have to set firewall permissions, open ports in the router and so on to allow the machines to communicate). That's what the Registry/Naming stuff is for.

Hi James,

I have two machines which is connected. Actually the RMIServer and RMICLient class which i created is in the package com.rm.server and com.rm.client . So if i just copy the RMICLient.class file into an another machine in any directory, will it work if i run it ? or do i have to create a folder com/rm/client and put the file in that directory in the new machine also in order to run it?

Like I said - your class files have to be in a directory structure that matches the package structure, so if your client is in a package com.rm.client then your class file should be in a directory com/rm/client (and the com directory should be in the classpath)

Hi James,

I have done as you said and it ran but throwed error as below. when i look at RMIClient class code, there is no mentioning of the RMIServers's machine address like IP address or something. It simply passes a String in Registry.Rebind.

Is that causing the problem ? I even disabled firewall in the machine which runs RMI server to see if it works but still no response.

Here is my Error and RMICLient code for your reference.

C:\CHI>java com.rm.RMIClient.RMIClient
Attempting to gain reference
Exception in thread "main" java.rmi.ConnectException: Connection refused to host
: 10.11.94.203; nested exception is:
        java.net.ConnectException: Connection refused: connect
        at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
        at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216
)
        at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
        at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:341)
        at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
        at java.rmi.Naming.lookup(Naming.java:101)
        at com.rm.RMIClient.RMIClient.<init>(RMIClient.java:16)
        at com.rm.RMIClient.RMIClient.main(RMIClient.java:31)
Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.TwoStacksPlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.ja
va:339)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocket
Impl.java:200)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java
:182)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:579)
        at java.net.Socket.connect(Socket.java:528)
        at java.net.Socket.<init>(Socket.java:425)
        at java.net.Socket.<init>(Socket.java:208)
        at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirect
SocketFactory.java:40)
        at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMaster
SocketFactory.java:147)
        at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
        ... 7 more

*************** RMICLient**************

package com.rm.RMIClient;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import com.rm.RMIInterface.*;

public class RMIClient {

    public RMIClient() throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated constructor stub

        System.out.println("Attempting to gain reference");
        RMIInterface remoteObject = (RMIInterface)Naming.lookup("server");
        String reply = remoteObject.query("test");
        System.out.println(reply);

    }

    /**
     * @param args
     * @throws NotBoundException 
     * @throws RemoteException 
     * @throws MalformedURLException 
     */
    public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated method stub

        RMIClient reference = new RMIClient();

    }

}

That looks like the server is refusing the connection for some reason - maybe a network/firewall configuration problem, maybe a Java policy file problem (doesn't grant sufficient permissions)?

Is 10.11.94.203 the correct server IP (that's where it was trying to connect to)? I can't see where you are specifying or searching for the server's Registry.

Have a look at
http://docs.oracle.com/javase/tutorial/rmi/client.html

Edited 3 Years Ago by JamesCherrill

Hi James,

I am running into a strange problem now, when i simply type "java RMIClient" it asks for fully qualified name, when i give fully qualified name, it says "cannot load main clas". I checked evrything, class path and path.

The thing is i am having RMIServer, client and interface classes in same Directory com/rm/server.

I dont know what is causing this problem, please check below and advise.

C:\Users\jacksons5>java com.rm.server.RMIClient
    Error: Could not find or load main class com.rm.server.RMIClient

****** fully qualified name also throws error below **********

C:\Users\jacksons5>java RMIClient
Exception in thread "main" java.lang.NoClassDefFoundError: RMIClient (wrong name
: com/rm/server/RMIClient)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

Below is the declaration

package com.rm.server;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;


public class RMIClient {

    public RMIClient() throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated constructor stub

        System.out.println("Attempting to gain reference");
        RMIInterface remoteObject = (RMIInterface)Naming.lookup("PlusOne");
        int reply = remoteObject.plusOne(12);
        System.out.println(reply);

    }

    /**
     * @param args
     * @throws NotBoundException 
     * @throws RemoteException 
     * @throws MalformedURLException 
     */
    public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated method stub

        RMIClient reference = new RMIClient();

    }

}

yeah, that was in my office. This time i tried in my home.

The only change is in my office i had the class files each in each directory

com/rm/server
com/rm/RMIClient
com/rm/Interface

in my home all class files in one location

** C:\Users\jacksons5\workspace\rm\bin\com\rm\server **

** Class path for your reference **

C:\Program Files\Java\jdk1.7.0_21\bin\ : D:\inputs\jgoodies-looks-2.5.3.jar;C:\Users\jacksons5\workspace\rm\bin\com\rm\server\

Wrong classpath.
Java will search the classpath for com\rm\server\RMIClient.class
It won't find that in C:\Users\jacksons5\workspace\rm\bin\com\rm\server
But it will find it in C:\Users\jacksons5\workspace\rm\bin

oh ok, so for example if i have a class file in the path

c:\test\test1\test2\test3\test.class and my package declaration is

package test2.test3

then my class path should be "c:\test\test1\"

and this is a worong classpath "c:\test\test1\test2\test3\

am i right in understanding?

Hi James,

Thanks, That worked well !!!

For RMIClient connection problem,

You have asked me "I can't see where you are specifying or searching for the server's Registry."

So I have modifed the client code as below to look for registry . Now I think its connecting to the machine but throwing some other error .

Please hava a look below .

package com.rm.RMIClient;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import com.rm.RMIInterface.*;

public class RMIClient {

    public RMIClient() throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated constructor stub

        System.out.println("Attempting to gain reference");
        Registry registry = LocateRegistry.getRegistry("tcs-app-prd02.global.iff.com");
        RMIInterface remoteObject = (RMIInterface)registry.lookup("server");
        String reply = remoteObject.query("test");
        System.out.println(reply);

    }

    /**
     * @param args
     * @throws NotBoundException 
     * @throws RemoteException 
     * @throws MalformedURLException 
     */
    public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
        // TODO Auto-generated method stub

        RMIClient reference = new RMIClient();

    }

}

***** ERROR ***************

C:\Documents and Settings\admin>java  com.rm.RMIClient.RMIClient
Attempting to gain reference
Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling retu
rn; nested exception is:
        java.lang.ClassNotFoundException: com.rm.RMIInterface.RMIInterface (no s
ecurity manager: RMI class loader disabled)
        at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
        at com.rm.RMIClient.RMIClient.<init>(RMIClient.java:19)
        at com.rm.RMIClient.RMIClient.main(RMIClient.java:34)
Caused by: java.lang.ClassNotFoundException: com.rm.RMIInterface.RMIInterface (n
o security manager: RMI class loader disabled)
        at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:553)
        at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:6
46)
        at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311
)
        at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStrea
m.java:255)
        at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1558)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1
771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
        ... 3 more

" (no security manager: RMI class loader disabled)"
That looks like the problem. RMI needs a security manager, and that has to grant the necessary permissions. To get things working you can use this common piece of boilerplate that gives you a "permit everything" security manager

      // create a simple security file in a known location, and use that
      final String POLICY_FILE_CONTENT = "grant {\n"
              + "permission java.security.AllPermission;\n" + "};\n";
      try {
         File tempFile = File.createTempFile("rmi-base", ".policy");
         BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
         writer.write(POLICY_FILE_CONTENT);
         writer.close();
         tempFile.deleteOnExit();
         System.setProperty("java.security.policy", tempFile.getAbsolutePath());
         if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
         }
      } catch (IOException e) {
         e.printStackTrace();
      }

Obviously for a production system you would set up a "proper" security manager with just the minimum necessary permissions.

My RMIServer.class already has these security manager .

Or do you want me to use security manager in Client class file ?

Please have a look of my RMIServer class below

package com.rm.server;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import com.rm.RMIInterface.*;

public class RMIServer  implements RMIInterface{
    static Registry registry;




    public RMIServer() throws RemoteException{
        // TODO Auto-generated constructor stub

        //super();
        try{


            //Naming.rebind("test.server", this);
            System.setProperty("java.rmi.server.codebase", RMIInterface.class.getProtectionDomain().getCodeSource().getLocation().toString());

            try {
                 File tempFile = File.createTempFile("rmi-base", ".policy");
                 BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
                 final String POLICY_FILE_CONTENT = "grant {\n"
                         + "permission java.security.AllPermission;\n" + "};\n";
                 writer.write(POLICY_FILE_CONTENT);
                 writer.close();
                 tempFile.deleteOnExit();
                 System.setProperty("java.security.policy", tempFile.getAbsolutePath());
                 System.out.println("inside 2nd try");

                 System.setSecurityManager(new RMISecurityManager());

              } catch (IOException e) {
                  System.out.println("inside ist change");
                 e.printStackTrace();
              }


        }catch(Exception e){
            System.out.println("inside 2nd change");
            System.out.println(e.getMessage());
        }


          try {
              registry = null;
             registry = LocateRegistry.createRegistry(1099);
             System.out.println("inside 3rd try");
          } catch (RemoteException e) {
              System.out.println("Create failed, locating pre-existing registry");
          }
             try {
                 System.out.println("inside 4th try"); 
                registry = LocateRegistry.getRegistry();

             } catch (RemoteException e1) {
                 System.out.println("inside 4th change");
                e1.printStackTrace();
             }
          }


    public static void main(String[] args) {
        // TODO Auto-generated method stub

        RMIInterface stub=null;
        try {

            RMIServer reference = new RMIServer();





              stub = (RMIInterface) UnicastRemoteObject.exportObject(reference, 0);
        registry.rebind("server", stub);
        System.out.println("set");
        }catch(Exception e){
            System.out.println("inside main change");
            System.out.println(e.getMessage());
        }

        try {
            registry.rebind("server", stub);

        }catch(Exception e){

            System.out.println("inside main 2 change");
            System.out.println(e.getMessage());
        }
    }

    @Override
    public String query(String input) {
        // TODO Auto-generated method stub
        return "123";
    }

}

Read the error message - it's the client that's throwing the error. To quote the API doc for RMISecurityManager...
"used by RMI applications that use downloaded code. RMI's class loader will not download any classes from remote locations if no security manager has been set"

It's nothing to do with what I may or may not want! The client won't download from a remote location without a security manager.

I have installed Security manager in RMIClient, and now its throwing classnotfound exception when running my client file stating that RMIInterface class not found.

By this error, I think it could be related to classpath, but if it is a class path issue how can i my client file relate to classpath on other system. I checked my classpath in the machine where the server runs and it looks good.

Classpath and error are below for clarity.

C:\Program Files\Java\jdk1.7.0_21\bin\  : D:\inputs\jgoodies-looks-2.5.3.jar;C:\Users\jacksons5\workspace\rm\bin\;




C:\java com.rm.server.RMIClient



Attempting to gain reference
Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling retu
rn; nested exception is:
        java.lang.ClassNotFoundException: com.rm.server.RMIInterface
         at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
        at com.rm.server.RMIClient.<init>(RMIClient.java:38)
        at com.rm.server.RMIClient.main(RMIClient.java:53)
Caused by: java.lang.ClassNotFoundException: com.rm.server.RMIInterface
         at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
         at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.rmi.server.LoaderHandler$Loader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
         at java.lang.Class.forName(Unknown Source)
        at sun.rmi.server.LoaderHandler.loadClassForName(Unknown Source)
        at sun.rmi.server.LoaderHandler.loadProxyInterfaces(Unknown Source)
        at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source)
         at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source)
        at java.rmi.server.RMIClassLoader$2.loadProxyClass(Unknown Source)
        at java.rmi.server.RMIClassLoader.loadProxyClass(Unknown Source)
         at sun.rmi.server.MarshalInputStream.resolveProxyClass(Unknown Source)
        at java.io.ObjectInputStream.readProxyDesc(Unknown Source)
        at java.io.ObjectInputStream.readClassDesc(Unknown Source)
         at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
        at java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.io.ObjectInputStream.readObject(Unknown Source)
        ... 3 more

Did you set the server's code base...
System.setProperty("java.rmi.server.codebase", path where class files are

ps: I'm away now for a couple of weeks, so good luck!
I'm sure someone else will be able to help in my absence.

I hava a very Basic quesion in RMI which i Dont know, Please advise

While creating an RMI application,
is the Remote interface, Remote Server and RMIClient classes need to be created in the same machine or RMIClient Class can be created in a Different Machine ?

This article has been dead for over six months. Start a new discussion instead.