Skip to content

Commit 13292c2

Browse files
jiekangadinnRoman KennkeJosh-Matsuokaquintesse
committed
Add JDK Flight Recorder support for Java native images
Co-authored-by: Andrew Dinn <adinn@redhat.com> Co-authored-by: Roman Kennke <rkennke@redhat.com> Co-authored-by: Josh Matsuoka <jmatsuok@redhat.com> Co-authored-by: Tako Schotanus <tschotan@redhat.com> Co-authored-by: Simon Tooke <stooke@redhat.com>
1 parent 274b478 commit 13292c2

File tree

60 files changed

+8923
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+8923
-0
lines changed

substratevm/JFR.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## JFR Implementation Notes
2+
3+
Implementation is based off of jdk/jdk commit rev
4+
5+
d2816784605b
6+
7+
## JDK Matrix
8+
9+
This branch builds with:
10+
labsjdk-ce-11.0.9-jvmci-20.3-b06
11+
12+
Tarballs can be found at:
13+
https://github.com/graalvm/labs-openjdk-11/releases
14+
15+
For example:
16+
https://github.com/graalvm/labs-openjdk-11/releases/download/jvmci-20.3-b06/labsjdk-ce-11.0.9+10-jvmci-20.3-b06-linux-amd64.tar.gz
17+
18+
## Testing the JFR code
19+
20+
Clone the graalvm-jfr-tests repo somewhere to be used in the -cp argument. Use a JDK 11 to compile into class files.
21+
22+
```
23+
javac /path/to/graalvm-jfr-tests/flat/EventCommit.java
24+
25+
26+
mx clean
27+
mx build
28+
mx native-image --allow-incomplete-classpath "-J-XX:FlightRecorderOptions=retransform=false" --no-fallback -ea -cp /path/to/graalvm-jfr-tests/flat/ EventCommit
29+
```
30+
31+
See `/tmp` for a `my-recording...` jfr file
32+
33+
## Logging
34+
35+
The JFR implementation supports log levels via runtime flag:
36+
```
37+
-XX:FlightRecorderLogging=<value>
38+
```
39+
40+
Values include:
41+
```
42+
trace, debug, info, warning, error
43+
```

substratevm/mx.substratevm/suite.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,24 @@
581581
"spotbugs": "false",
582582
},
583583

