Mam JNI oddzwaniania:JNI Attach/Odłącz zarządzanie pamięcią wątek
void callback(Data *data, char *callbackName){
JNIEnv *env;
jvm->AttachCurrentThread((void **)&env, NULL);
/* start useful code*/
/* end useful code */
jvm->DetachCurrentThread();
}
Gdy go tak (pusty użytecznego kodu), pojawia się przeciek pamięci. Jeśli skomentuję całą metodę, nie ma wycieku. Jaki jest właściwy sposób dołączania/odłączania wątków?
Moja aplikacja przetwarza dane dźwiękowe w czasie rzeczywistym, więc wątki odpowiedzialne za przetwarzanie danych muszą zostać wykonane tak szybko, jak to możliwe, aby być gotowym na kolejną partię. Tak więc dla tych wywołań zwrotnych tworzę nowe wątki. W każdej sekundzie są ich dziesiątki lub nawet setki, dołączają się do JVM, wywołują funkcję zwrotną, która odświeża wykres, odrywa się i ginie. Czy to jest właściwy sposób robienia tego? Jak radzić sobie z nieszczelną pamięcią?
EDIT: literówka
OK Stworzyłem mimimal kod potrzebny:
package test;
public class Start
{
public static void main(String[] args) throws InterruptedException{
System.loadLibrary("Debug/JNITest");
start();
}
public static native void start();
}
i
#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;
}
i kiedy uruchomić profilera VisualJM, pojawia się zwykle piłokształtny wzór, nie ma tam przecieku. Wykorzystanie sterty osiągnęło wartość około 5 MB. Obserwowanie eksploratora procesu pokazuje jednak pewne dziwne zachowanie: pamięć powoli rośnie i rośnie, 4K sekunda na minutę, a potem nagle cała ta przydzielona pamięć spada. Krople te nie odpowiadają zbieraniu śmieci (występują rzadziej i zwalniają mniej pamięci niż te zęby w profilerze).
Moim najlepszym rozwiązaniem jest to, że niektóre zachowania OS obsługują dziesiątki tysięcy milisekundowych wątków. Czy jakiś guru ma wytłumaczenie tego?
Rozumiem twój punkt widzenia i zwykle się zgadzam. Wątki, które tworzę, są naprawdę krótkotrwałe. Tworzę je (używając WinApi CreateThread), a następnie natychmiast dołączam je do JVM.W Javie odświeża wykres Swing z nową wartością. Po ich zakończeniu odrywają i przerywają wykonywanie (powrót 0), w którym to momencie powinni zostać zniszczeni przez system operacyjny. Są używane do przekazywania nowej wartości do Javy. Jest około 40 z nich na sekundę dla każdego kanału dźwiękowego (pracuję z maksymalnie 32 kanałami). –
Możesz rozważyć połączenie wątków. Spraw, aby wątki pozostały dłużej i pobieraj dane z kolejki, zamiast ciągle tworzyć nowe wątki. Zmniejszy to obciążenie zarządzania wątkami zarówno w systemie operacyjnym, jak i Java. – technomage
Jeśli robisz jakieś rzeczy Javy w JNI oprócz zwykłego wywoływania metody, możesz także popchnąć/popować lokalną ramkę wokół tych akcji. – technomage