Q:

RMI - как передать на сервер объект и вызвать на сервере метод этого объекта

Есть какой-то интерфейс.
    public interface stub extends Remote, Serializable{
        public void print() throws RemoteException;
        public void setRequest(Request request) throws RemoteException;
    }

Его реализация на сервере
public class RealizationStub implements stub {
    public boolean set = false;
    public Request request;
    @Override
    public void print() throws RemoteException {
        System.out.println("Печатать");
    }

    @Override
    public void setRequest(Request request) throws RemoteException {
        System.out.println("Установлен ответ");
        set = true;
        this.request = request;
    }
}

Некий интерфейс ответа от клиента.
public interface Request extends Serializable {
    void run();
}

Его реализация в клиенте.
public class RequestRunner implements Request {
    @Override
    public void run() {
        System.out.println("Выполнилась");
    }
}

Запускаю сервер так:
public class Test {
    public static void main(String[] args) {
        final int PORT = 2222;
        stub stub;
        RealizationStub realizationStub = null;
        try {
            Registry registry = LocateRegistry.createRegistry(PORT);
            realizationStub = new RealizationStub();
            stub = realizationStub;
            UnicastRemoteObject.exportObject(stub, PORT);
            registry.bind("stub", stub);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }
        System.out.println("Сервер стартовал");
        while (true) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (realizationStub.set) {
                realizationStub.request.run();
            }
        }
    }
}

Клиент запускаю так:
public class Test {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry(null, 2222);
            stub stub = (stub) registry.lookup("stub");
            stub.print();
            stub.setRequest(new RequestRunner());
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (NotBoundException e) {
            e.printStackTrace();
        }
    }
}

У клиента вылетает ошибка на строчке SetRequest:

java.rmi.ServerException: RemoteException occurred in server thread;
  nested exception is:      java.rmi.UnmarshalException: error
  unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: actions.RequestRunner (no security
  manager: RMI class loader disabled)

Что вообще я хочу сделать, я хочу при подключении клиента к серверу отправлять ему какой-то объект какого-то класса, который смогу потом использовать на сервере.

A:

Чтобы клиент и сервер RMI могли обмениваться объектами, понадобится:

Назначить им обоим менеджер безопасности;
Обеспечить кодовую базу, откуда они смогут брать необходимые классы;
Указать им, где эту кодовую базу искать.

Кроме того, менеджеру безопасности понадобится политика этой самой безопасности. Начнём с серверной стороны:
Hello.java (удалённый интерфейс)
package com.example;

import java.rmi.Remote; 
import java.rmi.RemoteException;  

public interface Hello extends Remote {
    String greet(User user) throws RemoteException;
}

HelloImpl.java
package com.example;

public class HelloImpl implements Hello {  
    public String greet(User user) {
        String name = user.getName();
        System.out.println("Call from " + name);
        return "Hello " + name + "!";
    }  
}

