Skip to content

Commit 8c210f7

Browse files
author
Aleksandar Gradinac
committed
Trace class initialization and object instantiation using a JVMTI agent.
1 parent e666b90 commit 8c210f7

File tree

27 files changed

+1075
-287
lines changed

27 files changed

+1075
-287
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeClassInitializationSupport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -54,7 +54,7 @@ public interface RuntimeClassInitializationSupport {
5454

5555
void initializeAtBuildTime(Class<?> aClass, String reason);
5656

57-
void reportClassInitialized(Class<?> aClass);
57+
void reportClassInitialized(Class<?> aClass, StackTraceElement[] stackTrace);
5858

59-
void reportObjectInstantiated(Object o);
59+
void reportObjectInstantiated(Object o, StackTraceElement[] stackTrace);
6060
}

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/clinit/ClassInitializationTracking.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -67,21 +67,21 @@ public class ClassInitializationTracking {
6767
* This method is called from the instrumented class initialization methods.
6868
*/
6969
@SuppressWarnings({"unused", "ConstantConditions"})
70-
public static void reportClassInitialized(Class<?> c) {
70+
public static void reportClassInitialized(Class<?> c, StackTraceElement[] stackTrace) {
7171
if (ImageSingletonsSupport.isInstalled() && ImageSingletons.contains(RuntimeClassInitializationSupport.class)) {
7272
RuntimeClassInitializationSupport runtimeClassInitialization = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
73-
runtimeClassInitialization.reportClassInitialized(c);
73+
runtimeClassInitialization.reportClassInitialized(c, stackTrace);
7474
}
7575
}
7676

7777
/**
7878
* This method is called from the instrumented class initialization methods.
7979
*/
8080
@SuppressWarnings({"unused"})
81-
public static void reportObjectInstantiated(Object o) {
81+
public static void reportObjectInstantiated(Object o, StackTraceElement[] stackTrace) {
8282
if (ImageSingletonsSupport.isInstalled() && ImageSingletons.contains(RuntimeClassInitializationSupport.class)) {
8383
RuntimeClassInitializationSupport runtimeClassInitialization = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
84-
runtimeClassInitialization.reportObjectInstantiated(o);
84+
runtimeClassInitialization.reportObjectInstantiated(o, stackTrace);
8585
}
8686
}
8787

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# ----------------------------------------------------------------------------------------------------
33
#
4-
# Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
4+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
55
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66
#
77
# This code is free software; you can redistribute it and/or modify it
@@ -293,7 +293,7 @@ def run_musl_basic_tests():
293293
def native_image_context(common_args=None, hosted_assertions=True, native_image_cmd='', config=None, build_if_missing=False):
294294
config = config or graalvm_config()
295295
common_args = [] if common_args is None else common_args
296-
base_args = ['--no-fallback', '-H:+EnforceMaxRuntimeCompileMethods', '-H:+TraceClassInitialization']
296+
base_args = ['--no-fallback', '-H:+EnforceMaxRuntimeCompileMethods']
297297
base_args += ['-H:Path=' + svmbuild_dir()]
298298
has_server = mx.get_os() != 'windows'
299299
if mx.get_opts().verbose:
@@ -862,6 +862,17 @@ def _native_image_launcher_extra_jvm_args():
862862
'--features=com.oracle.svm.agent.NativeImageAgent$RegistrationFeature'
863863
],
864864
),
865+
mx_sdk_vm.LibraryConfig(
866+
destination="<lib:native-image-diagnostics-agent>",
867+
jvm_library=True,
868+
jar_distributions=[
869+
'substratevm:JVMTI_AGENT_BASE',
870+
'substratevm:SVM_DIAGNOSTICS_AGENT',
871+
],
872+
build_args=[
873+
'--features=com.oracle.svm.diagnosticsagent.NativeImageDiagnosticsAgent$RegistrationFeature',
874+
],
875+
),
865876
],
866877
provided_executables=['bin/<cmd:rebuild-images>'],
867878
installable=True,
@@ -1081,7 +1092,6 @@ def build_and_test_clinittest_image(native_image, args=None):
10811092
native_image(
10821093
['-H:Path=' + build_dir, '-cp', test_cp, '-H:Class=com.oracle.svm.test.TestClassInitializationMustBeSafe',
10831094
'-H:Features=com.oracle.svm.test.TestClassInitializationMustBeSafeFeature',
1084-
'-H:+TraceClassInitialization',
10851095
'-H:+PrintClassInitialization', '-H:Name=clinittest', '-H:+ReportExceptionStackTraces'] + args)
10861096
mx.run([join(build_dir, 'clinittest')])
10871097

