Ошибка JRI моста Java-R: R уже инициализирован

Я использую JRI в качестве ведомого для расчета статистики из Java. Вычисления R требуются время от времени, но не слишком часто. Таким образом, я решил создать метод-оболочку для вычислений, который создает новый экземпляр REngine, а также закрывает его в конце. Все работает как шарм при первом вызове метода. К сожалению, повторный вызов вызывает ошибку «R уже инициализирован».

Инициализация:

private static Rengine createEngineInstance(){

        //Initialise R Engine. 
        Rengine re=new Rengine (new String [] {"--vanilla"}, false, new CallbackListener());

        //Wait until REngine-thread is ready
        if (!re.waitForR())
        {
            System.err.println ("Cannot load R. Is the environment variable R_HOME set correctly?");
            System.exit(1);
        }
        return re;
}

Метод обертки:

public static void performR(){

    //Create instance of R engine
    Rengine re = createEngineInstance();

    //Perform some R operations
    re.eval("...");

    re.end();

}

Очевидно, что экземпляр REngine не завершается корректно. Таким образом, мне нужно знать: 1) Есть ли возможность завершить работу REngine и позже снова создать новый экземпляр? Как это работает правильно? Я знаю, что с JRI невозможно запустить несколько потоков R одновременно, но это не то, к чему я стремлюсь. 2) Если это не так, я бы создал один экземпляр, используя шаблон Singleton. Как в этом случае я могу гарантировать, что сеанс R будет закрыт при завершении программы?

Ваша помощь очень ценится! Спасибо!


person Chris    schedule 09.05.2014    source источник
comment
Хотя это не тот ответ, который вы ожидали, попробуйте использовать renjin renjin.org, он не использует R интерпретатор, так что у вас не будет такой проблемы (хотя есть и другие проблемы с этим...)   -  person Yehoshaphat Schellekens    schedule 12.05.2014


Ответы (2)


согласно JRI Javadoc....

Можно использовать только один экземпляр Rengine, и функция Reengine.end() имеет некоторые проблемы...

вы не должны использовать такой код

Rengine engine = new Rengine(new String[] {"--vanilla"}, false, null);

вы можете использовать Reengine с этим кодом

Rengine engine = Rengine.getMainEngine();
if(engine == null)
    engine = new Rengine(new String[] {"--vanilla"}, false, null);
person user3741031    schedule 14.06.2014

Очень старый вопрос, но я бы добавил, что рассмотрение RServe в качестве альтернативы часто бывает привлекательным. Настройка менее сложная (на мой взгляд), а интерфейс почти идентичен.

Подробное руководство приведено здесь. (обратите внимание, что это ссылка waybackmachine (архив), поскольку исходная ссылка устарела - она ​​может загружаться немного медленно, но должна продолжать работать).

Это дает дополнительные преимущества: если вы когда-нибудь захотите вызывать R из параллельных потоков Java, вы сможете это сделать.

person kabdulla    schedule 17.11.2016
comment
Еще очень ценится. Спасибо! - person Chris; 18.11.2016
comment
Ссылка не работает. - person Emadpres; 04.06.2021
comment
@Emadpres, спасибо, что сообщили мне. Я заменил ссылку на waybackmachine. Я также начал вставлять информацию из этого урока сюда, но он довольно длинный. Мы надеемся, что ссылка WBM не сломается. - person kabdulla; 05.06.2021