Skip to content

Commit b9080bf

Browse files
committed
Add check for JFR enablement
Currently, JFR is enabled by default on all platforms that support it, and it cannot be disabled. We have been using `-XX:+FlightRecorder` to indicate if the JVM should start with recording enabled. This is not consistent with the RI. With this change `-XX:[+|-]FlightRecorder` toggles whether JFR is enabled. By default JFR will remain enabled, but we now have the ability to disable it. `-XX:StartFlightRecording` will be used to indicate that a recording should be begin at startup. Signed-off-by: tajila <[email protected]>
1 parent ffb9537 commit b9080bf

File tree

16 files changed

+151
-21
lines changed

16 files changed

+151
-21
lines changed

jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,9 @@ public static Properties internalGetProperties() {
639639
}
640640

641641
/*[IF JFR_SUPPORT]*/
642+
643+
public static native boolean isJFREnabled();
644+
642645
/**
643646
* Check if a JFR recording has been started.
644647
*

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -700,14 +700,17 @@ private static DiagnosticProperties doCheckpointJVM(String diagnosticCommand) {
700700
/*[ENDIF] CRAC_SUPPORT */
701701

702702
/*[IF JFR_SUPPORT]*/
703-
commandTable.put(DIAGNOSTICS_JFR_START, DiagnosticUtils::doJFR);
704-
helpTable.put(DIAGNOSTICS_JFR_START, DIAGNOSTICS_JFR_START_HELP);
703+
if (VM.isJFREnabled()) {
704+
commandTable.put(DIAGNOSTICS_JFR_START, DiagnosticUtils::doJFR);
705+
helpTable.put(DIAGNOSTICS_JFR_START, DIAGNOSTICS_JFR_START_HELP);
705706

706-
commandTable.put(DIAGNOSTICS_JFR_DUMP, DiagnosticUtils::doJFR);
707-
helpTable.put(DIAGNOSTICS_JFR_DUMP, DIAGNOSTICS_JFR_DUMP_HELP);
707+
commandTable.put(DIAGNOSTICS_JFR_DUMP, DiagnosticUtils::doJFR);
708+
helpTable.put(DIAGNOSTICS_JFR_DUMP, DIAGNOSTICS_JFR_DUMP_HELP);
709+
710+
commandTable.put(DIAGNOSTICS_JFR_STOP, DiagnosticUtils::doJFR);
711+
helpTable.put(DIAGNOSTICS_JFR_STOP, DIAGNOSTICS_JFR_STOP_HELP);
712+
}
708713

709-
commandTable.put(DIAGNOSTICS_JFR_STOP, DiagnosticUtils::doJFR);
710-
helpTable.put(DIAGNOSTICS_JFR_STOP, DIAGNOSTICS_JFR_STOP_HELP);
711714
/*[ENDIF] JFR_SUPPORT */
712715
}
713716
}

runtime/jcl/common/com_ibm_oti_vm_VM.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ Java_com_ibm_oti_vm_VM_isJVMInSingleThreadedMode(JNIEnv *env, jclass unused)
194194
}
195195

