Skip to content

Commit 2cdab8d

Browse files
committed
Prevent doube stop of JFR recording
There is an issue where jfr recording can be stopped twice. When this occurs buffers that are already free'd are freed a second time. Signed-off-by: tajila <[email protected]>
1 parent 8bbc086 commit 2cdab8d

File tree

5 files changed

+109
-11
lines changed

5 files changed

+109
-11
lines changed

jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/DiagnosticUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,9 @@ private static DiagnosticProperties doJFR(String diagnosticCommand) {
484484
Timer timer = new Timer();
485485
TimerTask jfrDumpTask = new TimerTask() {
486486
public void run() {
487-
VM.stopJFR();
487+
if (VM.isJFRRecordingStarted()) {
488+
VM.stopJFR();
489+
}
488490
}
489491
};
490492
timer.schedule(jfrDumpTask, duration);

runtime/jcl/common/com_ibm_oti_vm_VM.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,10 @@ Java_com_ibm_oti_vm_VM_startJFR(JNIEnv *env, jclass unused)
255255
J9JavaVM *vm = currentThread->javaVM;
256256
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
257257

258-
/* this is to initalize JFR late after VM startup */
259-
rc = vmFuncs->initializeJFR(vm, TRUE);
258+
if (!vmFuncs->isJFRRecordingStarted(vm)) {
259+
/* this is to initalize JFR late after VM startup */
260+
rc = vmFuncs->initializeJFR(vm, TRUE);
261+
}
260262

261263
return rc;
262264
}
@@ -268,12 +270,14 @@ Java_com_ibm_oti_vm_VM_stopJFR(JNIEnv *env, jclass unused)
268270
J9JavaVM *vm = currentThread->javaVM;
269271
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
270272

271-
vmFuncs->internalEnterVMFromJNI(currentThread);
272-
vmFuncs->acquireExclusiveVMAccess(currentThread);
273-
vmFuncs->jfrDump(currentThread, TRUE);
274-
vmFuncs->releaseExclusiveVMAccess(currentThread);
275-
vmFuncs->tearDownJFR(vm);
276-
vmFuncs->internalExitVMToJNI(currentThread);
273+
if (vmFuncs->isJFRRecordingStarted(vm)) {
274+
vmFuncs->internalEnterVMFromJNI(currentThread);
275+
vmFuncs->acquireExclusiveVMAccess(currentThread);
276+
vmFuncs->jfrDump(currentThread, TRUE);
277+
vmFuncs->releaseExclusiveVMAccess(currentThread);
278+
vmFuncs->tearDownJFR(vm);
279+
vmFuncs->internalExitVMToJNI(currentThread);
280+
}
277281
}
278282

279283
void JNICALL

test/functional/cmdLineTests/jfr/jfr.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
2424

2525
<!DOCTYPE suite SYSTEM "cmdlinetester.dtd">
2626

27-
<suite id="JFR Tests" timeout="1800">
27+
<suite id="JFR Tests" timeout="2400">
2828
<envvar name="OPENJ9_METADATA_BLOB_FILE_PATH" value="$METADATA_BLOB_PATH$" />
2929
<test id="triggerExecutionSample">
3030
<command>$EXE$ -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.TriggerExecutionSample</command>
@@ -45,6 +45,16 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
4545
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
4646
<output type="failure" caseSensitive="yes" regex="no">Failed</output>
4747
</test>
48+
<test id="VM API Test aggressive start and stop - approx 2mins">
49+
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.VMAPITest 1</command>
50+
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
51+
<output type="failure" caseSensitive="yes" regex="no">Failed</output>
52+
</test>
53+
<test id="VM API Test2 - approx 2mins">
54+
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.VMAPITest2</command>
55+
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
56+
<output type="failure" caseSensitive="yes" regex="no">Failed</output>
57+
</test>
4858
<test id="Test JFR enablement 1">
4959
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
5060
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>

test/functional/cmdLineTests/jfr/src/org/openj9/test/VMAPITest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
public class VMAPITest {
2727
public static void main(String[] args) throws Throwable {
2828
final WorkLoad workLoad = new WorkLoad(200, 20000, 200);
29+
int sleepDuration = 1000;
30+
31+
if (args.length > 1) {
32+
sleepDuration = Integer.parseInt(args[0]);
33+
}
2934

3035
if (VM.isJFRRecordingStarted()) {
3136
System.out.println("Failed should not be recording.");
@@ -55,7 +60,7 @@ public static void main(String[] args) throws Throwable {
5560
return;
5661
}
5762

58-
Thread.sleep(1000);
63+
Thread.sleep(sleepDuration);
5964
VM.jfrDump();
6065
VM.stopJFR();
6166

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright IBM Corp. and others 2024
3+
*
4+
* This program and the accompanying materials are made available under
5+
* the terms of the Eclipse Public License 2.0 which accompanies this
6+
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7+
* or the Apache License, Version 2.0 which accompanies this distribution and
8+
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
*
10+
* This Source Code may also be made available under the following
11+
* Secondary Licenses when the conditions for such availability set
12+
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13+
* General Public License, version 2 with the GNU Classpath
14+
* Exception [1] and GNU General Public License, version 2 with the
15+
* OpenJDK Assembly Exception [2].
16+
*
17+
* [1] https://www.gnu.org/software/classpath/license.html
18+
* [2] https://openjdk.org/legal/assembly-exception.html
19+
*
20+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
21+
*/
22+
package org.openj9.test;
23+
24+
import com.ibm.oti.vm.VM;
25+
26+
public class VMAPITest2 {
27+
public static void main(String[] args) throws Throwable {
28+
final WorkLoad workLoad = new WorkLoad(200, 20000, 200);
29+
30+
Thread app = new Thread(() -> {
31+
workLoad.runWork();
32+
});
33+
app.start();
34+
35+
try {
36+
Thread.sleep(3000);
37+
} catch(Throwable t) {
38+
t.printStackTrace();
39+
}
40+
41+
if (VM.isJFRRecordingStarted()) {
42+
System.out.println("Failed should not be recording 1.");
43+
System.exit(0);
44+
}
45+
46+
/* attempt a stop recording before it has started */
47+
VM.stopJFR();
48+
49+
if (VM.isJFRRecordingStarted()) {
50+
System.out.println("Failed should not be recording 2.");
51+
System.exit(0);
52+
}
53+
54+
VM.startJFR();
55+
if (!VM.isJFRRecordingStarted()) {
56+
System.out.println("Failed should be recording 3.");
57+
System.exit(0);
58+
}
59+
60+
61+
/* attempt another start recording after one has already started */
62+
VM.startJFR();
63+
if (!VM.isJFRRecordingStarted()) {
64+
System.out.println("Failed should be recording 4.");
65+
System.exit(0);
66+
}
67+
68+
VM.stopJFR();
69+
if (VM.isJFRRecordingStarted()) {
70+
System.out.println("Failed should not be recording 5.");
71+
System.exit(0);
72+
}
73+
74+
/* attempt a stop recording before it has started */
75+
VM.stopJFR();
76+
}
77+
}

0 commit comments

Comments
 (0)