diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 03079cf2a7cf..4d093a281784 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -1488,7 +1488,7 @@ public static boolean hasDumpRuntimeCompiledMethodsSupport() { return !Platform.includedIn(Platform.WINDOWS.class) && ConcealedOptions.DumpRuntimeCompiledMethods.getValue(); } - @Option(help = "file:doc-files/TrackDynamicAccessHelp.txt")// + @Option(help = "file:doc-files/TrackDynamicAccessHelp.txt", stability = OptionStability.EXPERIMENTAL)// public static final HostedOptionKey TrackDynamicAccess = new HostedOptionKey<>( AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/TrackDynamicAccessHelp.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/TrackDynamicAccessHelp.txt index 26921c04af39..c5cca972b525 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/TrackDynamicAccessHelp.txt +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/TrackDynamicAccessHelp.txt @@ -3,7 +3,7 @@ The analysis is limited to the provided comma-separated list of class-path entri If any dynamic access calls are found, a "dynamic-access" directory is created in the native image output, and the calls are serialized in "dynamic-access//[reflection-calls.json][resource-calls.json]". -Usage: -H:TrackDynamicAccess=[all|none|to-console|path=|module=|package=][,...] +Usage: -H:TrackDynamicAccess=[all|none|to-console|no-dump|path=|module=|package=][,...] The flag can be used in following ways: 1. -H:TrackDynamicAccess=all reports all dynamic access calls made across the entire project @@ -12,7 +12,8 @@ The flag can be used in following ways: 4. -H:TrackDynamicAccess=package= reports all dynamic access calls made from the specified package 5. -H:TrackDynamicAccess=none disables all previous selections for dynamic access detection 6. -H:TrackDynamicAccess=to-console outputs all detected dynamic access calls to the console -7. A comma-separated list of the previous cases. For example, -H:TrackDynamicAccess=path=,module=,package= +7. -H:TrackDynamicAccess=no-dump disables the serialization of detected dynamic access calls +8. A comma-separated list of the previous cases. For example, -H:TrackDynamicAccess=path=,module=,package= Example of the option usage: diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/DynamicAccessDetectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/DynamicAccessDetectionFeature.java index 6fcf40a8f384..8ee4a990cd21 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/DynamicAccessDetectionFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/DynamicAccessDetectionFeature.java @@ -71,7 +71,7 @@ @AutomaticallyRegisteredFeature public final class DynamicAccessDetectionFeature implements InternalFeature { - private record MethodsByAccessKind(Map methodsByAccessKind) { + public record MethodsByAccessKind(Map methodsByAccessKind) { MethodsByAccessKind() { this(new ConcurrentSkipListMap<>()); } @@ -85,7 +85,7 @@ public CallLocationsByMethod getCallLocationsByMethod(DynamicAccessDetectionPhas } } - private record CallLocationsByMethod(Map> callLocationsByMethod) { + public record CallLocationsByMethod(Map> callLocationsByMethod) { CallLocationsByMethod() { this(new ConcurrentSkipListMap<>()); } @@ -113,6 +113,7 @@ public ConcurrentLinkedQueue getMethodCallLocations(String methodName) { private static final String OUTPUT_DIR_NAME = "dynamic-access"; private static final String TRACK_NONE = "none"; private static final String TO_CONSOLE = "to-console"; + private static final String NO_DUMP = "no-dump"; private UnmodifiableEconomicSet sourceEntries; // Class path entries and module or // package names @@ -122,6 +123,7 @@ public ConcurrentLinkedQueue getMethodCallLocations(String methodName) { private final OptionValues hostedOptionValues = HostedOptionValues.singleton(); private boolean printToConsole; + private boolean dumpJsonFiles = true; public DynamicAccessDetectionFeature() { callsBySourceEntry = new ConcurrentSkipListMap<>(); @@ -169,7 +171,7 @@ private void printReportForEntry(String entry) { } } - public static Path getOrCreateDirectory(Path directory) throws IOException { + private static Path getOrCreateDirectory(Path directory) throws IOException { if (Files.exists(directory)) { if (!Files.isDirectory(directory)) { throw new NoSuchFileException(directory.toString(), null, @@ -225,7 +227,9 @@ private static String toMethodJson(DynamicAccessDetectionPhase.DynamicAccessKind public void reportDynamicAccess() { for (String entry : sourceEntries) { if (callsBySourceEntry.containsKey(entry)) { - dumpReportForEntry(entry); + if (dumpJsonFiles) { + dumpReportForEntry(entry); + } if (printToConsole) { printReportForEntry(entry); } @@ -299,10 +303,13 @@ public void afterRegistration(AfterRegistrationAccess access) { AccumulatingLocatableMultiOptionValue.Strings options = SubstrateOptions.TrackDynamicAccess.getValue(); for (String optionValue : options.values()) { - if (optionValue.equals(TO_CONSOLE)) { - printToConsole = true; - } else if (optionValue.equals(TRACK_NONE)) { - printToConsole = false; + switch (optionValue) { + case TO_CONSOLE -> printToConsole = true; + case NO_DUMP -> dumpJsonFiles = false; + case TRACK_NONE -> { + printToConsole = false; + dumpJsonFiles = true; + } } } @@ -324,8 +331,8 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { } private static String dynamicAccessPossibleOptions() { - return String.format("[%s, %s, %s, %s]", - TRACK_ALL, TRACK_NONE, TO_CONSOLE, IncludeOptionsSupport.possibleExtendedOptions()); + return String.format("[%s, %s, %s, %s, %s]", + TRACK_ALL, TRACK_NONE, TO_CONSOLE, NO_DUMP, IncludeOptionsSupport.possibleExtendedOptions()); } public static void parseDynamicAccessOptions(EconomicMap, Object> hostedValues, NativeImageClassLoaderSupport classLoaderSupport) { @@ -340,8 +347,8 @@ public static void parseDynamicAccessOptions(EconomicMap, Object> h switch (option) { case TRACK_ALL -> classLoaderSupport.setTrackAllDynamicAccess(valueWithOrigin); case TRACK_NONE -> classLoaderSupport.clearDynamicAccessSelectors(); - case TO_CONSOLE -> { - // This option is parsed later in the afterRegistration hook + case TO_CONSOLE, NO_DUMP -> { + // These options are parsed later in the afterRegistration hook } default -> parseIncludeSelector(optionArgument, valueWithOrigin, classLoaderSupport.getDynamicAccessSelectors(), IncludeOptionsSupport.ExtendedOption.parse(option), dynamicAccessPossibleOptions());