Server.java
package com.example;

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class Server extends HelloImpl {
    public Server() {}

    public static void main(String args[]) {
        System.setSecurityManager(new SecurityManager()); // Пункт 1
        try {
            HelloImpl greeter = new HelloImpl();

            Hello stub = (Hello) UnicastRemoteObject.exportObject(greeter, 0);

            Registry registry = LocateRegistry.getRegistry();

            registry.rebind("Hello", stub);

            System.out.println("Server ready");
        }
        catch (Exception e) {
            System.err.println("Server exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

server.policy
grant {
    permission java.net.SocketPermission "127.0.0.1:1099", "connect,resolve";
    permission java.net.SocketPermission "127.0.0.1:1024-65535", "connect,accept,resolve";
};

Клиентская сторона:
User.java (интерфейс передаваемого объекта)
package com.example;

import java.io.Serializable;

public interface User extends Serializable {
    String getName();
}

UserImpl.java
package com.example;

public class UserImpl implements User {
    private String name;

    public UserImpl() {}

    public UserImpl(String name) {
        setName(name);
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Client.java
package com.example;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.Naming; 

public class Client {
    private Client() {}

    public static void main(String[] args) {
        System.setSecurityManager(new SecurityManager());
        try {
            Hello stub = (Hello) Naming.lookup("//localhost/Hello");

            User user = new UserImpl(args[0]);

            System.out.println(stub.greet(user));
        }
        catch (Exception e) {
            System.err.println("Client exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

client.policy
grant {
    permission java.net.SocketPermission "127.0.0.1", "connect,resolve";
};

Компилируем код обеих сторон. Клиентской стороне понадобится иметь в CLASSPATH только Hello.class из кода серверной стороны. И складываем все class-файлы в какой-нибудь общий каталог для организации кодовой базы. У меня это выглядит так:
├───client
│   │   Client.java
│   │   client.policy
│   │   User.java
│   │   UserImpl.java
│   │
│   └───com
│       └───example
│               Client.class
│               Hello.class
│               User.class
│               UserImpl.class
│
├───codebase
│   └───com
│       └───example
│               Client.class
│               Hello.class
│               HelloImpl.class
│               Server.class
│               User.class
│               UserImpl.class
│
└───server
    │   Hello.java
    │   HelloImpl.java
    │   Server.java
    │   server.policy
    │
    └───com
        └───example
                Hello.class
                HelloImpl.class
                Server.class
                User.class

Естественно, корень может не быть общим. Клиент, сервер и кодовая база могут вообще располагаться на разных серверах.
Самый простой способ обеспечить доступность кодовой базы для разных сетевых узлов - http-протокол. Запускаем web-сервер для обслуживания каталога codebase.
Запускаем rmiregistry в каталоге server.
Запускаем сам сервер командой
java -Djava.security.policy=server.policy -Djava.rmi.server.codebase=http://localhost:8000/ com.example.Server

Ключ java.security.policy указывает, где менеджер безопасности должен искать политику, а ключ java.rmi.server.codebase где искать недостающие классы.
И запускаем клиент командой 
java -Djava.security.policy=client.policy -Djava.rmi.server.codebase=http://localhost:8000/ com.example.Client Test

Клиент и сервер должны вывести необходимые строки, а в логе web-сервера должна появится запись типа
127.0.0.1 - - [14/Dec/2017 21:54:20] "GET /com/example/UserImpl.class HTTP/1.1" 200 -

означающая, что сервер скачал UserImpl.class, чтобы инстанцировать переданный клиентом объект этого типа.
Классы можно упаковать в один jar-файл и указывать его как кодовую базу, тогда соответствующий ключ будет выглядеть так
-Djava.rmi.server.codebase=http://localhost:8000/code.jar

P.S. Если у вас под рукой нет web-сервера для экспериментов, можно буквально в несколько строк накидать свой:
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.net.URI;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.Headers;

public class WebServer {
    private static final int DEFAULT_PORT = 8000;

    public static void main(String[] args) throws Exception {
        int port = DEFAULT_PORT;
        if (args.length > 0)
            port = Integer.valueOf(args[0]);

        File file = new File(".");
        String cwdPath = file.getAbsolutePath();

        HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
        server.createContext("/", new CodeHandler(cwdPath));
        server.setExecutor(null);
        server.start();
    }

    static class CodeHandler implements HttpHandler {
        private static final int BUFFER_SIZE = 512;
        private final String codeBase;

        public CodeHandler(String path) {
            codeBase = path;
        }

        private static String getExtension(File file) {
            String fileName = file.getName();
            if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0)
                return fileName.substring(fileName.lastIndexOf(".") + 1);
            else
                return "";
        }

        @Override
        public void handle(HttpExchange t) throws IOException {
            URI uri = t.getRequestURI();
            String contentPath = uri.getPath();
            File file = new File(codeBase + contentPath).getCanonicalFile();

            try (OutputStream os = t.getResponseBody()) {
                if (!file.isFile()) {
                    String response = "Not found\n";
                    t.sendResponseHeaders(404, response.length());
                    os.write(response.getBytes());
                }
                else {
                    String mimeType = null;
                    switch(getExtension(file)) {
                        case "class":
                            mimeType = "application/java";
                            break;
                        case "jar":
                            mimeType = "application/java-archive";
                            break;
                        default:
                            String response = "Unsupported Media Type\n";
                            t.sendResponseHeaders(415, response.length());
                            os.write(response.getBytes());
                            return;
                    }
                    Headers headers = t.getResponseHeaders();
                    headers.set("Content-Type", mimeType);
                    t.sendResponseHeaders(200, file.length());
                    try (FileInputStream fs = new FileInputStream(file)) {
                        int count = 0;
                        byte[] buffer = new byte[BUFFER_SIZE];
                        while ((count = fs.read(buffer)) >= 0) {
                            os.write(buffer, 0, count);
                        }
                    }
                }
            }
        }
    }
}

Только в бою его не используйте.

