Создание объектов JNI и управление памятью

У меня есть следующий JNI-метод, который изначально создает коллекцию объектов Java, а затем возвращает их в Java:

JNIEXPORT jobject JNICALL Java_com_test_myClass_myMethod(JNIEnv * env, jclass klass) {
    jclass arrayClass = env->FindClass("java/util/ArrayList");
    jmethodID initMethod = env->GetMethodID(arrayClass, "<init>", "()V");
    jmethodID addMethod = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
    jobject myArray = env->NewObject(arrayClass, initMethod);

    env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("Hello"));
    env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("World"));

    return myArray;
}

Нужно ли мне освобождать объекты, созданные в собственном коде, или это делается автоматически GC? Если я это сделаю, как мне это сделать, поскольку мне нужно вернуть его на Java?

Ответ 1

Вам не нужно освобождать объекты Java, созданные в собственном коде. На самом деле вы не можете. Сборщик мусора может освободить объект, если дальнейшие ссылки не останутся.

Иногда в родном коде полезно использовать бесплатные ссылки на объекты Java. Это может уменьшить требования к памяти, когда собственный код сохраняется, но больше не нужен, ссылки на большие объекты или большое количество ссылок.

От: "Глобальные и локальные ссылки" в спецификации JNI.

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

  • Нативный метод обращается к большому объекту Java, тем самым создавая локальную ссылку на объект Java. Собственный метод затем выполняет дополнительные вычисления перед возвратом вызывающему. Локальная ссылка на большой объект Java будет препятствовать сбору мусора, даже если объект больше не используется в оставшейся части вычисления.
  • Нативный метод создает большое количество локальных ссылок, хотя не все из них используются одновременно. Поскольку виртуальной машине требуется определенное пространство для отслеживания локальной ссылки, создание слишком большого количества локальных ссылок может привести к тому, что система исчерпает память. Например, собственный метод проходит через большой массив объектов, извлекает элементы как локальные ссылки и работает на одном элементе на каждой итерации. После каждой итерации программисту больше не нужна локальная ссылка на элемент массива.

Дополнительная информация предоставлена См. "Освобождение ссылок" в Руководстве для программистов JNI.