Как вызвать метод Java через JNI, позволяющий JVM собирать аргументы? - PullRequest
1 голос
/ 31 марта 2019

У меня есть собственное приложение, которое запускает JVM и вызывает некоторые методы через JNI API.

Грубо говоря, собственное приложение:

  1. запускает JVM;
  2. создает новый фрейм с PushLocalFrame;
  3. создает Java-объект x, вызывая конструкторы через JNI;
  4. выскакивает из фрейма с PopLocalFrame(x);
  5. вызывает в JVM долгосрочную функцию foo(x), передавая созданный объект в качестве аргумента с CallObjectMethod;
  6. завершается.

Проблема в том, что в тех же случаях шаг 5 завершается с java.lang.OutOfMemoryError.Это неожиданно, потому что обычно эта функция Java не использует много памяти, когда она вызывается из приложения только для JVM.

Принимая дампы кучи с помощью VisualVM, я обнаружил, что существует много «корней GC (фрейма Java)», которыеЯ не ожидалМое лучшее объяснение состоит в том, что:

  1. foo берет некоторые поля из x и сохраняет в них вещи;
  2. во время выполнения foo JVM не может собирать мусорx и все, что в нем хранится транзитивно.

Итак, существует ли способ вызова метода Java через интерфейс JNI, позволяющий JVM-сборщику мусора аргументы?

Слабые глобальные ссылки - это почти то, что я хочу, но я не понимаю, как их использовать, потому что в теории они могут быть собраны мусором сразу после создания, прежде чем они будут переданы какаргумент в вызове функции.

1 Ответ

0 голосов
/ 31 марта 2019

При работе с собственными ресурсами вы не должны рассчитывать на сборку мусора для освобождения памяти.

Вместо этого реализуйте интерфейс Closable для каждого Java-класса, который переносит собственный объект или дескриптор, и обязательно закрывайте каждый объект перед разыменованием его.

Вы можете использовать синтаксис try (<Allocate Closables Here>) { <Use Them Here> } для автоматического закрытия объектов.

...