JNI Attacher/Détacher le thread de gestion de la mémoire
J'ai un JNI Rappel:
void callback(Data *data, char *callbackName){
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
/* start useful code*/
/* end useful code */
jvm->DetachCurrentThread();
}
Quand je le lance comme ça (vide utile de code), j'ai une fuite de mémoire. Si je commenter l'ensemble de la méthode, il n'y a pas de fuite. Quelle est la bonne manière d'attacher /détacher les threads?
Mon processus d'application en temps réel de données audio, de sorte que le fils responsable du traitement des données doit être faite dès que possible afin d'être prêt pour un autre lot. Donc, pour ces rappels, je vais créer de nouveaux threads. Il y a des dizaines ou même des centaines d'entre eux à chaque seconde, ils se fixent à la JVM, une fonction de rappel qui repeint un graphique, de le détacher et de mourir. Est-ce une bonne façon de faire ce genre de choses? Comment gérer la fuite de mémoire?
EDIT: faute de frappe
OK, j'ai créé un mimimal code nécessaire:
package test;
public class Start
{
public static void main(String[] args) throws InterruptedException{
System.loadLibrary("Debug/JNITest");
start();
}
public static native void start();
}
et
#include <jni.h>
#include <Windows.h>
#include "test_Start.h"
JavaVM *jvm;
DWORD WINAPI attach(__in LPVOID lpParameter);
JNIEXPORT void JNICALL Java_test_Start_start(JNIEnv *env, jclass){
env->GetJavaVM(&jvm);
while(true){
CreateThread(NULL, 0, &(attach), NULL, 0, NULL);
Sleep(10);
}
}
DWORD WINAPI attach(__in LPVOID lpParameter){
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
jvm->DetachCurrentThread();
return 0;
}
et quand je lance le VisualJM profiler, j'ai l'habitude, motif en dents de scie, pas de fuite à ce niveau. L'utilisation du tas a culminé à environ 5 MO. Cependant, en observant le processus de l'explorateur montre en effet certains comportements étranges: la mémoire est légèrement à la hausse et à la hausse, 4K, un deuxième pour une minute ou deux et puis soudain, tout cela de mémoire allouée sera en baisse. Ces gouttes ne correspondent pas avec la collecte des ordures (ils se produisent moins souvent et de libérer moins de mémoire que ceux de scie à dents dans le générateur de profils).
Donc, mon meilleur pari est que c'est un OS comportement de manipulation des dizaines de milliers milisecond durée de threads. Fait un peu gourou avoir une explication pour cela?
OriginalL'auteur Jakub Zaverka | 2012-03-09
Vous devez vous connecter pour publier un commentaire.
Plusieurs points sur l'appel de retour en Java à partir de code natif:
En fonction de votre code natif de thread du comportement, vous voudrez peut-être éviter le détachement et, au lieu de stocker des références à tous les threads natifs pour l'élimination de la cessation (même si vous devez le faire, vous pouvez être en mesure de s'appuyer sur l'arrêt de l'application à nettoyer).
Si vous continuez d'attacher et de détacher de threads natifs, la machine virtuelle doit continuellement associé (souvent les mêmes), les discussions avec des objets Java. Certaines VMs peut ré-utiliser les threads, temporairement ou de façon cache mappages pour améliorer les performances, mais vous obtiendrez de meilleurs résultats et un comportement plus prévisible si vous ne comptez pas sur la VM pour le faire pour vous.
Vous pouvez envisager la mise en pool de threads. Faites votre threads de rester plus longtemps et prendre une entrée à partir d'une file d'attente, plutôt que de continuellement de nouvelles zones de frai des threads. Cela permettra de réduire le thread de gestion des frais généraux dans le système d'exploitation et Java.
Si vous êtes en train de faire toutes les nouveautés de Java dans la JNI en dehors de tout appel d'une méthode, vous pouvez également push/pop local cadre autour de ces actions.
Où en êtes-vous de la détection de la fuite? au niveau de l'OS? l'onu collecté des objets Java? natif de la mémoire en dehors de java?
L'exigence de mémoire dans l'explorateur de processus grimpe sans bornes. Si j'omets les attacher/détacher, il reste constante.
OriginalL'auteur technomage
J'ai compris le problème. Il se balançait références locales dans la JNI de code je n'ai pas détruire. Chaque rappel de créer une nouvelle référence locale, entraînant une fuite de mémoire. Quand je me suis converti le local de référence au niveau mondial, afin que je puisse le réutiliser, le problème a disparu.
OriginalL'auteur Jakub Zaverka