java.rmi. NoSuchObjectException: никакой такой объект в таблице

В настоящее время нет специальных аналитических инструментов с открытым исходным кодом для Расы. Я предлагаю либо использовать постоянный трекер хранилище , например, Mongo или подключите посредник событий , например, RabbitMq, в Rasa Core и храните потоковые события, как вам нравится. Затем вы можете написать запросы или визуализировать данные с помощью таких инструментов, как Прометей и Графана.

27
задан Greg Mattes 11 December 2009 в 14:48
поделиться

3 ответа

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

Ниже приведена короткая программа, демонстрирующая исключение java.rmi.NoSuchObjectException . Скрипт самодостаточен, создание реестра RMI, а также «клиента» и «сервера» в одной JVM.

Просто скопируйте этот код и сохраните его в файле с именем RMITest.java . Скомпилируйте и вызовите с выбранными аргументами командной строки:

  • -gc (по умолчанию) Явно проинструктируйте JVM приложить «максимальные усилия» для запуска сборщика мусора после запуска сервера, но до того, как клиент подключится к сервер. Это, вероятно, приведет к удалению объекта Remote сборщиком мусора , если сильная ссылка на объект Remote будет освобождена . Исключение java.rmi.NoSuchObjectException наблюдается, когда клиент подключается после восстановления удаленного объекта .
  • -nogc Не запрашивать явно сборку мусора. Это, вероятно, приведет к тому, что объект Remote останется доступным для клиента независимо от того, удерживается или освобождается сильная ссылка , если не будет достаточной задержки между запуском сервера и клиентский вызов, так что система "естественным образом" вызывает сборщик мусора и восстанавливает объект Remote .
  • -hold Сохранять надежную ссылку на объект Remote . В этом случае переменная класса ссылается на объект Remote .
  • -release (по умолчанию) Будет выпущена сильная ссылка на объект Remote . В этом случае переменная метода ссылается на объект Remote . После возврата метода сильная ссылка теряется.
  • -delay Количество секунд ожидания между запуском сервера и вызовом клиента. Вставка задержки дает время для «естественного» запуска сборщика мусора. Это имитирует процесс, который изначально «работает», но перестает работать по прошествии некоторого значительного времени. Обратите внимание, что перед числом секунд нет пробела. Пример: -delay5 вызовет клиентский вызов через 5 секунд после запуска сервера.

Поведение программы, вероятно, будет отличаться от машины к машине и от JVM к JVM, потому что такие вещи, как System.gc () - это только подсказки, а установка параметра -delay - это игра в угадывание поведения сборщика мусора.

На моей машине после javac RMITest.java для компиляции, я вижу следующее поведение:

$ java RMITest -nogc -hold
received: foo
$ java RMITest -nogc -release
received: foo
$ java RMITest -gc -hold
received: foo
$ java RMITest -gc -release
Exception in thread "main" java.rmi.NoSuchObjectException: no such object in table
    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 java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
    at $Proxy0.remoteOperation(Unknown Source)
    at RMITest.client(RMITest.java:69)
    at RMITest.main(RMITest.java:46)

Вот исходный код:

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import static java.util.concurrent.TimeUnit.*;

interface RemoteOperations extends Remote {
    String remoteOperation() throws RemoteException;
}

public final class RMITest implements RemoteOperations {
    private static final String REMOTE_NAME = RemoteOperations.class.getName();
    private static final RemoteOperations classVariable = new RMITest();

    private static boolean holdStrongReference = false;
    private static boolean invokeGarbageCollector = true;
    private static int delay = 0;

    public static void main(final String... args) throws Exception {
        for (final String arg : args) {
            if ("-gc".equals(arg)) {
                invokeGarbageCollector = true;
            } else if ("-nogc".equals(arg)) {
                invokeGarbageCollector = false;
            } else if ("-hold".equals(arg)) {
                holdStrongReference = true;
            } else if ("-release".equals(arg)) {
                holdStrongReference = false;
            } else if (arg.startsWith("-delay")) {
                delay = Integer.parseInt(arg.substring("-delay".length()));
            } else {
                System.err.println("usage: javac RMITest.java && java RMITest [-gc] [-nogc] [-hold] [-release] [-delay<seconds>]");
                System.exit(1);
            }
        }
        server();
        if (invokeGarbageCollector) {
            System.gc();
        }
        if (delay > 0) {
            System.out.println("delaying " + delay + " seconds");
            final long milliseconds = MILLISECONDS.convert(delay, SECONDS);
            Thread.sleep(milliseconds);
        }
        client();
        System.exit(0); // stop RMI server thread
    }

    @Override
    public String remoteOperation() {
        return "foo";
    }

    private static void server() throws Exception {
        // This reference is eligible for GC after this method returns
        final RemoteOperations methodVariable = new RMITest();
        final RemoteOperations toBeStubbed = holdStrongReference ? classVariable : methodVariable;
        final Remote remote = UnicastRemoteObject.exportObject(toBeStubbed, 0);
        final Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        registry.bind(REMOTE_NAME, remote);
    }

    private static void client() throws Exception {
        final Registry registry = LocateRegistry.getRegistry();
        final Remote remote = registry.lookup(REMOTE_NAME);
        final RemoteOperations stub = RemoteOperations.class.cast(remote);
        final String message = stub.remoteOperation();
        System.out.println("received: " + message);
    }
}
67
ответ дан 28 November 2019 в 04:24
поделиться

Некоторые другие вопросы рассмотреть - Сначала Вы ссылаетесь на экземпляр объекта, или тупик является интерфейсом, который самим уводят? Если некоторого экземпляра объекта не стало, по обычным причинам, он был разыменован и GC'd, но если это - интерфейс тогда Ваш выход цикла конечной точки сервера RMI по некоторым причинам.

лучшее средство отладки, которое я нашел до сих пор, состоит в том, чтобы включить свойство Java rmi.server.logCalls=true (см. http://java.sun.com/j2se/1.5.0/docs/guide/rmi/javarmiproperties.html ), и наблюдайте весь замечательный поток информации вниз Ваше окно журнала. Это говорит мне, что является каждым разом.

jos

8
ответ дан jottos 28 November 2019 в 04:24
поделиться

Трудно ответить на этот вопрос, не смотря на код (который я предполагаю, будет достаточно большим, чтобы не быть пригодным для печати здесь). Однако с помощью бритвы Оккама, у Вас есть два possibilies

  • Серверный объекты должны становиться незарегистрированными так или иначе
  • Так как точки останова останавливают ошибки, это - определенно состояние состязания.

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

0
ответ дан talonx 28 November 2019 в 04:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: