From d777717d0f2bd60172eff4a491caa4bc7545ffd5 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 3 Oct 2025 12:01:38 -0400 Subject: [PATCH 1/4] fix leak in Java event TLBs --- .../src/com/oracle/svm/core/jfr/JfrThreadLocal.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index d5f58382182d..463d03e91375 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -123,7 +123,9 @@ public UnsignedWord getThreadLocalBufferSize() { } public void teardown() { + // At this point all native buffers should be freed already. getNativeBufferList().teardown(); + // At this point Java buffers will be retired or freed. getJavaBufferList().teardown(); } @@ -161,10 +163,11 @@ public static void stopRecording(IsolateThread isolateThread, boolean freeJavaBu flushToGlobalMemoryAndFreeBuffer(nb); JfrBuffer jb = javaBuffer.get(isolateThread); - javaBuffer.set(isolateThread, Word.nullPointer()); if (freeJavaBuffer) { + javaBuffer.set(isolateThread, Word.nullPointer()); flushToGlobalMemoryAndFreeBuffer(jb); } else { + // Do not reset the thread local since we may need it to reinstate the buffer in the next recording. flushToGlobalMemoryAndRetireBuffer(jb); } From 79b994724243bfa45f0f74ddb69045e064812ea5 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 3 Oct 2025 12:22:09 -0400 Subject: [PATCH 2/4] style --- .../src/com/oracle/svm/core/jfr/JfrThreadLocal.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index 463d03e91375..ae857e560e19 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -167,7 +167,8 @@ public static void stopRecording(IsolateThread isolateThread, boolean freeJavaBu javaBuffer.set(isolateThread, Word.nullPointer()); flushToGlobalMemoryAndFreeBuffer(jb); } else { - // Do not reset the thread local since we may need it to reinstate the buffer in the next recording. + // Do not reset the thread local since we may need it to reinstate the buffer in the + // next recording. flushToGlobalMemoryAndRetireBuffer(jb); } From 99396b5a9b871a964c6989467738c5bc7017708a Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 3 Oct 2025 13:17:11 -0400 Subject: [PATCH 3/4] small fix --- .../src/com/oracle/svm/core/jfr/JfrThreadLocal.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java index ae857e560e19..98d7daea7ce8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java @@ -217,7 +217,7 @@ private static void flushToGlobalMemoryAndFreeBuffer(JfrBuffer buffer) { @Uninterruptible(reason = "Locking without transition requires that the whole critical section is uninterruptible.") private static void flushToGlobalMemoryAndRetireBuffer(JfrBuffer buffer) { assert VMOperation.isInProgressAtSafepoint(); - if (buffer.isNull()) { + if (buffer.isNull() || JfrBufferAccess.isRetired(buffer)) { return; } From 0dc1a929160884bf57dcc2534262240316b29c03 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 6 Oct 2025 09:09:50 +0200 Subject: [PATCH 4/4] Minor JavaDoc fix. --- .../src/com/oracle/svm/core/jfr/JfrBufferAccess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrBufferAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrBufferAccess.java index cc38a316cba5..a6aaacc8fc4e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrBufferAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrBufferAccess.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.jfr; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; @@ -37,6 +36,7 @@ import com.oracle.svm.core.util.UnsignedUtils; import jdk.graal.compiler.api.replacements.Fold; +import jdk.graal.compiler.word.Word; /** * Used to access the raw memory of a {@link JfrBuffer}. @@ -178,7 +178,7 @@ public static boolean isThreadLocal(JfrBuffer buffer) { /** * If a buffer can't be freed right away, then we retire it instead. Retired buffers are ignored - * by the JFR infrastructure and may be reinstate or freed at a later point in time. + * by the JFR infrastructure and may be reinstated or freed at a later point in time. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static void setRetired(JfrBuffer buffer) {