196196
#if defined(J9VM_OPT_JFR)
197+
jboolean JNICALL
198+
Java_com_ibm_oti_vm_VM_isJFREnabled(JNIEnv *env, jclass unused)
199+
{
200+
J9JavaVM *vm = ((J9VMThread *)env)->javaVM;
201+
202+
return vm->internalVMFunctions->isJFREnabled(vm) ? JNI_TRUE : JNI_FALSE;
203+
}
204+
197205
jboolean JNICALL
198206
Java_com_ibm_oti_vm_VM_isJFRRecordingStarted(JNIEnv *env, jclass unused)
199207
{

runtime/jcl/exports.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ endif()
689689

690690
if(J9VM_OPT_JFR)
691691
omr_add_exports(jclse
692+
Java_com_ibm_oti_vm_VM_isJFREnabled
692693
Java_com_ibm_oti_vm_VM_isJFRRecordingStarted
693694
Java_com_ibm_oti_vm_VM_jfrDump
694695
Java_com_ibm_oti_vm_VM_setJFRRecordingFileName

runtime/jcl/uma/jfr_jdk11_exports.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ OpenJDK Assembly Exception [2].
2020
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
2121
-->
2222
<exports group="jfr_jdk11">
23+
<export name="Java_com_ibm_oti_vm_VM_isJFRRecordingStarted" />
24+
<export name="Java_com_ibm_oti_vm_VM_jfrDump" />
25+
<export name="Java_com_ibm_oti_vm_VM_setJFRRecordingFileName" />
26+
<export name="Java_com_ibm_oti_vm_VM_startJFR" />
27+
<export name="Java_com_ibm_oti_vm_VM_stopJFR" />
28+
<export name="Java_com_ibm_oti_vm_VM_triggerExecutionSample" />
2329
<export name="Java_jdk_jfr_internal_JVM_abort" />
2430
<export name="Java_jdk_jfr_internal_JVM_addStringConstant" />
2531
<export name="Java_jdk_jfr_internal_JVM_beginRecording" />

runtime/jcl/uma/jfr_jdk21_exports.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ OpenJDK Assembly Exception [2].
2020
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
2121
-->
2222
<exports group="jfr_jdk21">
23-
<export name="Java_com_ibm_oti_vm_VM_isJFRRecordingStarted" />
24-
<export name="Java_com_ibm_oti_vm_VM_jfrDump" />
25-
<export name="Java_com_ibm_oti_vm_VM_setJFRRecordingFileName" />
26-
<export name="Java_com_ibm_oti_vm_VM_startJFR" />
27-
<export name="Java_com_ibm_oti_vm_VM_stopJFR" />
28-
<export name="Java_com_ibm_oti_vm_VM_triggerExecutionSample" />
2923
<export name="Java_jdk_jfr_internal_JVM_abort" />
3024
<export name="Java_jdk_jfr_internal_JVM_addStringConstant" />
3125
<export name="Java_jdk_jfr_internal_JVM_beginRecording" />

runtime/oti/j9consts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ extern "C" {
369369
#define J9_EXTENDED_RUNTIME2_RAMSTATE_SNAPSHOT_RUN 0x40000000
370370
#define J9_EXTENDED_RUNTIME2_RAMSTATE_RESTORE_RUN 0x80000000
371371

372+
/* constants for J9JavaVM.extendedRuntimeFlags3 */
373+
#define J9_EXTENDED_RUNTIME3_START_FLIGHT_RECORDING 0x1
374+
372375
#define J9_OBJECT_HEADER_AGE_DEFAULT 0xA /* OBJECT_HEADER_AGE_DEFAULT */
373376
#define J9_OBJECT_HEADER_SHAPE_MASK 0xE /* OBJECT_HEADER_SHAPE_MASK */
374377
#define J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET 0x10 /* OBJECT_HEADER_LOWEST_REMEMBERED */

runtime/oti/j9nonbuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5257,6 +5257,7 @@ typedef struct J9InternalVMFunctions {
52575257
#endif /* defined(J9VM_ZOS_3164_INTEROPERABILITY) && (JAVA_SPEC_VERSION >= 17) */
52585258
#if defined(J9VM_OPT_JFR)
52595259
jint (*initializeJFR)(struct J9JavaVM *vm, BOOLEAN lateInit);
5260+
jboolean (*isJFREnabled)(struct J9JavaVM *vm);
52605261
jboolean (*isJFRRecordingStarted)(struct J9JavaVM *vm);
52615262
void (*jfrDump)(struct J9VMThread *currentThread, BOOLEAN finalWrite);
52625263
void (*jfrExecutionSample)(struct J9VMThread *currentThread, struct J9VMThread *sampleThread);
@@ -5790,6 +5791,7 @@ typedef struct J9JavaVM {
57905791
U_32 runtimeFlags;
57915792
U_32 extendedRuntimeFlags;
57925793
U_32 extendedRuntimeFlags2;
5794+
U_32 extendedRuntimeFlags3;
57935795
UDATA zeroOptions;
57945796
struct J9Pool* hotFieldClassInfoPool;
57955797
omrthread_monitor_t hotFieldClassInfoPoolMutex;

runtime/oti/jclprots.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,8 @@ Java_com_ibm_oti_vm_VM_isJVMInSingleThreadedMode(JNIEnv *env, jclass unused);
12711271

12721272
#if defined(J9VM_OPT_JFR)
12731273
jboolean JNICALL
1274+
Java_com_ibm_oti_vm_VM_isJFREnabled(JNIEnv *env, jclass unused);
1275+
jboolean JNICALL
12741276
Java_com_ibm_oti_vm_VM_isJFRRecordingStarted(JNIEnv *env, jclass unused);
12751277
void JNICALL
12761278
Java_com_ibm_oti_vm_VM_jfrDump(JNIEnv *env, jclass unused);

runtime/oti/jvminit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,8 @@ enum INIT_STAGE {
587587
#define VMOPT_XXFLIGHTRECORDER "-XX:+FlightRecorder"
588588
#define VMOPT_XXNOFLIGHTRECORDER "-XX:-FlightRecorder"
589589

590+
#define VMOPT_XXSTARTFLIGHTRECORDING "-XX:StartFlightRecording"
591+
590592
#define VMOPT_XXCONTINUATIONCACHE "-XX:ContinuationCache:"
591593

592594
#if JAVA_SPEC_VERSION >= 22

runtime/oti/vm_api.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5472,6 +5472,16 @@ hasMemoryScope(J9VMThread *walkThread, j9object_t scope);
54725472
jint
54735473
initializeJFR(J9JavaVM *vm, BOOLEAN lateInit);
54745474

5475+
/**
5476+
* Check if a JFR is enabled on the JVM.
5477+
*
5478+
* @param vm[in] the J9JavaVM
5479+
*
5480+
* @returns JNI_TRUE if a JFR enabled, JNI_FALSE otherwise
5481+
*/
5482+
jboolean
5483+
isJFREnabled(J9JavaVM *vm);
5484+
54755485
/**
54765486
* Check if a JFR recording has been started.
54775487
*

runtime/vm/intfunc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ J9InternalVMFunctions J9InternalFunctions = {
458458
#endif /* defined(J9VM_ZOS_3164_INTEROPERABILITY) && (JAVA_SPEC_VERSION >= 17) */
459459
#if defined(J9VM_OPT_JFR)
460460
initializeJFR,
461+
isJFREnabled,
461462
isJFRRecordingStarted,
462463
jfrDump,
463464
jfrExecutionSample,

runtime/vm/jfr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,12 @@ initializeEventFields(J9VMThread *currentThread, J9JFREvent *event, UDATA eventT
852852
event->vmThread = currentThread;
853853
}
854854

855+
jboolean
856+
isJFREnabled(J9JavaVM *vm)
857+
{
858+
return J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_JFR_ENABLED) ? JNI_TRUE : JNI_FALSE;
859+
}
860+
855861
jboolean
856862
isJFRRecordingStarted(J9JavaVM *vm)
857863
{

runtime/vm/jvminit.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4296,12 +4296,19 @@ processVMArgsFromFirstToLast(J9JavaVM * vm)
42964296
{
42974297
IDATA flightRecorder = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXFLIGHTRECORDER, NULL);
42984298
IDATA noFlightRecorder = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXNOFLIGHTRECORDER, NULL);
4299-
if (flightRecorder > noFlightRecorder) {
4300-
vm->extendedRuntimeFlags2 |= J9_EXTENDED_RUNTIME2_JFR_ENABLED;
4301-
} else if (flightRecorder < noFlightRecorder) {
4299+
4300+
vm->extendedRuntimeFlags2 |= J9_EXTENDED_RUNTIME2_JFR_ENABLED;
4301+
4302+
if (flightRecorder < noFlightRecorder) {
43024303
vm->extendedRuntimeFlags2 &= ~(UDATA)J9_EXTENDED_RUNTIME2_JFR_ENABLED;
43034304
}
43044305
}
4306+
{
4307+
if (0 <= FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXSTARTFLIGHTRECORDING, NULL)) {
4308+
vm->extendedRuntimeFlags3 |= J9_EXTENDED_RUNTIME3_START_FLIGHT_RECORDING;
4309+
}
4310+
}
4311+
43054312
#endif /* defined(J9VM_OPT_JFR) */
43064313

43074314
if (FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXKEEPJNIIDS, NULL) != -1) {
@@ -7560,8 +7567,10 @@ protectedInitializeJavaVM(J9PortLibrary* portLibrary, void * userData)
75607567

75617568
#if defined(J9VM_OPT_JFR)
75627569
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_JFR_ENABLED)) {
7563-
if (JNI_OK != initializeJFR(vm, FALSE)) {
7564-
goto error;
7570+
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_START_FLIGHT_RECORDING)) {
7571+
if (JNI_OK != initializeJFR(vm, FALSE)) {
7572+
goto error;
7573+
}
75657574
}
75667575
}
75677576
#endif /* defined(J9VM_OPT_JFR) */

test/functional/cmdLineTests/jfr/jfr.xml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,56 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
2727
<suite id="JFR Tests" timeout="300">
2828
<envvar name="OPENJ9_METADATA_BLOB_FILE_PATH" value="$METADATA_BLOB_PATH$" />
2929
<test id="triggerExecutionSample">
30-
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.TriggerExecutionSample</command>
30+
<command>$EXE$ -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.TriggerExecutionSample</command>
3131
<return type="success" value="0" />
3232
</test>
3333
<test id="runWorkload - approx 30seconds">
34-
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad</command>
34+
<command>$EXE$ -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad</command>
3535
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
3636
<output type="failure" caseSensitive="yes" regex="no">Exception</output>
3737
</test>
3838
<test id="runWorkload 2 - approx 2mins">
39-
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad 200 20000 200</command>
39+
<command>$EXE$ -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad 200 20000 200</command>
4040
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
4141
<output type="failure" caseSensitive="yes" regex="no">Exception</output>
4242
</test>
43-
<test id="runWorkload 2 - approx 2mins">
43+
<test id="VM API Test - approx 2mins">
4444
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.VMAPITest</command>
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="Test JFR enablement 1">
49+
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
50+
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>
51+
<output type="failure" caseSensitive="yes" regex="no">JFR recording has started</output>
52+
<output type="success" caseSensitive="yes" regex="no">JFR is enabled</output>
53+
</test>
54+
<test id="Test JFR enablement 2">
55+
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
56+
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>
57+
<output type="failure" caseSensitive="yes" regex="no">JFR recording has started</output>
58+
<output type="success" caseSensitive="yes" regex="no">JFR is enabled</output>
59+
</test>
60+
<test id="Test JFR enablement 3">
61+
<command>$EXE$ -XX:-FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
62+
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>
63+
<output type="failure" caseSensitive="yes" regex="no">JFR recording has started</output>
64+
<output type="failure" caseSensitive="yes" regex="no">JFR is enabled</output>
65+
<output type="success" caseSensitive="yes" regex="no">JFR is not enabled</output>
66+
</test>
67+
<test id="Test Start flight recording 1">
68+
<command>$EXE$ -XX:-FlightRecorder -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
69+
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>
70+
<output type="failure" caseSensitive="yes" regex="no">JFR recording has started</output>
71+
<output type="failure" caseSensitive="yes" regex="no">JFR is enabled</output>
72+
<output type="success" caseSensitive="yes" regex="no">JFR is not enabled</output>
73+
</test>
74+
<test id="Test Start flight recording 2">
75+
<command>$EXE$ -XX:StartFlightRecording --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.JFRCMDLineTest</command>
76+
<output type="required" caseSensitive="yes" regex="no">All runs complete</output>
77+
<output type="success" caseSensitive="yes" regex="no">JFR recording has started</output>
78+
<output type="success" caseSensitive="yes" regex="no">JFR is enabled</output>
79+
<output type="failure" caseSensitive="yes" regex="no">JFR is not enabled</output>
80+
</test>
81+
4882
</suite>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 JFRCMDLineTest {
27+
28+
public static void main(String[] args) throws Throwable {
29+
30+
final WorkLoad workLoad = new WorkLoad(200, 20000, 200);
31+
32+
if (VM.isJFRRecordingStarted()) {
33+
System.out.println("JFR recording has started");
34+
} else {
35+
System.out.println("JFR recording has not started");
36+
}
37+
38+
if (VM.isJFREnabled()) {
39+
System.out.println("JFR is enabled");
40+
} else {
41+
System.out.println("JFR is not enabled");
42+
}
43+
44+
System.out.println("All runs complete");
45+
}
46+
}

0 commit comments

Comments
 (0)