Skip to content

Commit 9932312

Browse files
author
Christian Wimmer
committed
[GR-35806] Support Flight Recorder at image build time.
PullRequest: graal/10580
2 parents 068f2b1 + 72898a6 commit 9932312

File tree

9 files changed

+245
-52
lines changed

9 files changed

+245
-52
lines changed

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ def svm_gate_body(args, tasks):
322322
javac_command = ['--javac-command', ' '.join(javac_image_command(svmbuild_dir()))]
323323
helloworld(['--output-path', svmbuild_dir()] + javac_command)
324324
helloworld(['--output-path', svmbuild_dir(), '--shared']) # Build and run helloworld as shared library
325+
if not mx.is_windows():
326+
helloworld(['--output-path', svmbuild_dir(), '-J-XX:StartFlightRecording=dumponexit=true']) # Build and run helloworld with FlightRecorder at image build time
325327
cinterfacetutorial([])
326328
clinittest([])
327329

substratevm/mx.substratevm/suite.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@
590590
"jdk.unsupported"
591591
],
592592
"requiresConcealed": {
593+
"jdk.management": [
594+
"com.sun.management.internal"
595+
],
593596
"jdk.jfr": [
594597
"jdk.jfr.internal",
595598
"jdk.jfr.internal.consumer",

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ public static void registerInvocationPlugins(AnnotationSubstitutionProcessor ann
186186
registerArrayPlugins(plugins, snippetReflection, parsingReason);
187187
registerClassPlugins(plugins, snippetReflection);
188188
registerEdgesPlugins(metaAccess, plugins);
189-
registerJFRThrowablePlugins(plugins, replacements);
190-
registerJFREventTokenPlugins(plugins, replacements);
191189
registerVMConfigurationPlugins(snippetReflection, plugins);
192190
registerPlatformPlugins(snippetReflection, plugins);
193191
registerAWTPlugins(plugins);
@@ -966,39 +964,6 @@ protected static long longValue(GraphBuilderContext b, ResolvedJavaMethod target
966964
return node.asJavaConstant().asLong();
967965
}
968966

969-
/*
970-
* When Java Flight Recorder is enabled during image generation, the bytecodes of some methods
971-
* get instrumented. Undo the instrumentation so that it does not end up in the generated image.
972-
*/
973-
974-
private static void registerJFRThrowablePlugins(InvocationPlugins plugins, Replacements replacements) {
975-
Registration r = new Registration(plugins, "oracle.jrockit.jfr.jdkevents.ThrowableTracer", replacements).setAllowOverwrite(true);
976-
r.register2("traceError", Error.class, String.class, new InvocationPlugin() {
977-
@Override
978-
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode throwable, ValueNode message) {
979-
return true;
980-
}
981-
});
982-
r.register2("traceThrowable", Throwable.class, String.class, new InvocationPlugin() {
983-
@Override
984-
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode throwable, ValueNode message) {
985-
return true;
986-
}
987-
});
988-
}
989-
990-
private static void registerJFREventTokenPlugins(InvocationPlugins plugins, Replacements replacements) {
991-
Registration r = new Registration(plugins, "com.oracle.jrockit.jfr.EventToken", replacements);
992-
r.register1("isEnabled", Receiver.class, new InvocationPlugin() {
993-
@Override
994-
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
995-
receiver.get();
996-
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(false));
997-
return true;
998-
}
999-
});
1000-
}
1001-
1002967
private static void registerVMConfigurationPlugins(SnippetReflectionProvider snippetReflection, InvocationPlugins plugins) {
1003968
Registration r = new Registration(plugins, ImageSingletons.class);
1004969
r.register1("contains", Class.class, new InvocationPlugin() {

substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrEnabled.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@
2626

2727
import java.util.function.BooleanSupplier;
2828

29-
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
30-
31-
import com.oracle.svm.core.OS;
32-
import com.oracle.svm.core.VMInspectionOptions;
29+
import org.graalvm.compiler.api.replacements.Fold;
30+
import org.graalvm.nativeimage.ImageSingletons;
3331

3432
/**
3533
* Used to include/exclude JFR feature and substitutions.
@@ -40,15 +38,8 @@ public boolean getAsBoolean() {
4038
return get();
4139
}
4240

41+
@Fold
4342
public static boolean get() {
44-
return VMInspectionOptions.AllowVMInspection.getValue() && jvmVersionSupported() && osSupported();
45-
}
46-
47-
private static boolean jvmVersionSupported() {
48-
return JavaVersionUtil.JAVA_SPEC >= 11;
49-
}
50-
51-
private static boolean osSupported() {
52-
return OS.getCurrent() == OS.LINUX || OS.getCurrent() == OS.DARWIN;
43+
return ImageSingletons.contains(JfrFeature.class);
5344
}
5445
}

substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@
3131
import java.util.Collections;
3232
import java.util.List;
3333
import java.util.Set;
34+
import java.util.function.BooleanSupplier;
3435

36+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
3537
import org.graalvm.nativeimage.ImageSingletons;
36-
import org.graalvm.nativeimage.Platform;
37-
import org.graalvm.nativeimage.Platforms;
3838
import org.graalvm.nativeimage.hosted.Feature;
3939
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
4040
import org.graalvm.nativeimage.hosted.RuntimeReflection;
41+
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
4142

43+
import com.oracle.svm.core.OS;
44+
import com.oracle.svm.core.VMInspectionOptions;
4245
import com.oracle.svm.core.annotate.AutomaticFeature;
4346
import com.oracle.svm.core.annotate.Uninterruptible;
4447
import com.oracle.svm.core.hub.DynamicHub;
@@ -47,12 +50,16 @@
4750
import com.oracle.svm.core.meta.SharedType;
4851
import com.oracle.svm.core.thread.ThreadListenerFeature;
4952
import com.oracle.svm.core.thread.ThreadListenerSupport;
53+
import com.oracle.svm.core.util.UserError;
5054
import com.oracle.svm.core.util.VMError;
5155
import com.oracle.svm.hosted.FeatureImpl;
5256
import com.oracle.svm.jfr.traceid.JfrTraceId;
5357
import com.oracle.svm.jfr.traceid.JfrTraceIdEpoch;
5458
import com.oracle.svm.jfr.traceid.JfrTraceIdMap;
5559
import com.oracle.svm.util.ModuleSupport;
60+
import com.oracle.svm.util.ReflectionUtil;
61+
import com.sun.management.HotSpotDiagnosticMXBean;
62+
import com.sun.management.internal.PlatformMBeanProviderImpl;
5663

5764
import jdk.jfr.Configuration;
5865
import jdk.jfr.Event;
@@ -100,13 +107,59 @@
100107
* consistent state).</li>
101108
* </ul>
102109
*/
103-
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
104110
@AutomaticFeature
105111
public class JfrFeature implements Feature {
106112

113+
public static final class JfrHostedEnabled implements BooleanSupplier {
114+
@Override
115+
public boolean getAsBoolean() {
116+
return ImageSingletons.contains(JfrFeature.class) && ImageSingletons.lookup(JfrFeature.class).hostedEnabled;
117+
}
118+
}
119+
120+
private final boolean hostedEnabled;
121+
122+
public JfrFeature() {
123+
hostedEnabled = Boolean.valueOf(getDiagnosticBean().getVMOption("FlightRecorder").getValue());
124+
}
125+
107126
@Override
108127
public boolean isInConfiguration(IsInConfigurationAccess access) {
109-
return JfrEnabled.get();
128+
boolean systemSupported = jvmVersionSupported() && osSupported();
129+
if (hostedEnabled && !systemSupported) {
130+
throw UserError.abort("FlightRecorder cannot be used to profile the image generator on this platform. " +
131+
"The image generator can only be profiled on platforms where FlightRecoder is also supported at run time.");
132+
}
133+
boolean runtimeEnabled = VMInspectionOptions.AllowVMInspection.getValue();
134+
if (hostedEnabled && !runtimeEnabled) {
135+
// Checkstyle: stop
136+
System.err.println("Warning: When FlightRecoder is used to profile the image generator, it is also automatically enabled in the native image at run time. " +
137+
"This can affect the measurements because it can can make the image larger and image build time longer.");
138+
// Checkstyle: resume
139+
runtimeEnabled = true;
140+
}
141+
return runtimeEnabled && systemSupported;
142+
}
143+
144+
private static boolean jvmVersionSupported() {
145+
return JavaVersionUtil.JAVA_SPEC >= 11;
146+
}
147+
148+
private static boolean osSupported() {
149+
return OS.getCurrent() == OS.LINUX || OS.getCurrent() == OS.DARWIN;
150+
}
151+
152+
/**
153+
* We cannot use the proper way of looking up the bean via
154+
* {@link java.lang.management.ManagementFactory} because that initializes too many classes at
155+
* image build time that we want to initialize only at run time.
156+
*/
157+
private static HotSpotDiagnosticMXBean getDiagnosticBean() {
158+
try {
159+
return (HotSpotDiagnosticMXBean) ReflectionUtil.lookupMethod(PlatformMBeanProviderImpl.class, "getDiagnosticMXBean").invoke(null);
160+
} catch (ReflectiveOperationException ex) {
161+
throw VMError.shouldNotReachHere(ex);
162+
}
110163
}
111164

112165
@Override
@@ -134,6 +187,14 @@ public void afterRegistration(AfterRegistrationAccess access) {
134187
JfrSerializerSupport.get().register(new JfrFrameTypeSerializer());
135188
JfrSerializerSupport.get().register(new JfrThreadStateSerializer());
136189
ThreadListenerSupport.get().register(SubstrateJVM.getThreadLocal());
190+
191+
if (hostedEnabled) {
192+
RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
193+
rci.initializeAtBuildTime("jdk.management.jfr", "Allow FlightRecorder to be used at image build time");
194+
rci.initializeAtBuildTime("com.sun.jmx.mbeanserver", "Allow FlightRecorder to be used at image build time");
195+
rci.initializeAtBuildTime("com.sun.jmx.defaults", "Allow FlightRecorder to be used at image build time");
196+
rci.initializeAtBuildTime("java.beans", "Allow FlightRecorder to be used at image build time");
197+
}
137198
}
138199

139200
@Override
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.jfr;
26+
27+
import com.oracle.svm.core.annotate.Alias;
28+
import com.oracle.svm.core.annotate.RecomputeFieldValue;
29+
import com.oracle.svm.core.annotate.TargetClass;
30+
31+
@TargetClass(className = "com.sun.jmx.mbeanserver.MXBeanIntrospector", onlyWith = JfrFeature.JfrHostedEnabled.class)
32+
final class Target_com_sun_jmx_mbeanserver_MXBeanIntrospector {
33+
34+
/* Reset caches that are used at image build time when FlightRecorder is enabled. */
35+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "com.sun.jmx.mbeanserver.MXBeanIntrospector") //
36+
private static Target_com_sun_jmx_mbeanserver_MXBeanIntrospector instance;
37+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "com.sun.jmx.mbeanserver.MBeanIntrospector$MBeanInfoMap") //
38+
private static Target_com_sun_jmx_mbeanserver_MBeanIntrospector_MBeanInfoMap mbeanInfoMap;
39+
}
40+
41+
@TargetClass(className = "com.sun.jmx.mbeanserver.MBeanIntrospector", innerClass = "MBeanInfoMap")
42+
final class Target_com_sun_jmx_mbeanserver_MBeanIntrospector_MBeanInfoMap {
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.jfr;
26+
27+
import com.oracle.svm.core.annotate.Alias;
28+
import com.oracle.svm.core.annotate.RecomputeFieldValue;
29+
import com.oracle.svm.core.annotate.TargetClass;
30+
import com.oracle.svm.jfr.JfrFeature.JfrHostedEnabled;
31+
32+
@TargetClass(className = "com.sun.jmx.mbeanserver.MXBeanLookup", onlyWith = JfrHostedEnabled.class)
33+
final class Target_com_sun_jmx_mbeanserver_MXBeanLookup {
34+
35+
/* Reset caches that are used at image build time when FlightRecorder is enabled. */
36+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "com.sun.jmx.mbeanserver.WeakIdentityHashMap") //
37+
private static Target_com_sun_jmx_mbeanserver_WeakIdentityHashMap mbscToLookup;
38+
}
39+
40+
@TargetClass(className = "com.sun.jmx.mbeanserver.WeakIdentityHashMap")
41+
final class Target_com_sun_jmx_mbeanserver_WeakIdentityHashMap {
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.jfr;
26+
27+
import java.util.ArrayList;
28+
29+
import javax.management.MBeanServerBuilder;
30+
31+
import com.oracle.svm.core.annotate.Alias;
32+
import com.oracle.svm.core.annotate.RecomputeFieldValue;
33+
import com.oracle.svm.core.annotate.TargetClass;
34+
35+
@TargetClass(className = "javax.management.MBeanServerFactory", onlyWith = JfrFeature.JfrHostedEnabled.class)
36+
final class Target_javax_management_MBeanServerFactory {
37+
38+
/* Reset caches that are used at image build time when FlightRecorder is enabled. */
39+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias) //
40+
private static ArrayList<?> mBeanServerList = new ArrayList<>();
41+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias) //
42+
private static MBeanServerBuilder builder = null;
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.jfr;
26+
27+
import com.oracle.svm.core.annotate.Alias;
28+
import com.oracle.svm.core.annotate.RecomputeFieldValue;
29+
import com.oracle.svm.core.annotate.TargetClass;
30+
import com.oracle.svm.jfr.JfrFeature.JfrHostedEnabled;
31+
32+
import jdk.jfr.FlightRecorder;
33+
34+
@TargetClass(value = jdk.jfr.FlightRecorder.class, onlyWith = JfrHostedEnabled.class)
35+
final class Target_jdk_jfr_FlightRecorder {
36+
/*
37+
* Ignore all state of the FlightRecorder maintained when profiling the image generator itself.
38+
*/
39+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
40+
private static FlightRecorder platformRecorder;
41+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
42+
private static boolean initialized;
43+
}

0 commit comments

Comments
 (0)