ReleaseStringUTF делает больше, чем свободная память? - PullRequest
2 голосов
/ 13 марта 2010

Рассмотрим следующие сегменты кода C.

Сегмент 1:

char * getSomeString(JNIEnv *env, jstring jstr) {
   char * retString;
   retString = (*env)->GetStringUTFChars(env, jstr, NULL);
   return retString;
}

void useSomeString(JNIEnv *env, jobject jobj, char *mName) {
   jclass cl = (*env)->GetObjectClass(env, jobj);
   jmethodId mId = (*env)->GetMethodID(env, cl, mName, "()Ljava/lang/String;");
   jstring jstr = (*env)->CallObjectMethod(env, obj, id, NULL);

   char * myString = getSomeString(env, jstr);

/* ... use myString without modifing it */

   free(myString);
}

Поскольку myString освобождается в useSomeString, я не думаю, что создаю утечку памяти; Однако я не уверен. Спецификация JNI специально требует использования ReleaseStringUTFChars. Поскольку я получаю указатель char * в стиле C от GetStringUTFChars, я полагаю, что ссылка на память существует в стеке C, а не в куче JAVA, поэтому она не находится в опасности сбора мусора; однако я не уверен.

Я знаю, что изменение getSomeString следующим образом будет безопаснее (и, вероятно, предпочтительнее).

Сегмент 2:

char * getSomeString(JNIEnv *env, jstring jstr) {
   char * retString;
   char * intermedString;

   intermedString = (*env)->GetStringUTFChars(env, jstr, NULL);
   retString = strdup(intermedString);
   (*env)->ReleaseStringUTFChars(env, jstr, intermedString);
   return retString;
}

Из-за нашего «процесса» мне нужно построить аргумент о том, почему getSomeString в Сегменте 2 предпочтительнее Сегмента 1.

Кто-нибудь знает о какой-либо документации или ссылках, в которых подробно описывается поведение GetStringUTFChars и ReleaseStringUTFChars в зависимости от того, где выделена память или что (если есть) выполняется дополнительная бухгалтерия (т. Е. Указатель локальной ссылки на создаваемую кучу Java и т. Д.) , Каковы конкретные последствия игнорирования этой бухгалтерии.

Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 13 марта 2010

Вам не нужно заботиться о деталях реализации; если документация GetStringUTFChars говорит вам, что вы должны использовать ReleaseStringUTFChars, вы делаете это, точка.

Большинство библиотек предоставляют свои собственные функции для освобождения памяти, которую они выделяют, потому что их CRT / heap / ... может отличаться от той, что используется в вашем приложении, поэтому, если вы попытаетесь использовать ваше free on их указателей вы можете получить на своей стороне эквивалент двойного освобождения, а на стороне библиотеки - утечку памяти.

Скажу еще раз: не полагайтесь на детали реализации . Авторы библиотеки уверены, что все следуют их указаниям, поэтому даже если сегодня может работать free , завтра они могут решить использовать другую кучу / распределитель / ... Если вы следовали их рекомендациям, у вас не возникнет никаких проблем. проблема в том, что они соответствующим образом обновили бы ReleaseStringUTFChars, но если бы вы вдруг обратились к деталям реализации, ваше приложение может внезапно начать умирать или иметь утечки памяти.

1 голос
/ 25 марта 2010

То, что мы наконец-то обнаружили.

Приложение, связывающее Java и C, будет совместно использовать пространство кучи. Это подразумевает, что любая память, выделенная на стороне C вещей с помощью malloc (и др.), Не может быть выделена в разделе кучи, зарезервированной для Java. Однако любая память, выделенная самими функциями JNI, может выделять или не выделять пространство на стороне Java кучи (это деталь реализации JNI). Это оставляет две возможности: 1) память выделяется со стороны C кучи, где вызов free не оставляет вредных последствий; 2) память, выделенная со стороны Java, открывает возможность восстановления памяти GC до того, как сторона C покончит с этим. Перед лицом этой неопределенности самый безопасный способ - это явно выделить новое пространство с помощью malloc, освободить память JNI и освободить вызов, когда вновь выделенная память больше не нужна.

Я хотел бы поблагодарить Matteo Italia за его помощь в этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...