substratevm/mx.substratevm/mx_substratevm_benchmark.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ def list_jars(path):
8181
'-Dnative-image.benchmark.extra-image-build-argument=-H:-ThrowUnsafeOffsetErrors'],
8282
'finagle-http' : ['-Dnative-image.benchmark.extra-image-build-argument=--initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access', '-Dnative-image.benchmark.extra-image-build-argument=--allow-incomplete-classpath'],
8383
'log-regression' : ['-Dnative-image.benchmark.extra-image-build-argument=--allow-incomplete-classpath',
84-
'-Dnative-image.benchmark.extra-image-build-argument=-H:+TraceClassInitialization',
8584
'-Dnative-image.benchmark.extra-image-build-argument=-H:IncludeResourceBundles=sun.security.util.Resources,javax.servlet.http.LocalStrings,javax.servlet.LocalStrings',
8685
'-Dnative-image.benchmark.extra-image-build-argument=--report-unsupported-elements-at-runtime',
8786
'-Dnative-image.benchmark.extra-image-build-argument=-H:-ThrowUnsafeOffsetErrors',

substratevm/mx.substratevm/suite.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,24 @@
854854
"spotbugs": "false",
855855
},
856856

857+
"com.oracle.svm.diagnosticsagent": {
858+
"subDir": "src",
859+
"sourceDirs": [
860+
"src",
861+
"resources"
862+
],
863+
"dependencies": [
864+
"JVMTI_AGENT_BASE",
865+
],
866+
"checkstyle": "com.oracle.svm.driver",
867+
"workingSets": "SVM",
868+
"annotationProcessors": [
869+
"compiler:GRAAL_PROCESSOR",
870+
],
871+
"javaCompliance": "8+",
872+
"spotbugs": "false",
873+
},
874+
857875
"com.oracle.svm.truffle.tck" : {
858876
"subDir": "src",
859877
"sourceDirs": ["src"],
@@ -1063,6 +1081,18 @@
10631081
# vm: included as binary, tool descriptor intentionally not copied
10641082
},
10651083

1084+
"SVM_DIAGNOSTICS_AGENT": {
1085+
"subDir": "src",
1086+
"description" : "Native-image diagnostics agent",
1087+
"dependencies": [
1088+
"com.oracle.svm.diagnosticsagent",
1089+
],
1090+
"distDependencies": [
1091+
"JVMTI_AGENT_BASE",
1092+
"LIBRARY_SUPPORT",
1093+
],
1094+
},
1095+
10661096
"SVM_CONFIGURE": {
10671097
"subDir": "src",
10681098
"description" : "SubstrateVM native-image configuration tool",

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ private static boolean loadClass(JNIEnvironment jni, Breakpoint bp) {
820820
JNIObjectHandle callerClass = nullHandle();
821821
JvmtiFrameInfo frameInfo = StackValue.get(JvmtiFrameInfo.class);
822822
CIntPointer frameCountPtr = StackValue.get(CIntPointer.class);
823-
if (jvmtiFunctions().GetStackTrace().invoke(jvmtiEnv(), nullHandle(), 1, 1, frameInfo, frameCountPtr) == JvmtiError.JVMTI_ERROR_NONE && frameCountPtr.read() == 1) {
823+
if (jvmtiFunctions().GetStackTrace().invoke(jvmtiEnv(), nullHandle(), 1, 1, (WordPointer) frameInfo, frameCountPtr) == JvmtiError.JVMTI_ERROR_NONE && frameCountPtr.read() == 1) {
824824
callerClass = getMethodDeclaringClass(frameInfo.getMethod());
825825
if (callerClass.notEqual(nullHandle()) && jniFunctions().getIsAssignableFrom().invoke(jni, callerClass, agent.handles().javaLangClassLoader)) {
826826
// ignore recursive class loader calls, we must have seen the root invocation

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -251,8 +251,13 @@ public Boolean getValue(OptionValues values) {
251251
@Option(help = "Trace VMOperation execution.")//
252252
public static final HostedOptionKey<Boolean> TraceVMOperations = new HostedOptionKey<>(false);
253253

254-
@Option(help = "Instrument code to trace and report class initialization.")//
255-
public static final HostedOptionKey<Boolean> TraceClassInitialization = new HostedOptionKey<>(false);
254+
@APIOption(name = "trace-class-initialization")//
255+
@Option(help = "Comma-separated list of fully qualified class names that class initialization is traced for.")//
256+
public static final HostedOptionKey<String> TraceClassInitialization = new HostedOptionKey<>("");
257+
258+
@APIOption(name = "trace-object-instantiation")//
259+
@Option(help = "Comma-separated list of fully qualified class names that object instantiation is traced for.")//
260+
public static final HostedOptionKey<String> TraceObjectInstantiation = new HostedOptionKey<>("");
256261

257262
@Option(help = "Prefix that is added to the names of entry point methods.")//
258263
public static final HostedOptionKey<String> EntryPointNamePrefix = new HostedOptionKey<>("");

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/SubstrateOptionsParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ public static String commandArgument(OptionKey<?> option, String value, String a
595595
} else {
596596
for (APIOption apiOption : apiOptions) {
597597
String fixedValue = apiOption.fixedValue().length == 0 ? null : apiOption.fixedValue()[0];
598-
if (apiOption.name().equals(apiOptionName)) {
598+
if (apiOptionName == null || apiOption.name().equals(apiOptionName)) {
599599
if (fixedValue == null) {
600600
return APIOption.Utils.name(apiOption) + "=" + value;
601601
} else if (value.equals(fixedValue)) {

0 commit comments

Comments
 (0)