Отладка утечки памяти JVM

У меня есть приложение Java, которое использует собственную библиотеку для некоторых своих функций. Он использует JNI для управления собственной библиотекой, а также получает асинхронный обратный вызов из библиотеки. Вы можете думать об этом как о внешнем интерфейсе Java и внутреннем интерфейсе, которые общаются друг с другом.

Я сталкиваюсь с утечкой памяти. Вскоре после запуска приложения память медленно, но неуклонно увеличивается. Поэтому я попытался посмотреть, что может вызвать утечку.

Сначала я попытался заменить интерфейс Java простым текстовым интерфейсом C ++. Таким образом, приложение никак не использует Java — и утечки прекратились. Так что проблема должна быть во внешнем интерфейсе Java.

Поэтому я запустил jvisualVM, чтобы увидеть, увеличивается ли куча — и оказалось, что нет. Размер кучи Java был довольно постоянным. Я даже запустил программу с xmx32m, но память продолжала увеличиваться за 100 м без каких-либо OutOfMemoryErrors. Фактически, jvisualVM показывал кучу Java около 7 метров.

Поэтому я углубился в программу с WinDbg. Я проанализировал шаблоны кучи с !heap -s команда и я получил это:

Кучи на только что запущенной программе:

0:059> !heap -s
LFH Key                   : 0x382288b9
Termination on corruption : ENABLED
Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast
(k)     (k)    (k)     (k) length      blocks cont. heap
-----------------------------------------------------------------------------
00330000 00000002    2048   1704   2048     22    71     2    0      0   LFH
005b0000 00001002    1088    212   1088     68     3     2    0      0   LFH
00aa0000 00001002    1088    108   1088     15     7     2    0      0   LFH
004f0000 00001002   15424  12876  15424   1372    89     9    0      1   LFH
...

0:059> !heap -stat -h 004f0000
heap @ 004f0000
group-by: TOTSIZE max-display: 20
size     #blocks     total     ( %) (percent of total busy bytes)
2b110 20 - 562200  (60.36)
98 166e - d5150  (9.33)
6cd20 1 - 6cd20  (4.77)
...

Кучи на программе, которая работает около получаса:

0:046> !heap -s
LFH Key                   : 0x5e47ba72
Termination on corruption : ENABLED
Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast
(k)     (k)    (k)     (k) length      blocks cont. heap
-----------------------------------------------------------------------------
006b0000 00000002    2048   1744   2048     46    92     2    0      0   LFH
00200000 00001002    1088    220   1088     68     3     2    0      0   LFH
00950000 00001002    1088    108   1088     15     7     2    0      0   LFH
001b0000 00001002   47808  31936  47808   1855   102    12    0      0   LFH
...

0:046> !heap -stat -h 001b0000
heap @ 001b0000
group-by: TOTSIZE max-display: 20
size     #blocks     total     ( %) (percent of total busy bytes)
98 59d1 - 355418  (36.67)
2b110 10 - 2b1100  (29.61)
6cd20 1 - 6cd20  (4.68)
...

Теперь ясно видно, что утечки вызваны растущим числом блоков размером 98. Но когда я пытаюсь проанализировать один из блоков с !heap -p -a, Я получил:

*** ОШИБКА: файл символов не найден. По умолчанию для экспорта символов для jvm.dll

без каких-либо следов стека. Таким образом, блоки расположены где-то внутри jvm.dll, и, поскольку нет никаких pdbs для JVM, я не могу отлаживать утечку дальше.

Мне удалось точно определить, где происходит утечка в моем коде. Все вызовы к интерфейсу Java проходят через одну функцию:

void callback(JNIEnv *env, int stream, double value, char *callbackName){
jclass jni = env->FindClass("nativ/Callbacks");
jmethodID callbackMethodID = env->GetStaticMethodID(jni, callbackName, "(ID)V");
jvalue params[2];
params[0].i = (long)(stream);
params[1].d = value;
env->CallStaticVoidMethodA(jni, callbackMethodID, params); //commenting this out stops the leaks
}

Когда я закомментирую последнюю команду, утечки прекращаются, но я не получаю обратной связи с внешним интерфейсом.

Может ли это быть ошибка JVM? Как я узнаю?

1

Решение

malloc () внутренне вызывает HeapAlloc (). Я предполагаю, что вам нужен метод Release для освобождения памяти, выделенной JVM, если ваша библиотека содержит ссылку на внутреннее состояние JVM.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]