JDK-8294228 : AttachCurrentThread memory leak
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 19
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2022-09-15
  • Updated: 2022-12-13
  • Resolved: 2022-12-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 20
20Resolved
Related Reports
Duplicate :  
Description
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



Comments
Closing as a dup of JDK-8296463
13-12-2022

additional information from submitter: ===================================== The bug has been fixed. Thanks David Holmes! Your bug fix for https://bugs.openjdk.org/browse/JDK-8296463 also fixed my bug. =====================================
12-12-2022

[~sswsharm] Can we contact the original submitter and ask them to use the test program to see if they see the same leak using the same tool they originally used. If so then we can eliminate the fact DllMain was involved as a factor - otherwise it would suggest the issue does relate to DllMain. Did the submitter see any evidence of a memory leak other than the tool output as reported i.e. the process eventually getting out-of-memory conditions? Otherwise my current inclination is to blame the monitoring mechanism for introducing the apparent leak - something which itself may need investigating. Thanks.
26-10-2022

I've saved a copy of the test I used here: https://github.com/dholmes-ora/jdk/tree/8294228-attachDetach jdk/test/hotspot/jtreg/runtime/jni/attachDetach Runs on Posix (but only tested on Linux) and Windows
26-10-2022

As the reporter indicated that this worked okay in 17 I tried 17 as well and initially saw no memory increase via Task manager. However I then connected jconsole and discovered that the memory use started going up! Once I detached jconsole again the memory use stopped going up (but wasn't restored to previous levels). It now appears to me that the problem only exists when a monitoring tool is attached to the JVM - so perhaps that is what the reporter was also observing? Otherwise I cannot reproduce this.
25-10-2022

jconsole on Windows shows the same behaviour as Linux and is of no use in monitoring this. However Windows Task manager is showing a continual increase in the active private working set, which is indicating an increase of approx 10K per second i.e. per thread attach. Unfortunately there seems to be no way to track down exactly what this memory is.being used by.
25-10-2022

I think I have been chasing shadows on Linux. NMT is not showing any leak AFAICS. jconsole shows continual growth in non-heap memory over time but it is not consistent, as more time passes the leak grows more and more slowly - which makes no sense if the issue is supposed to be related to the once-per-second thread attaching/creation of the test. I've reworked the test to run on Windows - but not as DllMain as I don't know how to do that within our build/test framework (I don't think it is possible).
25-10-2022

Using jconsole I can observe a slow increase of non-heap memory over time. The smallest observable delta was 64K (or zero) but there seems a problem with the exported timestamps. Further, the leak over time seems to slow as time goes on, even though it should remain steady based on the cycle of attach/detach. I used a simple Thread creation program and observed the same behaviour with continually starting and joining a new thread, so the issue seems not to be specific to attach/detach. The issue seems to have been introduced in JDK 14.
24-10-2022

I used the same basic test on Linux with a 1 second sleep in the loop. I observed the RES memory continuing to increase for a few minutes but then it stabilized and ceased growing any further. I'm not in a position to test this easily on Windows and certainly not as a DLL attach routine. It may be the issue there is to do with the DLL memory management not the JVM.
18-10-2022