RMI NoSuchObjetcException: такого объекта нет в таблице - PullRequest
0 голосов
/ 11 апреля 2020

Я потратил довольно много времени, пытаясь решить эту проблему, и, похоже, я ничего не получил. Из моего исследования, кажется, что это повторяющаяся проблема при использовании RMI. В основном у меня есть Сервер и Клиент, и связь между Клиентом и сервером осуществляется через объект RMI.

Вот код для Клиента

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

public class Client{

    static private RMIDecoder rmi_name = new RMIDecoder();
    private static Registry registry;
    private static Communication stub;

    private Client() {}

    public static void main(String args[]){


        try {
            int port = 1099 + rmi_name.getId(args[0]);
            registry = LocateRegistry.getRegistry(port);
            stub = (Communication) registry.lookup(args[0]); //object name as argument


            if(args[1].equals("BACKUP")){
                System.out.println(stub.backup(args[2], Integer.parseInt(args[3])));
            }
            else {
                System.out.println(stub.restore(args[2]));
            }



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

}

А вот код для сервера

public class Server implements Communication {

    static private Hashtable<String, ChunkInfo> file_info = new Hashtable<>();

    static private RMIDecoder rmi_name = new RMIDecoder();
    static private MulticastSocket mc = null;
    static private DatagramSocket mdb = null;
    static private MulticastSocket mdr = null;
    static private String server_id;
    static private FileHandler file_handler = new FileHandler();
    static private Utils utility = new Utils();
    static private Network network = new Network();
    private static Registry registry;
    private static Communication stub;

    public Server(){
        mc = network.initiateMC();
        mdb = network.initiateMDB();
        mdr = network.initiateMDR();

        new File(".\\PEER" + server_id).mkdir();
    }

    //COMMUNICATION INTERFACE FUNCTIONS IMPLEMENTATION
    public String backup(String filename, int repDegree){

        storeInfo(filename);
        Thread backup = new Thread(new BackupInit(filename, repDegree, server_id));
        backup.start();


        return "Backing up " + filename;
    }

    public String restore(String filename){

        Thread restore = new Thread(new RestoreInit(filename, file_info.get(filename), server_id));
        restore.run();
        return filename + " has been restored successfully.";
    }

    public static void main(String args[]){

        server_id = args[0];

        Thread mc_listener = new Thread(new MCListener(mc, server_id));
        Thread mdb_listener = new Thread(new MDBListener(server_id));
        mc_listener.start();
        mdb_listener.start();

        try{
            Server obj = new Server();
            stub = (Communication) UnicastRemoteObject.exportObject(obj, 0);

            //Bind the remote object's stub in the registry
            int port = 1098 + Integer.parseInt(args[0]);
            registry = LocateRegistry.createRegistry(port);
            registry.bind(rmi_name.getName(Integer.parseInt(args[0]) - 1), stub);
        }
        catch (Exception e){
            e.printStackTrace();
        }


    }

    private void storeInfo(String filename){
        String fileId = file_handler.getFileId(filename);
        double totalChunkNr = file_handler.getNumberOfChunks(filename);

        ChunkInfo chunkInfo = new ChunkInfo(fileId);
        chunkInfo.setTotalChunks(totalChunkNr);

        file_info.put(filename, chunkInfo);
    }



}

Мой интерфейс связи

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

public interface Communication extends Remote{

    String backup(String filename, int repDegree) throws RemoteException;

    String restore(String filename) throws RemoteException;
}

И, наконец, созданный мною класс под названием RMIDecoder

import java.util.Vector;

public class RMIDecoder {

    static Vector<String> rmi_name = new Vector<>();

    public RMIDecoder(){
        fillRMITable();
    }

    void fillRMITable(){
        rmi_name.add("alpha");
        rmi_name.add("bravo");
        rmi_name.add("charlie");
        rmi_name.add("delta");
        rmi_name.add("echo");
        rmi_name.add("foxtrot");
    }

    String getName(int index){
        return rmi_name.elementAt(index);
    }

    int getId(String name){
        return rmi_name.indexOf(name);
    }
}

Итак, я запускаю шесть серверов, каждый из которых как «java Server x», где x - это цифра c id сервера. У каждого идентификатора есть имя, которое он будет использовать для имени объекта rmi (оно следует из алфавита phoneti c НАТО, альфа для 1, браво для 2 и т. Д. c.). Реестр создается в классе Server с уникальным портом и соответствующим именем. В классе Client вместо этого я использую getRegistry, поскольку предполагается, что сервер, с которым я буду общаться через RMI, уже создан. Клиент называется «java Client name_of_rmi_obj ...», где name_of_rmi_obj может быть альфа / bravo / charl ie et c ..

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

Из того, что я прочитал, важно убедиться, что как используемые заглушки, так и реестр являются stati c и переменными класса, поэтому сборщик мусора не подхватывает их, поэтому я тоже это сделал. Я считаю, что приведенного здесь кода достаточно, чтобы раскрыть мою проблему, но если я не смог что-то показать, пожалуйста, дайте мне знать. Спасибо.

...