A DESCRIPTION OF THE PROBLEM :
Call to AttachCurrentThread/DetachCurrentThread in loop cause memory leak
REGRESSION : Last worked in version 17
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a dll, that on process attach start thread that calls AttachCurrentThread/DetachCurrentThread in the infinite loop.
Load this dll from java code.
Put java thread into infinite sleep.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No memory leaks
ACTUAL -
Memory leaks
---------- BEGIN SOURCE ----------
#################################################################################
JAVA code
#################################################################################
package org.example;
public class Main {
public static void main(String[] args) throws InterruptedException {
System.loadLibrary("attach_detach");
Thread.sleep(Long.MAX_VALUE);
}
}
################################################################################
DLL code (Microsoft Visual Studio 2022)
################################################################################
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include <jni.h>
void attachDetachLoop(void* param);
HANDLE threadHandle;
JavaVM* jvm;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
threadHandle = (HANDLE)_beginthread(attachDetachLoop, 0, NULL);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void print(LPCTSTR message, UINT code) {
TCHAR buf[MAX_PATH];
wsprintf(buf, message, code);
OutputDebugString(buf);
}
void attachDetachLoop(void* param) {
while (true) {
JNIEnv* env = NULL;
if (!jvm) {
auto res = JNI_GetCreatedJavaVMs(&jvm, 1, NULL);
if (res != JNI_OK) {
print(TEXT("unexpected response from JNI_GetCreatedJavaVMs: %u"), res);
continue;
}
}
auto res = jvm->GetEnv((void**)&env, JNI_VERSION_10);
if (res != JNI_OK) {
if (res == JNI_EDETACHED) {
res = jvm->AttachCurrentThread((void**)&env, NULL);
if (res != JNI_OK) {
print(TEXT("unexpected response from AttachCurrentThread : %u"), res);
continue;
}
}
else {
print(TEXT("unexpected response from GetEnv: %u"), res);
continue;
}
}
res = jvm->DetachCurrentThread();
if (res != JNI_OK) {
print(TEXT("unexpected response from DetachCurrentThread: %u"), res);
continue;
}
}
}
---------- END SOURCE ----------
EXPECTED -
No memory leaks
ACTUAL -
Have memory leaks. See https://ibb.co/8msw6GW
CUSTOMER SUBMITTED WORKAROUND :
Use Java 17
FREQUENCY : always