Skip to content

Commit 048e550

Browse files
author
Christian Wimmer
committed
Support Flight Recorder at image build time
1 parent aaf921f commit 048e550

File tree

7 files changed

+228
-40
lines changed

7 files changed

+228
-40
lines changed

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
@@ -188,8 +188,6 @@ public static void registerInvocationPlugins(AnnotationSubstitutionProcessor ann
188188
registerArrayPlugins(plugins, snippetReflection, parsingReason);
189189
registerClassPlugins(plugins, snippetReflection);
190190
registerEdgesPlugins(metaAccess, plugins);
191-
registerJFRThrowablePlugins(plugins, replacements);
192-
registerJFREventTokenPlugins(plugins, replacements);
193191
registerVMConfigurationPlugins(snippetReflection, plugins);
194192
registerPlatformPlugins(snippetReflection, plugins);
195193
registerAWTPlugins(plugins);
@@ -969,39 +967,6 @@ protected static long longValue(GraphBuilderContext b, ResolvedJavaMethod target
969967
return node.asJavaConstant().asLong();
970968
}
971969

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

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

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

2727
import java.util.function.BooleanSupplier;
2828

29+
import org.graalvm.compiler.api.replacements.Fold;
2930
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
31+
import org.graalvm.nativeimage.ImageSingletons;
3032

3133
import com.oracle.svm.core.OS;
32-
import com.oracle.svm.core.VMInspectionOptions;
3334

3435
/**
3536
* Used to include/exclude JFR feature and substitutions.
@@ -40,15 +41,16 @@ public boolean getAsBoolean() {
4041
return get();
4142
}
4243

44+
@Fold
4345
public static boolean get() {
44-
return VMInspectionOptions.AllowVMInspection.getValue() && jvmVersionSupported() && osSupported();
46+
return ImageSingletons.contains(JfrFeature.class);
4547
}
4648

47-
private static boolean jvmVersionSupported() {
49+
static boolean jvmVersionSupported() {
4850
return JavaVersionUtil.JAVA_SPEC >= 11;
4951
}
5052

51-
private static boolean osSupported() {
53+
static boolean osSupported() {
5254
return OS.getCurrent() == OS.LINUX || OS.getCurrent() == OS.DARWIN;
5355
}
5456
}

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

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,24 @@
2626

2727
//Checkstyle: allow reflection
2828

29+
import java.io.IOException;
30+
import java.lang.management.ManagementFactory;
2931
import java.lang.reflect.Field;
3032
import java.util.Collection;
3133
import java.util.Collections;
3234
import java.util.List;
3335
import java.util.Set;
36+
import java.util.function.BooleanSupplier;
3437

3538
import org.graalvm.nativeimage.ImageSingletons;
3639
import org.graalvm.nativeimage.Platform;
3740
import org.graalvm.nativeimage.Platforms;
3841
import org.graalvm.nativeimage.hosted.Feature;
3942
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
4043
import org.graalvm.nativeimage.hosted.RuntimeReflection;
44+
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
4145

46+
import com.oracle.svm.core.VMInspectionOptions;
4247
import com.oracle.svm.core.annotate.AutomaticFeature;
4348
import com.oracle.svm.core.annotate.Uninterruptible;
4449
import com.oracle.svm.core.hub.DynamicHub;
@@ -47,12 +52,14 @@
4752
import com.oracle.svm.core.meta.SharedType;
4853
import com.oracle.svm.core.thread.ThreadListenerFeature;
4954
import com.oracle.svm.core.thread.ThreadListenerSupport;
55+
import com.oracle.svm.core.util.UserError;
5056
import com.oracle.svm.core.util.VMError;
5157
import com.oracle.svm.hosted.FeatureImpl;
5258
import com.oracle.svm.jfr.traceid.JfrTraceId;
5359
import com.oracle.svm.jfr.traceid.JfrTraceIdEpoch;
5460
import com.oracle.svm.jfr.traceid.JfrTraceIdMap;
5561
import com.oracle.svm.util.ModuleSupport;
62+
import com.sun.management.HotSpotDiagnosticMXBean;
5663

5764
import jdk.jfr.Configuration;
5865
import jdk.jfr.Event;
@@ -104,9 +111,44 @@
104111
@AutomaticFeature
105112
public class JfrFeature implements Feature {
106113

114+
public static final class JfrHostedEnabled implements BooleanSupplier {
115+
@Override
116+
public boolean getAsBoolean() {
117+
return ImageSingletons.contains(JfrFeature.class) && ImageSingletons.lookup(JfrFeature.class).hostedEnabled;
118+
}
119+
}
120+
121+
private final boolean hostedEnabled;
122+
123+
public JfrFeature() {
124+
hostedEnabled = Boolean.valueOf(getDiagnosticBean().getVMOption("FlightRecorder").getValue());
125+
}
126+
107127
@Override
108128
public boolean isInConfiguration(IsInConfigurationAccess access) {
109-
return JfrEnabled.get();
129+
boolean systemSupported = JfrEnabled.jvmVersionSupported() && JfrEnabled.osSupported();
130+
if (hostedEnabled && !systemSupported) {
131+
throw UserError.abort("FlightRecorder cannot be used to profile the image generator on this platform. " +
132+
"The image generator can only be profiled on platforms where FlightRecoder is also supported at run time.");
133+
}
134+
boolean runtimeEnabled = VMInspectionOptions.AllowVMInspection.getValue();
135+
if (hostedEnabled && !runtimeEnabled) {
136+
// Checkstyle: stop
137+
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. " +
138+
"This can affect the measurements because it can can make the image larger and image build time longer.");
139+
// Checkstyle: resume
140+
runtimeEnabled = true;
141+
}
142+
return runtimeEnabled && systemSupported;
143+
}
144+
145+
private static HotSpotDiagnosticMXBean getDiagnosticBean() {
146+
try {
147+
return ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
148+
"com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
149+
} catch (IOException e) {
150+
throw VMError.shouldNotReachHere("Cannot create HotSpotDiagnosticMXBean diagnostic bean.", e);
151+
}
110152
}
111153

112154
@Override
@@ -134,6 +176,14 @@ public void afterRegistration(AfterRegistrationAccess access) {
134176
JfrSerializerSupport.get().register(new JfrFrameTypeSerializer());
135177
JfrSerializerSupport.get().register(new JfrThreadStateSerializer());
136178
ThreadListenerSupport.get().register(SubstrateJVM.getThreadLocal());
179+
180+
if (hostedEnabled) {
181+
RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
182+
rci.initializeAtBuildTime("jdk.management.jfr", "Allow FlightRecorder to be used at image build time");
183+
rci.initializeAtBuildTime("com.sun.jmx.mbeanserver", "Allow FlightRecorder to be used at image build time");
184+
rci.initializeAtBuildTime("com.sun.jmx.defaults", "Allow FlightRecorder to be used at image build time");
185+
rci.initializeAtBuildTime("java.beans", "Allow FlightRecorder to be used at image build time");
186+
}
137187
}
138188

139189
@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)