У меня есть собственное приложение, которое запускает JVM и вызывает некоторые методы через JNI API.
Грубо говоря, собственное приложение:
- запускает JVM;
- создает новый фрейм с
PushLocalFrame
; - создает Java-объект
x
, вызывая конструкторы через JNI; - выскакивает из фрейма с
PopLocalFrame(x)
; - вызывает в JVM долгосрочную функцию
foo(x)
, передавая созданный объект в качестве аргумента с CallObjectMethod
; - завершается.
Проблема в том, что в тех же случаях шаг 5 завершается с java.lang.OutOfMemoryError
.Это неожиданно, потому что обычно эта функция Java не использует много памяти, когда она вызывается из приложения только для JVM.
Принимая дампы кучи с помощью VisualVM, я обнаружил, что существует много «корней GC (фрейма Java)», которыеЯ не ожидалМое лучшее объяснение состоит в том, что:
foo
берет некоторые поля из x
и сохраняет в них вещи; - во время выполнения
foo
JVM не может собирать мусорx
и все, что в нем хранится транзитивно.
Итак, существует ли способ вызова метода Java через интерфейс JNI, позволяющий JVM-сборщику мусора аргументы?
Слабые глобальные ссылки - это почти то, что я хочу, но я не понимаю, как их использовать, потому что в теории они могут быть собраны мусором сразу после создания, прежде чем они будут переданы какаргумент в вызове функции.