Fuite de mémoire lors de l'appel de code java à partir de C en utilisant JNI
J'ai un programme C qui stocke un objet en java store en utilisant JNI. (Avant que quelqu'un demande, en utilisant java store est une exigence ici et je dois écrire un client en C qui serait en mesure d'ajouter et de récupérer les objets de cette boutique).
J'ai fait le programme et a essayé d'ajouter de 100000 objet de taille 1KB. Mais après l'ajout de seulement 50000 objets, je suis "out of memory" des messages (veuillez noter que je suis d'impression de ces 'out of memory' messages à chaque fois que je ne suis pas en mesure d'allouer une nouvelle chaîne de caractères ou un tableau d'octets à l'aide de NewStringUTF et NewByteArray fonctions). À cette époque, ma demande est à l'aide de seulement 80 MO de mémoire. Je n'ai pas le pourquoi de ces méthodes sont retourner NULL. Est-il quelque chose que je suis absent.
En outre, la mémoire continue d'augmenter même si je publie le tableau d'octets et chaîne créée pour java.
Voici le code source.
void create_jvm(void)
{
JavaVMInitArgs vm_args;
JavaVMOption vm_options;
vm_options.optionString = "-Djava.class.path=c:\\Store";
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 1;
vm_args.options = &vm_options;
vm_args.ignoreUnrecognized = 0;
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if(env != null)
{
j_store = (*env)->FindClass(env, "com/store");
if(j_store == null)
{
printf("unable to find class. class name: JStore");
}
}
}
void add(char* key, char* value, int length)
{
jstring j_key = (*env)->NewStringUTF(env, key);
jbyteArray j_value = (*env)->NewByteArray(env, length);
(*env)->SetByteArrayRegion(env, j_value, 0, length, (jbyte *)value);
ret = (*env)->CallStaticBooleanMethod(env, j_store, method_id, j_key, j_value);
if(j_value != null)
{
(*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, 0);
}
if(j_key != null)
{
(*env)->ReleaseStringUTFChars(env, j_key, key);
}
}
La java côté reçoit les données de byte[] et la stocke dans une table de hachage.
Le problème est que chaque fois que le code s'exécute le mémoire ajoute seulement et n'est jamais sorti.
J'ai essayé d'ajouter 1 MO objet et débogué il.
Le processus de la mémoire augmente de 1 MO quand je l'appelle NewByteArray. Mais quand CallStaticBooleanMethod est appelé le processus de la mémoire, augmenter de 4 MO. Et l'appel à ReleaseByteArrayElements ne doivent pas libérer de la mémoire à tous.
Si j'ajoute un autre 1MB objet après cela, puis de la mémoire du processus reste le même quand je l'appelle NewByteArray et augmenter de 1 MO quand je l'appelle CallStaticBooleanMethod mais reste le même quand j'essaie de libérer le tableau d'octets.
Vous devez vous connecter pour publier un commentaire.
Lorsque vous appelez Nouveau... fonctions, vous créez une "référence" - référence à cet objet dans les locaux de la trame de pile. Cela empêche la machine virtuelle Java de GC cet objet alors que vous avez encore besoin d'elle. C'est très bien si vous êtes à la mise en œuvre de certains indigènes de la méthode de son repère local est créé uniquement pour la méthode de la durée des appels. Mais lors de la création d'objet à partir d'un natif java-joint à visser, elle devient liée à ce fil, la trame de pile, qui va être détruit qu'avec ce fil.
Alors, quand vous avez fait avec un objet, vous pouvez appeler DeleteLocalRef() pour dire que vous n'en avez plus besoin. Ou vous pouvez entourer l'ensemble de la méthode add() de la fonction avec une paire de PushLocalFrame()/PopLocalFrame() pour faire un autre local cadre de sa durée.
Le but de les fonctions ReleaseByteArrayElements et ReleaseStringUTFChars n'est pas la suppression de l'objet, mais pour le débloquer après un pointeur a été obtenu avec GetByteArrayElements ou GetStringUTFChars.
Les deux instructions if doit être supprimé.
Oui, j'ai rencontré le même problème.
Mon application java appeler une application C++ par JNI, l'application C++ va commencer un nouveau fil de discussion, et de retour d'appel à une méthode java. Dans le nouveau thread, de nombreux objets ont été créés et le de mémoire augmente rapidement, bien que j'ai utilisé DeleteLocalRef, PushLocalFrame et PopLocalFram.
J'ai trouvé de nombreux objets créés par NewObject méthode ne peut pas être libéré. C'est étrange .
J'ai essayé, tous que vous avez dit.
on doit utiliser DeleteLocalRef méthode après tout jstring a été créé et ne plus l'utiliser.
Newxxx ou CallStaticObjectMethod peut créer jstring,tout doit supprimer.