From dea1968b44a7507a77cd17e4ac5d54126de4e982 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Mon, 30 Sep 2024 14:23:15 +0200 Subject: [PATCH 1/2] Test --- .github/workflows/quarkus.yml | 26 +++ .github/workflows/reachability-metadata.yml | 38 ++- .github/workflows/spring.yml | 3 + .../impl/RuntimeReflectionSupport.java | 17 ++ .../core/configure/ConfigurationParser.java | 2 + .../LegacyResourceConfigurationParser.java | 2 + ...egacySerializationConfigurationParser.java | 6 + .../ReflectionConfigurationParser.java | 6 + .../configure/ReflectionMetadataParser.java | 2 + .../ResourceConfigurationParser.java | 3 + .../SerializationMetadataParser.java | 5 + .../svm/hosted/HeapBreakdownProvider.java | 5 +- .../oracle/svm/hosted/ProgressReporter.java | 221 +++++++++--------- .../hosted/ProgressReporterJsonHelper.java | 2 + .../hosted/reflect/ReflectionDataBuilder.java | 1 + .../oracle/svm/util/ImageBuildStatistics.java | 3 +- 16 files changed, 230 insertions(+), 112 deletions(-) diff --git a/.github/workflows/quarkus.yml b/.github/workflows/quarkus.yml index 289551edb574..e6019ebdf955 100644 --- a/.github/workflows/quarkus.yml +++ b/.github/workflows/quarkus.yml @@ -170,8 +170,10 @@ jobs: if: startsWith(matrix.os-name, 'ubuntu') env: TEST_MODULES: ${{matrix.test-modules}} + MATRIX_DUMP: ${{ toJson(matrix) }} run: | cd ${QUARKUS_PATH} + echo "$MATRIX_DUMP" ${GRAALVM_HOME}/bin/native-image --version ./mvnw $COMMON_MAVEN_ARGS -f integration-tests -pl "$TEST_MODULES" $NATIVE_TEST_MAVEN_ARGS - name: Prepare failure archive (if maven failed) @@ -184,3 +186,27 @@ jobs: with: name: test-reports-native-${{matrix.category}} path: 'test-reports.tgz' + - name: "Probe stats" + run: ls ${QUARKUS_PATH}/integration-tests/*/target/quarkus-integration-test-*-999-SNAPSHOT-native-image-source-jar/reports + - name: "Upload stats" + id: upload + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: ${{ strategy.job-index }} + path: ${{ env.QUARKUS_PATH }}/integration-tests/*/target/quarkus-integration-test-*-999-SNAPSHOT-native-image-source-jar/reports/stats.json + retention-days: 1 + + gather-stats: + name: "Gather stats files" + runs-on: ubuntu-latest + if: success() || failure() + needs: [ native-tests ] + steps: + - name: "Download build stats" + uses: actions/download-artifact@v4 + with: + path: artifacts + - name: "Report build stats" + run: | + grep . artifacts/*/*/*/*/*/stats.json diff --git a/.github/workflows/reachability-metadata.yml b/.github/workflows/reachability-metadata.yml index b19d621f5103..8d9cd0ab2285 100644 --- a/.github/workflows/reachability-metadata.yml +++ b/.github/workflows/reachability-metadata.yml @@ -108,7 +108,8 @@ jobs: - name: "Checkout oracle/graalvm-reachability-metadata" uses: actions/checkout@v4 with: - repository: oracle/graalvm-reachability-metadata + repository: loicottet/graalvm-reachability-metadata + ref: lottet/update - name: Download GraalVM JDK build uses: actions/download-artifact@v4 with: @@ -134,6 +135,37 @@ jobs: sudo systemctl daemon-reload sudo systemctl restart docker - name: "Run '${{ matrix.coordinates }}' tests" + id: run run: | - ./gradlew test -Pcoordinates=${{ matrix.coordinates }} - \ No newline at end of file + ./gradlew test -Pcoordinates=${{ matrix.coordinates }} --continue + - name: "Transform coordinate" + id: coordinate + run: | + echo ${{ matrix.coordinates }} > coords.txt + sed -i "s/:/\//g" coords.txt + echo "COORDS=$(cat coords.txt)" > $GITHUB_ENV + sed -i "s/\//-/g" coords.txt + echo "ESC_COORDS=$(cat coords.txt)" >> $GITHUB_ENV + - name: "Upload stats" + id: upload + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ESC_COORDS }} + path: tests/src/${{ env.COORDS }}/build/native/nativeTestCompile/reports/stats.json + retention-days: 1 + + gather-stats: + name: "Gather stats files" + runs-on: ubuntu-latest + if: success() || failure() + needs: [test-all-metadata] + steps: + - name: "Download build stats" + uses: actions/download-artifact@v4 + with: + path: artifacts + - name: "Report build stats" + run: | + grep . artifacts/*/stats.json + diff --git a/.github/workflows/spring.yml b/.github/workflows/spring.yml index 3d2c0a6efa58..33f627dcf64a 100644 --- a/.github/workflows/spring.yml +++ b/.github/workflows/spring.yml @@ -79,3 +79,6 @@ jobs: run: | cd ${{ env.SPRING_PETCLINIC_PATH }} ./gradlew nativeTest + - name: "Report build stats" + run: | + cat ${{ env.SPRING_PETCLINIC_PATH }}/build/native/nativeTestCompile/reports/stats.json diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java index 68e78b2c975b..e2b871586023 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java @@ -40,6 +40,8 @@ */ package org.graalvm.nativeimage.impl; +import java.util.concurrent.atomic.AtomicInteger; + public interface RuntimeReflectionSupport extends ReflectionRegistry { // needed as reflection-specific ImageSingletons key void registerAllMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz); @@ -67,4 +69,19 @@ public interface RuntimeReflectionSupport extends ReflectionRegistry { void registerAllSignersQuery(ConfigurationCondition condition, Class clazz); void registerClassLookupException(ConfigurationCondition condition, String typeName, Throwable t); + + AtomicInteger count = new AtomicInteger(0); + AtomicInteger relevantCount = new AtomicInteger(0); + + static void increaseCount(boolean interest) { + count.incrementAndGet(); + if (interest) { + relevantCount.incrementAndGet(); + } + } + + static int getCount(boolean interest) { + return interest ? relevantCount.get() : count.get(); + } + } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationParser.java index 23730c8a4ca2..f5c70f9f3164 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationParser.java @@ -46,6 +46,7 @@ import java.util.Set; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.core.SubstrateUtil; @@ -228,6 +229,7 @@ protected static long asLong(Object value, String propertyName) { protected UnresolvedConfigurationCondition parseCondition(EconomicMap data, boolean runtimeCondition) { Object conditionData = data.get(CONDITIONAL_KEY); if (conditionData != null) { + RuntimeReflectionSupport.increaseCount(false); EconomicMap conditionObject = asMap(conditionData, "Attribute 'condition' must be an object"); if (conditionObject.containsKey(TYPE_REACHABLE_KEY) && conditionObject.containsKey(TYPE_REACHED_KEY)) { failOnSchemaError("condition can not have both '" + TYPE_REACHED_KEY + "' and '" + TYPE_REACHABLE_KEY + "' set."); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyResourceConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyResourceConfigurationParser.java index 25487904cc63..dea22190332a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyResourceConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyResourceConfigurationParser.java @@ -31,6 +31,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.core.TypeResult; @@ -109,6 +110,7 @@ private void parseResourcesObject(Object resourcesObject, Object origin) { private void parsePatternEntry(Object data, BiConsumer resourceRegistry, GlobPatternConsumer globRegistry, String parentType) { EconomicMap resource = asMap(data, "Elements of " + parentType + " must be a resource descriptor object"); checkAttributes(resource, "regex resource descriptor object", Collections.singletonList("pattern"), Collections.singletonList(CONDITIONAL_KEY)); + RuntimeReflectionSupport.increaseCount(false); TypeResult resolvedConfigurationCondition = conditionResolver.resolveCondition(parseCondition(resource, false)); if (!resolvedConfigurationCondition.isPresent()) { return; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacySerializationConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacySerializationConfigurationParser.java index 46c92f8b389c..ac77d0371b11 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacySerializationConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacySerializationConfigurationParser.java @@ -30,6 +30,8 @@ import java.util.List; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; @@ -86,6 +88,7 @@ protected void parseSerializationDescriptorObject(EconomicMap da } else { checkAttributes(data, "serialization descriptor object", Collections.singleton(NAME_KEY), Arrays.asList(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY, CONDITIONAL_KEY)); } + RuntimeReflectionSupport.increaseCount(false); ConfigurationTypeDescriptor targetSerializationClass = new NamedConfigurationTypeDescriptor(asString(data.get(NAME_KEY))); UnresolvedConfigurationCondition unresolvedCondition = parseCondition(data, false); @@ -99,6 +102,9 @@ protected void parseSerializationDescriptorObject(EconomicMap da serializationSupport.registerLambdaCapturingClass(condition.get(), className); } else { Object optionalCustomCtorValue = data.get(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY); + if (optionalCustomCtorValue != null) { + RuntimeReflectionSupport.increaseCount(false); + } String customTargetConstructorClass = optionalCustomCtorValue != null ? asString(optionalCustomCtorValue) : null; if (targetSerializationClass instanceof NamedConfigurationTypeDescriptor namedClass) { serializationSupport.registerWithTargetConstructorClass(condition.get(), namedClass.name(), customTargetConstructorClass); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java index 349f586ff5f7..b4d970081440 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import com.oracle.svm.core.TypeResult; import com.oracle.svm.util.LogUtils; @@ -75,6 +76,9 @@ protected void parseClassArray(List classes) { protected abstract void parseClass(EconomicMap data); protected void registerIfNotDefault(EconomicMap data, boolean defaultValue, T clazz, String propertyName, Runnable register) { + if (data.containsKey(propertyName)) { + RuntimeReflectionSupport.increaseCount(false); + } if (data.containsKey(propertyName) ? asBoolean(data.get(propertyName), propertyName) : defaultValue) { try { register.run(); @@ -92,6 +96,7 @@ protected void parseFields(C condition, List fields, T clazz) { private void parseField(C condition, EconomicMap data, T clazz) { checkAttributes(data, "reflection field descriptor object", Collections.singleton("name"), Arrays.asList("allowWrite", "allowUnsafeAccess")); + RuntimeReflectionSupport.increaseCount(false); String fieldName = asString(data.get("name"), "name"); boolean allowWrite = data.containsKey("allowWrite") && asBoolean(data.get("allowWrite"), "allowWrite"); @@ -112,6 +117,7 @@ protected void parseMethods(C condition, boolean queriedOnly, List metho private void parseMethod(C condition, boolean queriedOnly, EconomicMap data, T clazz) { checkAttributes(data, "reflection method descriptor object", Collections.singleton("name"), Collections.singleton("parameterTypes")); + RuntimeReflectionSupport.increaseCount(false); String methodName = asString(data.get("name"), "name"); List methodParameterTypes = null; Object parameterTypes = data.get("parameterTypes"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java index 33bd0028be6c..982588099e97 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java @@ -31,6 +31,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.core.TypeResult; @@ -59,6 +60,7 @@ public void parseAndRegister(Object json, URI origin) { @Override protected void parseClass(EconomicMap data) { checkAttributes(data, "reflection class descriptor object", List.of(TYPE_KEY), OPTIONAL_REFLECT_METADATA_ATTRS); + RuntimeReflectionSupport.increaseCount(false); Optional type = parseTypeContents(data.get(TYPE_KEY)); if (type.isEmpty()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ResourceConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ResourceConfigurationParser.java index 01ec3fae048d..0c4663f816e2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ResourceConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ResourceConfigurationParser.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.core.TypeResult; @@ -69,6 +70,7 @@ protected void parseBundlesObject(Object bundlesObject) { private void parseBundle(Object bundle) { EconomicMap resource = asMap(bundle, "Elements of 'bundles' list must be a bundle descriptor object"); checkAttributes(resource, "bundle descriptor object", Collections.singletonList("name"), Arrays.asList("locales", "classNames", "condition")); + RuntimeReflectionSupport.increaseCount(false); String basename = asString(resource.get("name")); TypeResult resolvedConfigurationCondition = conditionResolver.resolveCondition(parseCondition(resource)); if (!resolvedConfigurationCondition.isPresent()) { @@ -122,6 +124,7 @@ protected interface GlobPatternConsumer { private void parseGlobEntry(Object data, GlobPatternConsumer resourceRegistry) { EconomicMap globObject = asMap(data, "Elements of 'globs' list must be a glob descriptor objects"); checkAttributes(globObject, "glob resource descriptor object", Collections.singletonList(GLOB_KEY), List.of(CONDITIONAL_KEY, MODULE_KEY)); + RuntimeReflectionSupport.increaseCount(false); TypeResult resolvedConfigurationCondition = conditionResolver.resolveCondition(parseCondition(globObject)); if (!resolvedConfigurationCondition.isPresent()) { return; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/SerializationMetadataParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/SerializationMetadataParser.java index 9b74ed811243..1f6a9f82221f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/SerializationMetadataParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/SerializationMetadataParser.java @@ -29,6 +29,7 @@ import java.util.Optional; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; @@ -49,6 +50,7 @@ public void parseAndRegister(Object json, URI origin) { @Override protected void parseSerializationDescriptorObject(EconomicMap data, boolean lambdaCapturingType) { checkAttributes(data, "serialization descriptor object", List.of(TYPE_KEY), List.of(CONDITIONAL_KEY, CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY)); + RuntimeReflectionSupport.increaseCount(false); Optional targetSerializationClass = parseTypeContents(data.get(TYPE_KEY)); if (targetSerializationClass.isEmpty()) { @@ -62,6 +64,9 @@ protected void parseSerializationDescriptorObject(EconomicMap da } Object optionalCustomCtorValue = data.get(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY); + if (optionalCustomCtorValue != null) { + RuntimeReflectionSupport.increaseCount(false); + } registerType(targetSerializationClass.get(), condition.get(), optionalCustomCtorValue); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java index 864f7de01645..210e28e217f2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java @@ -46,7 +46,6 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.BeforeImageWriteAccessImpl; import com.oracle.svm.hosted.ProgressReporter.LinkStrategy; -import com.oracle.svm.hosted.ProgressReporterJsonHelper.ImageDetailKey; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.meta.HostedClass; import com.oracle.svm.hosted.meta.HostedMetaAccess; @@ -162,7 +161,7 @@ protected void calculate(BeforeImageWriteAccessImpl access) { } } } - reporter.recordJsonMetric(ImageDetailKey.RESOURCE_SIZE_BYTES, resourcesByteArraySize); +// reporter.recordJsonMetric(ImageDetailKey.RESOURCE_SIZE_BYTES, resourcesByteArraySize); if (resourcesByteArraySize > 0) { addEntry(entries, byteArrayEntry, new HeapBreakdownEntry(BYTE_ARRAY_PREFIX, "embedded resources", "#glossary-embedded-resources"), resourcesByteArraySize, resourcesByteArrayCount); } @@ -170,7 +169,7 @@ protected void calculate(BeforeImageWriteAccessImpl access) { /* Extract byte[] for graph encodings. */ if (graphEncodingByteLength >= 0) { long graphEncodingSize = objectLayout.getArraySize(JavaKind.Byte, graphEncodingByteLength, true); - reporter.recordJsonMetric(ImageDetailKey.GRAPH_ENCODING_SIZE, graphEncodingSize); +// reporter.recordJsonMetric(ImageDetailKey.GRAPH_ENCODING_SIZE, graphEncodingSize); addEntry(entries, byteArrayEntry, new HeapBreakdownEntry(BYTE_ARRAY_PREFIX, "graph encodings", "#glossary-graph-encodings"), graphEncodingSize, 1); } /* Add remaining byte[]. */ diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index 96a6e449d3df..1aa4e5dbe994 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -42,7 +42,6 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.TreeMap; -import java.util.TreeSet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -54,9 +53,6 @@ import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.ImageSingletonsSupport; -import com.oracle.graal.pointsto.meta.AnalysisField; -import com.oracle.graal.pointsto.meta.AnalysisMethod; -import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.reports.ReportUtils; import com.oracle.graal.pointsto.util.Timer; @@ -69,7 +65,6 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.VM; import com.oracle.svm.core.heap.Heap; -import com.oracle.svm.core.hub.ClassForNameSupport; import com.oracle.svm.core.jdk.Resources; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; @@ -88,7 +83,6 @@ import com.oracle.svm.hosted.ProgressReporterJsonHelper.GeneralInfo; import com.oracle.svm.hosted.ProgressReporterJsonHelper.ImageDetailKey; import com.oracle.svm.hosted.ProgressReporterJsonHelper.JsonMetric; -import com.oracle.svm.hosted.ProgressReporterJsonHelper.ResourceUsageKey; import com.oracle.svm.hosted.c.codegen.CCompilerInvoker; import com.oracle.svm.hosted.image.AbstractImage.NativeImageKind; import com.oracle.svm.hosted.reflect.ReflectionHostedSupport; @@ -103,7 +97,8 @@ import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionStability; import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.util.json.JsonWriter; +import jdk.graal.compiler.util.json.JsonPrettyWriter; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; public class ProgressReporter implements FeatureSingleton, UnsavedSingleton { private static final boolean IS_CI = SubstrateUtil.isRunningInCI(); @@ -230,14 +225,14 @@ public void printUnsuccessfulInitializeEnd() { public void printInitializeEnd(List features, ImageClassLoader classLoader) { stagePrinter.end(getTimer(TimerCollection.Registry.CLASSLIST).getTotalTime() + getTimer(TimerCollection.Registry.SETUP).getTotalTime()); VM vm = ImageSingletons.lookup(VM.class); - recordJsonMetric(GeneralInfo.JAVA_VERSION, vm.version); - recordJsonMetric(GeneralInfo.VENDOR_VERSION, vm.vendorVersion); - recordJsonMetric(GeneralInfo.GRAALVM_VERSION, vm.vendorVersion); // deprecated +// recordJsonMetric(GeneralInfo.JAVA_VERSION, vm.version); +// recordJsonMetric(GeneralInfo.VENDOR_VERSION, vm.vendorVersion); +// recordJsonMetric(GeneralInfo.GRAALVM_VERSION, vm.vendorVersion); // deprecated l().a(" ").doclink("Java version", "#glossary-java-info").a(": ").a(vm.version).a(", ").doclink("vendor version", "#glossary-java-info").a(": ").a(vm.vendorVersion).println(); String optimizationLevel = SubstrateOptions.Optimize.getValue(); - recordJsonMetric(GeneralInfo.GRAAL_COMPILER_OPTIMIZATION_LEVEL, optimizationLevel); +// recordJsonMetric(GeneralInfo.GRAAL_COMPILER_OPTIMIZATION_LEVEL, optimizationLevel); String march = CPUType.getSelectedOrDefaultMArch(); - recordJsonMetric(GeneralInfo.GRAAL_COMPILER_MARCH, march); +// recordJsonMetric(GeneralInfo.GRAAL_COMPILER_MARCH, march); DirectPrinter graalLine = l().a(" ").doclink("Graal compiler", "#glossary-graal-compiler").a(": optimization level: %s, target machine: %s", optimizationLevel, march); ImageSingletons.lookup(ProgressReporterFeature.class).appendGraalSuffix(graalLine); graalLine.println(); @@ -246,9 +241,9 @@ public void printInitializeEnd(List features, ImageClassLoader classLoa cCompilerShort = ImageSingletons.lookup(CCompilerInvoker.class).compilerInfo.getShortDescription(); l().a(" ").doclink("C compiler", "#glossary-ccompiler").a(": ").a(cCompilerShort).println(); } - recordJsonMetric(GeneralInfo.CC, cCompilerShort); +// recordJsonMetric(GeneralInfo.CC, cCompilerShort); String gcName = Heap.getHeap().getGC().getName(); - recordJsonMetric(GeneralInfo.GC, gcName); +// recordJsonMetric(GeneralInfo.GC, gcName); long maxHeapSize = SubstrateGCOptions.MaxHeapSize.getValue(); String maxHeapValue = maxHeapSize == 0 ? Heap.getHeap().getGC().getDefaultMaxHeapSize() : ByteFormattingUtil.bytesToHuman(maxHeapSize); l().a(" ").doclink("Garbage collector", "#glossary-gc").a(": ").a(gcName).a(" (").doclink("max heap size", "#glossary-gc-max-heap-size").a(": ").a(maxHeapValue).a(")").println(); @@ -418,9 +413,9 @@ private void printEnvironmentVariableOptions() { private void printResourceInfo() { Runtime runtime = Runtime.getRuntime(); long maxMemory = runtime.maxMemory(); - recordJsonMetric(ResourceUsageKey.GC_MAX_HEAP, maxMemory); +// recordJsonMetric(ResourceUsageKey.GC_MAX_HEAP, maxMemory); long totalMemorySize = getOperatingSystemMXBean().getTotalMemorySize(); - recordJsonMetric(ResourceUsageKey.MEMORY_TOTAL, totalMemorySize); +// recordJsonMetric(ResourceUsageKey.MEMORY_TOTAL, totalMemorySize); List inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments(); List maxRAMPrecentageValues = inputArguments.stream().filter(arg -> arg.startsWith("-XX:MaxRAMPercentage")).toList(); @@ -434,9 +429,9 @@ private void printResourceInfo() { } int maxNumberOfThreads = NativeImageOptions.getActualNumberOfThreads(); - recordJsonMetric(ResourceUsageKey.PARALLELISM, maxNumberOfThreads); +// recordJsonMetric(ResourceUsageKey.PARALLELISM, maxNumberOfThreads); int availableProcessors = runtime.availableProcessors(); - recordJsonMetric(ResourceUsageKey.CPU_CORES_TOTAL, availableProcessors); +// recordJsonMetric(ResourceUsageKey.CPU_CORES_TOTAL, availableProcessors); String maxNumberOfThreadsSuffix = "determined at start"; if (NativeImageOptions.NumberOfThreads.hasBeenSet()) { maxNumberOfThreadsSuffix = "set via '%s'".formatted(SubstrateOptionsParser.commandArgument(NativeImageOptions.NumberOfThreads, Integer.toString(maxNumberOfThreads))); @@ -475,81 +470,96 @@ public void closeAction() { } private void printAnalysisStatistics(AnalysisUniverse universe, Collection libraries) { - String actualFormat = "%,9d "; - String totalFormat = " (%4.1f%% of %,8d total)"; - long reachableTypes; - if (universe.hostVM().useBaseLayer()) { - reachableTypes = universe.getTypes().stream().filter(AnalysisType::isReachable).filter(t -> !t.isInBaseLayer()).count(); - } else { - reachableTypes = universe.getTypes().stream().filter(AnalysisType::isReachable).count(); - } - long totalTypes = universe.getTypes().size(); - recordJsonMetric(AnalysisResults.TYPES_TOTAL, totalTypes); - recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_TOTAL, totalTypes); - recordJsonMetric(AnalysisResults.TYPES_REACHABLE, reachableTypes); - recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_REACHABLE, reachableTypes); - l().a(actualFormat, reachableTypes).doclink("reachable types", "#glossary-reachability").a(" ") - .a(totalFormat, Utils.toPercentage(reachableTypes, totalTypes), totalTypes).println(); - Collection fields = universe.getFields(); - long reachableFields; - if (universe.hostVM().useBaseLayer()) { - reachableFields = fields.stream().filter(AnalysisField::isAccessed).filter(f -> !f.isInBaseLayer()).count(); - } else { - reachableFields = fields.stream().filter(AnalysisField::isAccessed).count(); - } - int totalFields = fields.size(); - recordJsonMetric(AnalysisResults.FIELD_TOTAL, totalFields); - recordJsonMetric(AnalysisResults.FIELD_REACHABLE, reachableFields); - l().a(actualFormat, reachableFields).doclink("reachable fields", "#glossary-reachability").a(" ") - .a(totalFormat, Utils.toPercentage(reachableFields, totalFields), totalFields).println(); - Collection methods = universe.getMethods(); - long reachableMethods; - if (universe.hostVM().useBaseLayer()) { - reachableMethods = methods.stream().filter(AnalysisMethod::isReachable).filter(m -> !m.isInBaseLayer()).count(); - } else { - reachableMethods = methods.stream().filter(AnalysisMethod::isReachable).count(); - } - int totalMethods = methods.size(); - recordJsonMetric(AnalysisResults.METHOD_TOTAL, totalMethods); - recordJsonMetric(AnalysisResults.METHOD_REACHABLE, reachableMethods); - l().a(actualFormat, reachableMethods).doclink("reachable methods", "#glossary-reachability") - .a(totalFormat, Utils.toPercentage(reachableMethods, totalMethods), totalMethods).println(); - if (numRuntimeCompiledMethods >= 0) { - recordJsonMetric(ImageDetailKey.RUNTIME_COMPILED_METHODS_COUNT, numRuntimeCompiledMethods); - l().a(actualFormat, numRuntimeCompiledMethods).doclink("runtime compiled methods", "#glossary-runtime-methods") - .a(totalFormat, Utils.toPercentage(numRuntimeCompiledMethods, totalMethods), totalMethods).println(); - } - String typesFieldsMethodFormat = "%,9d types, %,5d fields, and %,5d methods "; - int reflectClassesCount = ClassForNameSupport.singleton().count(); - ReflectionHostedSupport rs = ImageSingletons.lookup(ReflectionHostedSupport.class); - int reflectFieldsCount = rs.getReflectionFieldsCount(); - int reflectMethodsCount = rs.getReflectionMethodsCount(); - recordJsonMetric(AnalysisResults.METHOD_REFLECT, reflectMethodsCount); - recordJsonMetric(AnalysisResults.TYPES_REFLECT, reflectClassesCount); - recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_REFLECT, reflectClassesCount); - recordJsonMetric(AnalysisResults.FIELD_REFLECT, reflectFieldsCount); - l().a(typesFieldsMethodFormat, reflectClassesCount, reflectFieldsCount, reflectMethodsCount) - .doclink("registered for reflection", "#glossary-reflection-registrations").println(); - recordJsonMetric(AnalysisResults.METHOD_JNI, (numJNIMethods >= 0 ? numJNIMethods : UNAVAILABLE_METRIC)); - recordJsonMetric(AnalysisResults.TYPES_JNI, (numJNIClasses >= 0 ? numJNIClasses : UNAVAILABLE_METRIC)); - recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_JNI, (numJNIClasses >= 0 ? numJNIClasses : UNAVAILABLE_METRIC)); - recordJsonMetric(AnalysisResults.FIELD_JNI, (numJNIFields >= 0 ? numJNIFields : UNAVAILABLE_METRIC)); - if (numJNIClasses >= 0) { - l().a(typesFieldsMethodFormat, numJNIClasses, numJNIFields, numJNIMethods) - .doclink("registered for JNI access", "#glossary-jni-access-registrations").println(); - } - String stubsFormat = "%,9d downcalls and %,d upcalls "; - recordJsonMetric(AnalysisResults.FOREIGN_DOWNCALLS, (numForeignDowncalls >= 0 ? numForeignDowncalls : UNAVAILABLE_METRIC)); - recordJsonMetric(AnalysisResults.FOREIGN_UPCALLS, (numForeignUpcalls >= 0 ? numForeignUpcalls : UNAVAILABLE_METRIC)); - if (numForeignDowncalls >= 0 || numForeignUpcalls >= 0) { - l().a(stubsFormat, numForeignDowncalls, numForeignUpcalls) - .doclink("registered for foreign access", "#glossary-foreign-downcall-and-upcall-registrations").println(); - } - int numLibraries = libraries.size(); - if (numLibraries > 0) { - TreeSet sortedLibraries = new TreeSet<>(libraries); - l().a("%,9d native %s: ", numLibraries, numLibraries == 1 ? "library" : "libraries").a(String.join(", ", sortedLibraries)).println(); - } + recordJsonMetric(AnalysisResults.ALL_CONFIG_ENTRIES, RuntimeReflectionSupport.getCount(false)); + recordJsonMetric(AnalysisResults.RELEVANT_CONFIG_ENTRIES, RuntimeReflectionSupport.getCount(true)); +// String actualFormat = "%,9d "; +// String totalFormat = " (%4.1f%% of %,8d total)"; +// long reachableTypes; +// if (universe.hostVM().useBaseLayer()) { +// reachableTypes = universe.getTypes().stream().filter(AnalysisType::isReachable).filter(t -> +// !t.isInBaseLayer()).count(); +// } else { +// reachableTypes = universe.getTypes().stream().filter(AnalysisType::isReachable).count(); +// } +// long totalTypes = universe.getTypes().size(); +// recordJsonMetric(AnalysisResults.TYPES_TOTAL, totalTypes); +// recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_TOTAL, totalTypes); +// recordJsonMetric(AnalysisResults.TYPES_REACHABLE, reachableTypes); +// recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_REACHABLE, reachableTypes); +// l().a(actualFormat, reachableTypes).doclink("reachable types", "#glossary-reachability").a(" ") +// .a(totalFormat, Utils.toPercentage(reachableTypes, totalTypes), totalTypes).println(); +// Collection fields = universe.getFields(); +// long reachableFields; +// if (universe.hostVM().useBaseLayer()) { +// reachableFields = fields.stream().filter(AnalysisField::isAccessed).filter(f -> +// !f.isInBaseLayer()).count(); +// } else { +// reachableFields = fields.stream().filter(AnalysisField::isAccessed).count(); +// } +// int totalFields = fields.size(); +// recordJsonMetric(AnalysisResults.FIELD_TOTAL, totalFields); +// recordJsonMetric(AnalysisResults.FIELD_REACHABLE, reachableFields); +// l().a(actualFormat, reachableFields).doclink("reachable fields", "#glossary-reachability").a(" ") +// .a(totalFormat, Utils.toPercentage(reachableFields, totalFields), totalFields).println(); +// Collection methods = universe.getMethods(); +// long reachableMethods; +// if (universe.hostVM().useBaseLayer()) { +// reachableMethods = methods.stream().filter(AnalysisMethod::isReachable).filter(m -> +// !m.isInBaseLayer()).count(); +// } else { +// reachableMethods = methods.stream().filter(AnalysisMethod::isReachable).count(); +// } +// int totalMethods = methods.size(); +// recordJsonMetric(AnalysisResults.METHOD_TOTAL, totalMethods); +// recordJsonMetric(AnalysisResults.METHOD_REACHABLE, reachableMethods); +// l().a(actualFormat, reachableMethods).doclink("reachable methods", "#glossary-reachability") +// .a(totalFormat, Utils.toPercentage(reachableMethods, totalMethods), totalMethods).println(); +// if (numRuntimeCompiledMethods >= 0) { +// recordJsonMetric(ImageDetailKey.RUNTIME_COMPILED_METHODS_COUNT, numRuntimeCompiledMethods); +// l().a(actualFormat, numRuntimeCompiledMethods).doclink("runtime compiled methods", +// "#glossary-runtime-methods") +// .a(totalFormat, Utils.toPercentage(numRuntimeCompiledMethods, totalMethods), +// totalMethods).println(); +// } +// String typesFieldsMethodFormat = "%,9d types, %,5d fields, and %,5d methods "; +// int reflectClassesCount = ClassForNameSupport.singleton().count(); +// ReflectionHostedSupport rs = ImageSingletons.lookup(ReflectionHostedSupport.class); +// int reflectFieldsCount = rs.getReflectionFieldsCount(); +// int reflectMethodsCount = rs.getReflectionMethodsCount(); +// recordJsonMetric(AnalysisResults.METHOD_REFLECT, reflectMethodsCount); +// recordJsonMetric(AnalysisResults.TYPES_REFLECT, reflectClassesCount); +// recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_REFLECT, reflectClassesCount); +// recordJsonMetric(AnalysisResults.FIELD_REFLECT, reflectFieldsCount); +// l().a(typesFieldsMethodFormat, reflectClassesCount, reflectFieldsCount, reflectMethodsCount) +// .doclink("registered for reflection", "#glossary-reflection-registrations").println(); +// recordJsonMetric(AnalysisResults.METHOD_JNI, (numJNIMethods >= 0 ? numJNIMethods : +// UNAVAILABLE_METRIC)); +// recordJsonMetric(AnalysisResults.TYPES_JNI, (numJNIClasses >= 0 ? numJNIClasses : +// UNAVAILABLE_METRIC)); +// recordJsonMetric(AnalysisResults.DEPRECATED_CLASS_JNI, (numJNIClasses >= 0 ? numJNIClasses : +// UNAVAILABLE_METRIC)); +// recordJsonMetric(AnalysisResults.FIELD_JNI, (numJNIFields >= 0 ? numJNIFields : +// UNAVAILABLE_METRIC)); +// if (numJNIClasses >= 0) { +// l().a(typesFieldsMethodFormat, numJNIClasses, numJNIFields, numJNIMethods) +// .doclink("registered for JNI access", "#glossary-jni-access-registrations").println(); +// } +// String stubsFormat = "%,9d downcalls and %,d upcalls "; +// recordJsonMetric(AnalysisResults.FOREIGN_DOWNCALLS, (numForeignDowncalls >= 0 ? +// numForeignDowncalls : UNAVAILABLE_METRIC)); +// recordJsonMetric(AnalysisResults.FOREIGN_UPCALLS, (numForeignUpcalls >= 0 ? numForeignUpcalls : +// UNAVAILABLE_METRIC)); +// if (numForeignDowncalls >= 0 || numForeignUpcalls >= 0) { +// l().a(stubsFormat, numForeignDowncalls, numForeignUpcalls) +// .doclink("registered for foreign access", +// "#glossary-foreign-downcall-and-upcall-registrations").println(); +// } +// int numLibraries = libraries.size(); +// if (numLibraries > 0) { +// TreeSet sortedLibraries = new TreeSet<>(libraries); +// l().a("%,9d native %s: ", numLibraries, numLibraries == 1 ? "library" : +// "libraries").a(String.join(", ", sortedLibraries)).println(); +// } } public ReporterClosable printUniverse() { @@ -582,7 +592,7 @@ public void setDebugInfoTimer(Timer timer) { } public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageHeapSize, int codeAreaSize, int numCompilations, int debugInfoSize) { - recordJsonMetric(ImageDetailKey.IMAGE_HEAP_OBJECT_COUNT, heapObjectCount); +// recordJsonMetric(ImageDetailKey.IMAGE_HEAP_OBJECT_COUNT, heapObjectCount); Timer imageTimer = getTimer(TimerCollection.Registry.IMAGE); Timer writeTimer = getTimer(TimerCollection.Registry.WRITE); stagePrinter.end(imageTimer.getTotalTime() + writeTimer.getTotalTime()); @@ -591,11 +601,11 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH l().a(format, ByteFormattingUtil.bytesToHuman(codeAreaSize), Utils.toPercentage(codeAreaSize, imageFileSize)) .doclink("code area", "#glossary-code-area").a(":%,10d compilation units", numCompilations).println(); int numResources = Resources.singleton().count(); - recordJsonMetric(ImageDetailKey.IMAGE_HEAP_RESOURCE_COUNT, numResources); +// recordJsonMetric(ImageDetailKey.IMAGE_HEAP_RESOURCE_COUNT, numResources); l().a(format, ByteFormattingUtil.bytesToHuman(imageHeapSize), Utils.toPercentage(imageHeapSize, imageFileSize)) .doclink("image heap", "#glossary-image-heap").a(":%,9d objects and %,d resources", heapObjectCount, numResources).println(); if (debugInfoSize > 0) { - recordJsonMetric(ImageDetailKey.DEBUG_INFO_SIZE, debugInfoSize); // Optional metric +// recordJsonMetric(ImageDetailKey.DEBUG_INFO_SIZE, debugInfoSize); // Optional metric DirectPrinter l = l().a(format, ByteFormattingUtil.bytesToHuman(debugInfoSize), Utils.toPercentage(debugInfoSize, imageFileSize)) .doclink("debug info", "#glossary-debug-info"); @@ -605,10 +615,10 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH l.println(); } long otherBytes = imageFileSize - codeAreaSize - imageHeapSize - debugInfoSize; - recordJsonMetric(ImageDetailKey.IMAGE_HEAP_SIZE, imageHeapSize); +// recordJsonMetric(ImageDetailKey.IMAGE_HEAP_SIZE, imageHeapSize); recordJsonMetric(ImageDetailKey.TOTAL_SIZE, imageFileSize); - recordJsonMetric(ImageDetailKey.CODE_AREA_SIZE, codeAreaSize); - recordJsonMetric(ImageDetailKey.NUM_COMP_UNITS, numCompilations); +// recordJsonMetric(ImageDetailKey.CODE_AREA_SIZE, codeAreaSize); +// recordJsonMetric(ImageDetailKey.NUM_COMP_UNITS, numCompilations); l().a(format, ByteFormattingUtil.bytesToHuman(otherBytes), Utils.toPercentage(otherBytes, imageFileSize)) .doclink("other data", "#glossary-other-data").println(); l().a("%9s in total", ByteFormattingUtil.bytesToHuman(imageFileSize)).println(); @@ -729,7 +739,7 @@ public void printEpilog(Optional optionalImageName, Optional { try { - jsonHelper.print(new JsonWriter(out)); + jsonHelper.print(new JsonPrettyWriter(out)); } catch (IOException e) { throw VMError.shouldNotReachHere("Failed to create " + jsonOutputFile, e); } @@ -828,8 +839,8 @@ private void printResourceStatistics() { double totalProcessTimeSeconds = Utils.millisToSeconds(System.currentTimeMillis() - ManagementFactory.getRuntimeMXBean().getStartTime()); GCStats gcStats = GCStats.getCurrent(); double gcSeconds = Utils.millisToSeconds(gcStats.totalTimeMillis); - recordJsonMetric(ResourceUsageKey.GC_COUNT, gcStats.totalCount); - recordJsonMetric(ResourceUsageKey.GC_SECS, gcSeconds); +// recordJsonMetric(ResourceUsageKey.GC_COUNT, gcStats.totalCount); +// recordJsonMetric(ResourceUsageKey.GC_SECS, gcSeconds); CenteredTextPrinter p = centered(); p.a("%.1fs (%.1f%% of total time) in %d ", gcSeconds, gcSeconds / totalProcessTimeSeconds * 100, gcStats.totalCount) .doclink("GCs", "#glossary-garbage-collections"); @@ -837,14 +848,14 @@ private void printResourceStatistics() { if (peakRSS >= 0) { p.a(" | ").doclink("Peak RSS", "#glossary-peak-rss").a(": ").a("%.2fGB", ByteFormattingUtil.bytesToGiB(peakRSS)); } - recordJsonMetric(ResourceUsageKey.PEAK_RSS, (peakRSS >= 0 ? peakRSS : UNAVAILABLE_METRIC)); +// recordJsonMetric(ResourceUsageKey.PEAK_RSS, (peakRSS >= 0 ? peakRSS : UNAVAILABLE_METRIC)); long processCPUTime = getOperatingSystemMXBean().getProcessCpuTime(); double cpuLoad = UNAVAILABLE_METRIC; if (processCPUTime > 0) { cpuLoad = Utils.nanosToSeconds(processCPUTime) / totalProcessTimeSeconds; p.a(" | ").doclink("CPU load", "#glossary-cpu-load").a(": ").a("%.2f", cpuLoad); } - recordJsonMetric(ResourceUsageKey.CPU_LOAD, cpuLoad); +// recordJsonMetric(ResourceUsageKey.CPU_LOAD, cpuLoad); p.flushln(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporterJsonHelper.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporterJsonHelper.java index ba3b991571cd..900e0893f676 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporterJsonHelper.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporterJsonHelper.java @@ -180,6 +180,8 @@ public enum AnalysisResults implements JsonMetric { FIELD_REFLECT("fields", "reflection"), FOREIGN_DOWNCALLS("methods", "foreign_downcalls"), FOREIGN_UPCALLS("methods", "foreign_upcalls"), + ALL_CONFIG_ENTRIES("config", "all_entries"), + RELEVANT_CONFIG_ENTRIES("config", "relevant_entries"), // TODO GR-42148: remove deprecated entries in a future release DEPRECATED_CLASS_TOTAL("classes", "total"), diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java index 4ed3331b39fd..9a11cb6f1815 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java @@ -64,6 +64,7 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.stream.Collectors; diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ImageBuildStatistics.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ImageBuildStatistics.java index 88e3f9b35980..a92bc1edfa22 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ImageBuildStatistics.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ImageBuildStatistics.java @@ -31,11 +31,12 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import org.graalvm.nativeimage.ImageSingletons; + import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.nodes.extended.BytecodeExceptionNode; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; -import org.graalvm.nativeimage.ImageSingletons; public class ImageBuildStatistics { From 765a0c4344ecf80d4184b65d3d5b5f78b6982981 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Tue, 1 Oct 2024 01:24:12 +0200 Subject: [PATCH 2/2] Consider all types as registered for JNI --- .../LegacyReflectionConfigurationParser.java | 2 +- .../configure/ReflectionConfigurationParser.java | 16 +++++++++++----- .../core/configure/ReflectionMetadataParser.java | 9 ++++----- .../oracle/svm/hosted/jni/JNIAccessFeature.java | 6 +++++- .../svm/hosted/reflect/ReflectionFeature.java | 7 +++++++ 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyReflectionConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyReflectionConfigurationParser.java index a123418dc670..f4c94039374a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyReflectionConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyReflectionConfigurationParser.java @@ -47,7 +47,7 @@ final class LegacyReflectionConfigurationParser extends ReflectionConfigur LegacyReflectionConfigurationParser(ConfigurationConditionResolver conditionResolver, ReflectionConfigurationParserDelegate delegate, boolean strictConfiguration, boolean printMissingElements, boolean treatAllNameEntriesAsType) { - super(conditionResolver, delegate, strictConfiguration, printMissingElements); + super(conditionResolver, delegate, strictConfiguration, printMissingElements, ""); this.treatAllNameEntriesAsType = treatAllNameEntriesAsType; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java index b4d970081440..541872f3664d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java @@ -47,14 +47,16 @@ public abstract class ReflectionConfigurationParser extends ConfigurationP protected final ConfigurationConditionResolver conditionResolver; protected final ReflectionConfigurationParserDelegate delegate; + protected final String combinedFileKey; private final boolean printMissingElements; public ReflectionConfigurationParser(ConfigurationConditionResolver conditionResolver, ReflectionConfigurationParserDelegate delegate, boolean strictConfiguration, - boolean printMissingElements) { + boolean printMissingElements, String combinedFileKey) { super(strictConfiguration); this.conditionResolver = conditionResolver; this.printMissingElements = printMissingElements; this.delegate = delegate; + this.combinedFileKey = combinedFileKey; } public static ReflectionConfigurationParser create(String combinedFileKey, boolean strictMetadata, @@ -76,8 +78,8 @@ protected void parseClassArray(List classes) { protected abstract void parseClass(EconomicMap data); protected void registerIfNotDefault(EconomicMap data, boolean defaultValue, T clazz, String propertyName, Runnable register) { - if (data.containsKey(propertyName)) { - RuntimeReflectionSupport.increaseCount(false); + if (data.containsKey(propertyName) && delegate.getClass().getName().contains("ReflectionRegistryAdapter")) { + RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY)); } if (data.containsKey(propertyName) ? asBoolean(data.get(propertyName), propertyName) : defaultValue) { try { @@ -96,7 +98,9 @@ protected void parseFields(C condition, List fields, T clazz) { private void parseField(C condition, EconomicMap data, T clazz) { checkAttributes(data, "reflection field descriptor object", Collections.singleton("name"), Arrays.asList("allowWrite", "allowUnsafeAccess")); - RuntimeReflectionSupport.increaseCount(false); + if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) { + RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY)); + } String fieldName = asString(data.get("name"), "name"); boolean allowWrite = data.containsKey("allowWrite") && asBoolean(data.get("allowWrite"), "allowWrite"); @@ -117,7 +121,9 @@ protected void parseMethods(C condition, boolean queriedOnly, List metho private void parseMethod(C condition, boolean queriedOnly, EconomicMap data, T clazz) { checkAttributes(data, "reflection method descriptor object", Collections.singleton("name"), Collections.singleton("parameterTypes")); - RuntimeReflectionSupport.increaseCount(false); + if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) { + RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY)); + } String methodName = asString(data.get("name"), "name"); List methodParameterTypes = null; Object parameterTypes = data.get("parameterTypes"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java index 982588099e97..ca86881c2d94 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java @@ -41,12 +41,9 @@ class ReflectionMetadataParser extends ReflectionConfigurationParser "allDeclaredConstructors", "allPublicConstructors", "allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields", "methods", "fields", "unsafeAllocated"); - private final String combinedFileKey; - ReflectionMetadataParser(String combinedFileKey, ConfigurationConditionResolver conditionResolver, ReflectionConfigurationParserDelegate delegate, boolean strictConfiguration, boolean printMissingElements) { - super(conditionResolver, delegate, strictConfiguration, printMissingElements); - this.combinedFileKey = combinedFileKey; + super(conditionResolver, delegate, strictConfiguration, printMissingElements, combinedFileKey); } @Override @@ -60,7 +57,9 @@ public void parseAndRegister(Object json, URI origin) { @Override protected void parseClass(EconomicMap data) { checkAttributes(data, "reflection class descriptor object", List.of(TYPE_KEY), OPTIONAL_REFLECT_METADATA_ATTRS); - RuntimeReflectionSupport.increaseCount(false); + if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) { + RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY)); + } Optional type = parseTypeContents(data.get(TYPE_KEY)); if (type.isEmpty()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java index 1faf781e3323..61518eaf1358 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java @@ -25,6 +25,7 @@ package com.oracle.svm.hosted.jni; import static com.oracle.svm.core.configure.ConfigurationParser.JNI_KEY; +import static com.oracle.svm.core.configure.ConfigurationParser.REFLECTION_KEY; import java.lang.reflect.Executable; import java.lang.reflect.Field; @@ -209,11 +210,14 @@ public void afterRegistration(AfterRegistrationAccess arg) { ClassInitializationSupport.singleton()); ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader()); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "JNI"); + ReflectionConfigurationParser> reflectParser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader()); + loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(reflectParser, access.getImageClassLoader(), "Reflection"); ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null, access.getImageClassLoader()); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "JNI", ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources, ConfigurationFile.JNI.getFileName()); - } + loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "Reflection", + ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources, ConfigurationFile.REFLECTION.getFileName()); } private class JNIRuntimeAccessibilitySupportImpl extends ConditionalConfigurationRegistry implements RuntimeJNIAccessSupport { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java index 5d80ffe544e6..85fbbb36c1ce 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.hosted.reflect; +import static com.oracle.svm.core.configure.ConfigurationParser.JNI_KEY; import static com.oracle.svm.core.configure.ConfigurationParser.REFLECTION_KEY; import java.lang.invoke.MethodHandle; @@ -283,11 +284,17 @@ public void duringSetup(DuringSetupAccess a) { ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, reflectionData, proxyRegistry, access.getImageClassLoader()); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "reflection"); + ReflectionConfigurationParser> jniParser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, reflectionData, proxyRegistry, + access.getImageClassLoader()); + loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(jniParser, access.getImageClassLoader(), "JNI"); ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry, access.getImageClassLoader()); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "reflection", ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources, ConfigurationFile.REFLECTION.getFileName()); + loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "JNI", + ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources, + ConfigurationFile.JNI.getFileName()); loader = access.getImageClassLoader(); annotationSubstitutions = ((Inflation) access.getBigBang()).getAnnotationSubstitutionProcessor();