title: Java RMI ClassNotFoundException on the client side
body: <p>There have been several questions with this same Title, but none of them have helped me solve my issue.</p>
  
  <p>I have been trying to follow the tutorial here:
  <a href="https://docs.oracle.com/javase/tutorial/rmi/overview.html" rel="nofollow">https://docs.oracle.com/javase/tutorial/rmi/overview.html</a></p>
  
  <p>I was driving myself crazy by putting everything in one project, so I've created 3 separate projects:</p>
  
  <ol>
  <li>Server -> It has Main (Driver), and class:ServerNode implements Compute</li>
  <li>Client -> It has Main (Driver), and class:TestTask implements Task</li>
  <li>Shared -> It has interface:Task, and interface:Compute </li>
  </ol>
  
  <p>The idea is... both applications need to know about the Interfaces Task (The unit of work the client sends to the server), and Compute (Which is the interface of ServerNode that the client uses to give commands to).</p>
  
  <p>Server Code:</p>
  
  <pre><code>System.setProperty("java.security.policy","file:server.policy");
      System.out.println(System.getProperty("java.security.policy"));
  
      if (System.getSecurityManager() == null) {
          System.setSecurityManager(new SecurityManager());
      }
      int port = 1099;
      try {
          LocateRegistry.createRegistry(port);
          String name = "Compute"; // Name of the interface
          Compute engine = new ServerNode(); // Implementor of Compute interface, ComputeEngine
          Compute stub =
                  (Compute) UnicastRemoteObject.exportObject(engine, 0); // Create the stub the client will use
          Registry registry = LocateRegistry.getRegistry(port);
          registry.bind(name, stub);   // Bind the "Compute" to the stub, so client can access it by "Compute"
          System.out.println("ComputeEngine bound");
      } catch (Exception e) {
          System.err.println("ComputeEngine exception:");
          e.printStackTrace();
      }
  </code></pre>
  
  <p>Client Code:</p>
  
  <pre><code>System.out.println("Entering client");
      String lookupName = "localhost";
      System.setProperty("java.security.policy","file:client.policy");
      System.out.println(System.getProperty("java.security.policy"));
      System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");
      System.out.println(System.getProperty("rmi.server.codebase"));
      if (System.getSecurityManager() == null) {
          System.setSecurityManager(new SecurityManager());
      }
      try {
          String name = "Compute";
  
  
  
          Registry registry = LocateRegistry.getRegistry("localhost", 1099);
  
          Compute comp99 = (Compute)registry.lookup("Compute");
  
          System.out.println(comp99.executeTask(new TestTask()));
  
      } catch (Exception e) {
          System.err.println("ComputePi exception:");
          e.printStackTrace();
      }
  </code></pre>
  
  <p>I am led to believe, from the tutorial
  That only the CLIENT needs to know about TestTask... It doesn't/shouldn't need to go in Shared. The server just needs to know about the interface Task and the client gives it an implementor of that interface... I believe in the background the server downloads the concrete code from the clients codebase. </p>
  
  <p>My directory structure is
  1. Documents/RMI_ServiceSide
  2. Documents/RMI_ClientSide
  3. Documents/RMI_Shared</p>
  
  <p>Right now I am programmatically starting up the rmiregister in the server code, instead of running it on the command line. I don't think that's my problem, but at this point (after 4 hours of debugging) I have no idea. I am able to start the server though with that code.</p>
  
  <p>The problem is on the client side. When I try to run the client code, I get:</p>
  
  <pre><code>Entering client
  file:client.policy
  file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class
  ComputePi exception:
  java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
      java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
      java.lang.ClassNotFoundException: com.company.TestTask
      at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:355)
      at sun.rmi.transport.Transport$1.run(Transport.java:200)
      at sun.rmi.transport.Transport$1.run(Transport.java:197)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
      at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
      at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
      at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
      at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:162)
      at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227)
      at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179)
      at com.sun.proxy.$Proxy0.executeTask(Unknown Source)
      at com.company.Main.main(Main.java:46)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
  Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
      java.lang.ClassNotFoundException: com.company.TestTask
      at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:315)
      at sun.rmi.transport.Transport$1.run(Transport.java:200)
      at sun.rmi.transport.Transport$1.run(Transport.java:197)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
      at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
  Caused by: java.lang.ClassNotFoundException: com.company.TestTask
  </code></pre>
  
  <p>Alright, it appears that when I try to execute the TestTask, the Registry comes back that it can't find it. I have tried every possible combination of paths for the -Djava.rmi.server.codebase=file:/c:/Users/Brian/Documents/RMI_ClientSide/   command line argument AND/OR the System.setProperty("rmi.server.codebase", "file:/c:/Users/Brian/Documents/RMI_ClientSide/TestTask.class");</p>
  
  <p>Absolutely nothing seems to work... I don't know if this is an issue with the rmiregistry or if I just didn't hit the correct permutation on my codebase. This is all on one machine, so I don't know why it is having problems finding it. </p>
  
  <p>To be explicit... The files that would be necessary:
  1. Client -> RMI_ClientSide/bin/.../Main.class and TestTask.class
  2. Server -> RMI_ServerSide/bin/..Main.class and ServerNode.class
  3. Shared -> RMI_Shared/bin/.../RMI_Shared.jar -> contains Task.class and Compute.class</p>
  
  <p>As I said, these are three separate projects, BUT the package name is the same... package com.company; Just by coincidence, I didn't rename the default when creating each project. I don't know if that matters either. Certainly didn't when importing RMI_Shared.jar into server and client projects... they both compiled fine. </p>
  
  <p>One other answer I found gave the impression Shared would need to contain the TestTask too... but that doesn't make sense as the registry should pull the class definition up to the server when needed... That way a client can execute arbitrary code up to the server (Which is intended in this simple insecure test). </p>
  
  <p>I would appreciate any help to get this running. Thanks!</p>
  
  <p>EDIT: Added a link to my codebase folder image
  <a href="http://i.stack.imgur.com/b2p8p.png" rel="nofollow">Codebase directory</a></p>
  
  <p>Note that the directories for my projects themselves are just documents/. Client, server, and helper. </p>