584+
"com.oracle.svm.core.jdk.jfr.test": {
585+
"subDir": "src",
586+
"sourceDirs": ["src"],
587+
"dependencies": [
588+
"com.oracle.svm.core",
589+
"mx:JUNIT",
590+
"sdk:GRAAL_SDK",
591+
],
592+
"checkstyle": "com.oracle.svm.core",
593+
"workingSets": "SVM_CORE",
594+
"annotationProcessors": [
595+
"compiler:GRAAL_PROCESSOR",
596+
],
597+
"javaCompliance": "8+",
598+
"spotbugs": "false",
599+
},
600+
601+
584602
"com.oracle.svm.test.jdk11": {
585603
"subDir": "src",
586604
"sourceDirs": ["src"],
@@ -1193,11 +1211,13 @@
11931211
"com.oracle.svm.test.jdk11",
11941212
"com.oracle.svm.configure.test",
11951213
"com.oracle.svm.graal.test",
1214+
"com.oracle.svm.core.jdk.jfr.test",
11961215
],
11971216
"distDependencies": [
11981217
"mx:JUNIT_TOOL",
11991218
"sdk:GRAAL_SDK",
12001219
"SVM_CONFIGURE",
1220+
"SVM_CORE",
12011221
],
12021222
"testDistribution" : True,
12031223
},
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2020, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jdk.jfr.test;
28+
29+
import org.graalvm.collections.EconomicMap;
30+
import org.junit.Assert;
31+
import org.junit.Test;
32+
33+
import com.oracle.svm.core.jdk.jfr.JfrOptions;
34+
35+
public class JfrOptionsTest {
36+
37+
// Taken from GlobalDefinitions.hpp
38+
private static final long K = 1024;
39+
private static final long M = K*K;
40+
private static final long G = M*K;
41+
42+
@Test
43+
public void testBasicOptions() {
44+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(), "dumponexit=true");
45+
Assert.assertEquals(JfrOptions.getDumpOnExit(), true);
46+
}
47+
48+
@Test
49+
public void testValidMemoryOptions() {
50+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(), "memorysize=256m," +
51+
"globalbuffersize=128m,globalbuffercount=2,threadbuffersize=8k");
52+
Assert.assertEquals(JfrOptions.getGlobalBufferSize(), 128 * M);
53+
Assert.assertEquals(JfrOptions.getMemorySize(), 256*M);
54+
Assert.assertEquals(JfrOptions.getGlobalBufferCount(), 2);
55+
}
56+
57+
@Test
58+
public void testInvalidMemoryOptions() {
59+
try {
60+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(), "memorysize=1k");
61+
} catch (IllegalArgumentException e) {
62+
// Pass
63+
return;
64+
}
65+
Assert.fail();
66+
}
67+
68+
@Test
69+
public void testBadInput() {
70+
try {
71+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(), "memorysize=thisShouldFail");
72+
} catch (Exception e) {
73+
// Pass
74+
return;
75+
}
76+
Assert.fail();
77+
}
78+
79+
@Test
80+
public void testTimeOptions() {
81+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(),"delay=10s,maxage=1h,duration=2m");
82+
Assert.assertEquals(10, JfrOptions.getRecordingDelay());
83+
Assert.assertEquals(360, JfrOptions.getMaxAge());
84+
Assert.assertEquals(120, JfrOptions.getDuration());
85+
}
86+
87+
@Test
88+
public void testMaxStackDepth() {
89+
try {
90+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(),"stackdepth=9000");
91+
} catch (Exception e) {
92+
// Pass
93+
return;
94+
}
95+
Assert.fail();
96+
}
97+
98+
@Test
99+
public void testNegativeStackDepth() {
100+
try {
101+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(),"stackdepth=-10");
102+
} catch (Exception e) {
103+
// Pass
104+
return;
105+
}
106+
Assert.fail();
107+
}
108+
109+
@Test
110+
public void testAllArguments() {
111+
JfrOptions.StartFlightRecordingOption.update(EconomicMap.create(),
112+
"maxchunksize=1k,globalbuffersize=1m,memorysize=2m,retransform=true," +
113+
"stackdepth=10,sampleprotection=true,samplethreads=true,old-object-queue-size=100," +
114+
"numglobalbuffers=2,threadbuffersize=4k,repository=/path/to/repository,dumponexit=false," +
115+
"name=recording,settings=/path/to/settings,delay=10s,duration=1m,disk=true,maxage=1h," +
116+
"maxsize=10k,path-to-gc-roots=true");
117+
Assert.assertEquals(1*K, JfrOptions.getMaxChunkSize());
118+
Assert.assertEquals(1*M, JfrOptions.getGlobalBufferSize());
119+
Assert.assertEquals(2, JfrOptions.getGlobalBufferCount());
120+
Assert.assertEquals(2*M, JfrOptions.getMemorySize());
121+
Assert.assertEquals(true, JfrOptions.isRetransformEnabled());
122+
Assert.assertEquals(10, JfrOptions.getStackDepth());
123+
Assert.assertEquals(true, JfrOptions.isSampleProtectionEnabled());
124+
Assert.assertEquals(true, JfrOptions.isSampleThreadsEnabled());
125+
Assert.assertEquals(100, JfrOptions.getObjectQueueSize());
126+
Assert.assertEquals(2, JfrOptions.getGlobalBufferCount());
127+
Assert.assertEquals(4*K, JfrOptions.getThreadBufferSize());
128+
Assert.assertEquals("/path/to/repository", JfrOptions.getRepositoryLocation());
129+
Assert.assertEquals(false, JfrOptions.getDumpOnExit());
130+
Assert.assertEquals("recording", JfrOptions.getRecordingName());
131+
Assert.assertEquals("/path/to/settings", JfrOptions.getRecordingSettingsFile());
132+
Assert.assertEquals(10, JfrOptions.getRecordingDelay());
133+
Assert.assertEquals(60, JfrOptions.getDuration());
134+
Assert.assertEquals(true, JfrOptions.isPersistedToDisk());
135+
Assert.assertEquals(360, JfrOptions.getMaxAge());
136+
Assert.assertEquals(10*K, JfrOptions.getMaxRecordingSize());
137+
Assert.assertEquals(true, JfrOptions.trackPathToGcRoots());
138+
}
139+
140+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2020, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jdk.jfr;
28+
29+
public class JavaJfrUtils {
30+
public static boolean isJFRClass(Class<?> clazz) {
31+
32+
if (clazz.isInterface()) {
33+
return false;
34+
}
35+
36+
Class<?> targetClass = clazz;
37+
String targetClassName = targetClass.getCanonicalName();
38+
39+
// a bit convoluted but needed to avoid referencing classes by name so we don't need to open internal
40+
// jfr packages
41+
42+
while (targetClassName != null && !targetClassName.equals("java.lang.Object")) {
43+
if (targetClassName.equals("jdk.internal.event.Event") ||
44+
targetClassName.equals("jdk.jfr.internal.handlers.EventHandler")) {
45+
return true;
46+
}
47+
48+
targetClass = targetClass.getSuperclass();
49+
targetClassName = targetClass.getCanonicalName();
50+
}
51+
52+
return false;
53+
}
54+
55+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2020, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jdk.jfr;
28+
29+
import com.oracle.svm.core.jdk.jfr.recorder.JfrRecorder;
30+
import com.oracle.svm.core.jdk.jfr.support.JfrThreadLocal;
31+
32+
public class Jfr {
33+
34+
public static boolean isEnabled() {
35+
return JfrRecorder.isEnabled();
36+
}
37+
38+
public static boolean isDisabled() {
39+
return JfrRecorder.isDisabled();
40+
}
41+
42+
public static boolean isRecording() {
43+
return JfrRecorder.isRecording();
44+
}
45+
46+
public static void excludeThread(Thread t) {
47+
JfrThreadLocal.excludeThread(t);
48+
}
49+
50+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.oracle.svm.core.jdk.jfr;
2+
3+
import java.util.function.BooleanSupplier;
4+
5+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
6+
7+
public class JfrAvailability {
8+
public static boolean withJfr = false;
9+
public static class WithJfr implements BooleanSupplier {
10+
@Override
11+
public boolean getAsBoolean() {
12+
return JavaVersionUtil.JAVA_SPEC >= 11 && withJfr;
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)