Документация JNI по этому вопросу мягкая.Я обнаружил на практике, что иногда количество локальных ссылок кажется неограниченным, но вы действительно можете исчерпать локальные ссылки, например, при переборе массива с использованием вызовов JNI.Что такое местная ссылка?Это рабочий объект (или jarray, jstring и т. Д.), Который вы получаете из любого из следующих источников:
- Возвращается из необработанного вызова JNI, такого как NewObjectV () или GetObjectArrayElement ()
- Возвращено из вызова метода, такого как CallObjectMethodV ()
- Передано в вашу нативную функцию в качестве аргумента
- Вероятно, другие, которые я забыл
Из них вам обычно нужноне беспокойтесь о ссылках, которые передаются вам в аргументе метода, ЕСЛИ вы не намерены хранить ссылку за пределами текущего вызова метода, и в этом случае вы должны преобразовать ее в глобальную.
Стоит отметить, чтоВы не должны висеть на локальной ссылке за пределами текущей области метода.Если вы собираетесь хранить его в объекте C ++, вы должны преобразовать его в глобальный.Локальные ссылки имеют два преимущества:
- Они всегда освобождаются автоматически, когда текущий кадр выходит из области видимости.
- Они быстрее, чем конвертируются в глобальные
Как и большинство ошибок JNI, любое неправильное использование ссылок ужасно диагностировать, поэтому вы действительно не хотите их получать.Ваша лучшая защита - последовательный подход.По моему опыту, стоимость преобразования локального в глобальный довольно мала.Я бы предложил следующее, если только у вас нет очень строгих требований к производительности.
Учитывая это, мое правило - ВСЕГДА преобразовывать локальные ссылки в глобальные ссылки, используя такой код:
jobject localjo = ...
jobject globaljo = env->NewGlobalRef(localjo);
env->DeleteLocalRef(localjo);
На этом этапевы можете знать, что каждый ref является глобальным, и когда вы закончите, вам нужно помнить, что нужно выполнить env-> DeleteGlobalRef (globaljo) для каждого.В C ++ можно написать класс-оболочку вокруг ссылок JNI, который вызывает env-> DeleteGlobalRef () в dtor.Но так как JNI не подсчитывает ссылки JNI для вас, вам, возможно, потребуется встроить это.