From 519f14b5ae2160f1a9a6e40d31e30dfc01a2f1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 12 Sep 2022 11:40:33 +0200 Subject: [PATCH 1/6] Add RuntimeResourceAccess#addResource(Module, String, byte[]) API method --- .../hosted/RuntimeResourceAccess.java | 18 ++++++ .../impl/RuntimeResourceSupport.java | 2 + .../config/ResourceConfigurationTest.java | 4 ++ .../config/ResourceConfiguration.java | 10 ++- .../com/oracle/svm/core/jdk/Resources.java | 7 ++- .../oracle/svm/hosted/ResourcesFeature.java | 62 ++++++++++++++++++- 6 files changed, 98 insertions(+), 5 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java index 6f62b7a194b2..f5fb199bebb0 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java @@ -67,10 +67,28 @@ public final class RuntimeResourceAccess { * @since 22.3 */ public static void addResource(Module module, String resourcePath) { + Objects.requireNonNull(module); + Objects.requireNonNull(resourcePath); ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), withModuleName(module, Pattern.quote(resourcePath))); } + /** + * Inject a Java resource at {@code resourcePath} in {@code module} with the specified + * {@code resourceContent}. At runtime the resource can be accessed as if it was part of the + * original application. If the given {@code module} is unnamed, the resource is placed on the + * classpath instead. + * + * @since 22.3 + */ + public static void addResource(Module module, String resourcePath, byte[] resourceContent) { + Objects.requireNonNull(module); + Objects.requireNonNull(resourcePath); + Objects.requireNonNull(resourceContent); + ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(ConfigurationCondition.alwaysTrue(), + module, resourcePath, resourceContent); + } + /** * Make Java ResourceBundle that is specified by a {@code baseBundleName} and {@code locales} * from module {@code module} available at run time. If the given {@code module} is unnamed, the diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java index b98cb47b6d1c..ca8599e072fc 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java @@ -46,6 +46,8 @@ public interface RuntimeResourceSupport { void addResources(ConfigurationCondition condition, String pattern); + void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent); + void ignoreResources(ConfigurationCondition condition, String pattern); void addResourceBundles(ConfigurationCondition condition, String name); diff --git a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java index 1d5fe077170b..ad774a260356 100644 --- a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java +++ b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java @@ -93,6 +93,10 @@ public void addResources(ConfigurationCondition condition, String pattern) { addedResources.add(pattern); } + @Override + public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { + } + @Override public void ignoreResources(ConfigurationCondition condition, String pattern) { ignoredResources.add(pattern); diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java index b0845a4db275..ca274f1c26db 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java @@ -35,15 +35,16 @@ import java.util.concurrent.ConcurrentMap; import java.util.regex.Pattern; -import com.oracle.svm.core.configure.ConfigurationParser; -import com.oracle.svm.core.configure.ResourceConfigurationParser; import org.graalvm.nativeimage.impl.ConfigurationCondition; import com.oracle.svm.configure.ConfigurationBase; import com.oracle.svm.configure.json.JsonPrinter; import com.oracle.svm.configure.json.JsonWriter; import com.oracle.svm.core.configure.ConditionalElement; +import com.oracle.svm.core.configure.ConfigurationParser; +import com.oracle.svm.core.configure.ResourceConfigurationParser; import com.oracle.svm.core.configure.ResourcesRegistry; +import com.oracle.svm.core.util.VMError; public final class ResourceConfiguration extends ConfigurationBase { @@ -62,6 +63,11 @@ public void addResources(ConfigurationCondition condition, String pattern) { configuration.addResourcePattern(condition, pattern); } + @Override + public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { + VMError.shouldNotReachHere("Resource injection is only supported via Feature implementation"); + } + @Override public void ignoreResources(ConfigurationCondition condition, String pattern) { configuration.ignoreResourcePattern(condition, pattern); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index 3596120035e5..ec808b3e1981 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -41,10 +41,10 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.jdk.resources.NativeImageResourcePath; import com.oracle.svm.core.jdk.resources.ResourceStorageEntry; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.core.util.VMError; @@ -111,6 +111,11 @@ public static void registerResource(String moduleName, String resourceName, Inpu registerResource(moduleName, resourceName, is, true); } + @Platforms(Platform.HOSTED_ONLY.class) + public static void registerResource(String moduleName, String resourceName, byte[] resourceContent) { + addEntry(moduleName, resourceName, false, resourceContent, true); + } + @Platforms(Platform.HOSTED_ONLY.class) public static void registerResource(String moduleName, String resourceName, InputStream is, boolean fromJar) { addEntry(moduleName, resourceName, false, inputStreamToByteArray(is), fromJar); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index f9fb8dda78e8..89d7b86176cd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -29,10 +29,14 @@ import java.io.InputStream; import java.nio.file.FileSystem; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @@ -52,6 +56,7 @@ import com.oracle.svm.core.configure.ConfigurationFiles; import com.oracle.svm.core.configure.ResourceConfigurationParser; import com.oracle.svm.core.configure.ResourcesRegistry; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.jdk.Resources; import com.oracle.svm.core.jdk.resources.NativeImageResourceFileAttributes; @@ -60,7 +65,6 @@ import com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystemProvider; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.LocatableMultiOptionValue; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.util.UserError; import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; import com.oracle.svm.hosted.config.ConfigurationParserUtils; @@ -108,6 +112,7 @@ public static class Options { } private boolean sealed = false; + private final Map injectResourceWorkSet = new ConcurrentHashMap<>(); private final Set resourcePatternWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Set excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>()); private int loadedConfigurations; @@ -115,6 +120,38 @@ public static class Options { public final Set includedResourcesModules = new HashSet<>(); + private static final class ResourceLocation { + private final Module module; + private final String path; + + private ResourceLocation(Module module, String path) { + this.module = module; + this.path = path; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResourceLocation that = (ResourceLocation) o; + return Objects.equals(module, that.module) && Objects.equals(path, that.path); + } + + @Override + public int hashCode() { + return Objects.hash(module, path); + } + + @Override + public String toString() { + return module.getName() + ":" + path; + } + } + private class ResourcesRegistryImpl extends ConditionalConfigurationRegistry implements ResourcesRegistry { private final ConfigurationTypeResolver configurationTypeResolver; @@ -133,6 +170,18 @@ public void addResources(ConfigurationCondition condition, String pattern) { }); } + @Override + public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { + if (configurationTypeResolver.resolveType(condition.getTypeName()) == null) { + return; + } + registerConditionalConfiguration(condition, () -> { + ResourceLocation resourceLocation = new ResourceLocation(module, resourcePath); + UserError.guarantee(!sealed, "Resources added too late: %s", resourceLocation); + injectResourceWorkSet.put(resourceLocation, resourceContent); + }); + } + @Override public void ignoreResources(ConfigurationCondition condition, String pattern) { if (configurationTypeResolver.resolveType(condition.getTypeName()) == null) { @@ -255,13 +304,22 @@ private void collectModuleName(String moduleName) { @Override public void duringAnalysis(DuringAnalysisAccess access) { resourceRegistryImpl().flushConditionalConfiguration(access); - if (resourcePatternWorkSet.isEmpty()) { + if (resourcePatternWorkSet.isEmpty() && injectResourceWorkSet.isEmpty()) { return; } access.requireAnalysisIteration(); DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext(); + List removed = new ArrayList<>(); + + for (Map.Entry entry : injectResourceWorkSet.entrySet()) { + var resourceLocation = entry.getKey(); + var moduleName = resourceLocation.module.isNamed() ? resourceLocation.module.getName() : null; + Resources.registerResource(moduleName, resourceLocation.path, entry.getValue()); + } + injectResourceWorkSet.clear(); + ResourcePattern[] includePatterns = compilePatterns(resourcePatternWorkSet); ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns); ResourceCollectorImpl collector = new ResourceCollectorImpl(debugContext, includePatterns, excludePatterns, includedResourcesModules); From f071019eedb0d5a2cbe971bf3c4e2817f9689791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 12 Sep 2022 11:42:37 +0200 Subject: [PATCH 2/6] Update CHANGELOG --- substratevm/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index ecf08e03e429..b5ac2b3cc134 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -13,6 +13,7 @@ This changelog summarizes major changes to GraalVM Native Image. * (GR-15630) Allow multiple classes with the same name from different class loaders. * (GR-40198) Introduce public API for programmatic JNI / Resource / Proxy / Serialization registration from Feature classes during the image build. * (GR-38909) Moved strictly-internal annotation classes (e.g. @AlwaysInline, @NeverInline, @Uninterruptible, ...) out of com.oracle.svm.core.annotate. Moved remaining annotation classes to org.graalvm.sdk module. +* (GR-40906) Add RuntimeResourceAccess#addResource(Module module, String resourcePath, byte[] resource) API method that allows injecting resources into images ## Version 22.2.0 * (GR-20653) Re-enable the usage of all CPU features for JIT compilation on AMD64. From 74279af53ac9b4a43882849e9e0e36d946482d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 12 Sep 2022 12:55:21 +0200 Subject: [PATCH 3/6] Add new API method to snapshot.sigtest --- sdk/src/org.graalvm.nativeimage/snapshot.sigtest | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index fd45783d107b..db5dc36fdd3d 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -1017,6 +1017,7 @@ supr java.lang.Object CLSS public final org.graalvm.nativeimage.hosted.RuntimeResourceAccess meth public static void addResource(java.lang.Module,java.lang.String) +meth public static void addResource(java.lang.Module,java.lang.String,byte[]) meth public static void addResourceBundle(java.lang.Module,java.lang.String,java.util.Locale[]) meth public static void addResourceBundle(java.lang.Module,java.lang.String) supr java.lang.Object From 54f579c1ffb63058cc3d2ca95c344df9ea061c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Mon, 12 Sep 2022 13:23:04 +0200 Subject: [PATCH 4/6] Stylefix --- .../src/com/oracle/svm/hosted/ResourcesFeature.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 89d7b86176cd..2b01eefb3ab2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -29,11 +29,9 @@ import java.io.InputStream; import java.nio.file.FileSystem; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -310,9 +308,6 @@ public void duringAnalysis(DuringAnalysisAccess access) { access.requireAnalysisIteration(); - DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext(); - List removed = new ArrayList<>(); - for (Map.Entry entry : injectResourceWorkSet.entrySet()) { var resourceLocation = entry.getKey(); var moduleName = resourceLocation.module.isNamed() ? resourceLocation.module.getName() : null; @@ -322,10 +317,9 @@ public void duringAnalysis(DuringAnalysisAccess access) { ResourcePattern[] includePatterns = compilePatterns(resourcePatternWorkSet); ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns); + DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext(); ResourceCollectorImpl collector = new ResourceCollectorImpl(debugContext, includePatterns, excludePatterns, includedResourcesModules); - ImageSingletons.lookup(ClassLoaderSupport.class).collectResources(collector); - resourcePatternWorkSet.clear(); } From 53c3f5cd24b3ce685c4904b7c39c8a81d655a4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 13 Sep 2022 09:35:15 +0200 Subject: [PATCH 5/6] Make Resources#addEntry thread-safe instead of accumulating into ConcurrentHashMap for ResourcesRegistryImpl#injectResource --- .../hosted/RuntimeResourceAccess.java | 2 +- .../impl/RuntimeResourceSupport.java | 2 +- .../config/ResourceConfigurationTest.java | 2 +- .../config/ResourceConfiguration.java | 2 +- .../com/oracle/svm/core/jdk/Resources.java | 16 +++--- .../oracle/svm/hosted/ResourcesFeature.java | 56 ++----------------- 6 files changed, 17 insertions(+), 63 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java index f5fb199bebb0..355a4f06e4f7 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java @@ -85,7 +85,7 @@ public static void addResource(Module module, String resourcePath, byte[] resour Objects.requireNonNull(module); Objects.requireNonNull(resourcePath); Objects.requireNonNull(resourceContent); - ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(ConfigurationCondition.alwaysTrue(), + ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource( module, resourcePath, resourceContent); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java index ca8599e072fc..68242b311d69 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java @@ -46,7 +46,7 @@ public interface RuntimeResourceSupport { void addResources(ConfigurationCondition condition, String pattern); - void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent); + void injectResource(Module module, String resourcePath, byte[] resourceContent); void ignoreResources(ConfigurationCondition condition, String pattern); diff --git a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java index ad774a260356..d949092c7ccb 100644 --- a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java +++ b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java @@ -94,7 +94,7 @@ public void addResources(ConfigurationCondition condition, String pattern) { } @Override - public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { + public void injectResource(Module module, String resourcePath, byte[] resourceContent) { } @Override diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java index ca274f1c26db..0fd6d5e53301 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java @@ -64,7 +64,7 @@ public void addResources(ConfigurationCondition condition, String pattern) { } @Override - public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { + public void injectResource(Module module, String resourcePath, byte[] resourceContent) { VMError.shouldNotReachHere("Resource injection is only supported via Feature implementation"); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index ec808b3e1981..d83c44134f93 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -86,14 +86,16 @@ public static byte[] inputStreamToByteArray(InputStream is) { } private static void addEntry(String moduleName, String resourceName, boolean isDirectory, byte[] data, boolean fromJar) { - Resources support = singleton(); - Pair key = Pair.create(moduleName, resourceName); - ResourceStorageEntry entry = support.resources.get(key); - if (entry == null) { - entry = new ResourceStorageEntry(isDirectory, fromJar); - support.resources.put(key, entry); + var resources = singleton().resources; + synchronized (resources) { + Pair key = Pair.create(moduleName, resourceName); + ResourceStorageEntry entry = resources.get(key); + if (entry == null) { + entry = new ResourceStorageEntry(isDirectory, fromJar); + resources.put(key, entry); + } + entry.getData().add(data); } - entry.getData().add(data); } @Platforms(Platform.HOSTED_ONLY.class) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 2b01eefb3ab2..ec633a06163e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -33,8 +33,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Locale; -import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @@ -110,7 +108,6 @@ public static class Options { } private boolean sealed = false; - private final Map injectResourceWorkSet = new ConcurrentHashMap<>(); private final Set resourcePatternWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Set excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>()); private int loadedConfigurations; @@ -118,38 +115,6 @@ public static class Options { public final Set includedResourcesModules = new HashSet<>(); - private static final class ResourceLocation { - private final Module module; - private final String path; - - private ResourceLocation(Module module, String path) { - this.module = module; - this.path = path; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ResourceLocation that = (ResourceLocation) o; - return Objects.equals(module, that.module) && Objects.equals(path, that.path); - } - - @Override - public int hashCode() { - return Objects.hash(module, path); - } - - @Override - public String toString() { - return module.getName() + ":" + path; - } - } - private class ResourcesRegistryImpl extends ConditionalConfigurationRegistry implements ResourcesRegistry { private final ConfigurationTypeResolver configurationTypeResolver; @@ -169,15 +134,9 @@ public void addResources(ConfigurationCondition condition, String pattern) { } @Override - public void injectResource(ConfigurationCondition condition, Module module, String resourcePath, byte[] resourceContent) { - if (configurationTypeResolver.resolveType(condition.getTypeName()) == null) { - return; - } - registerConditionalConfiguration(condition, () -> { - ResourceLocation resourceLocation = new ResourceLocation(module, resourcePath); - UserError.guarantee(!sealed, "Resources added too late: %s", resourceLocation); - injectResourceWorkSet.put(resourceLocation, resourceContent); - }); + public void injectResource(Module module, String resourcePath, byte[] resourceContent) { + var moduleName = module.isNamed() ? module.getName() : null; + Resources.registerResource(moduleName, resourcePath, resourceContent); } @Override @@ -302,19 +261,12 @@ private void collectModuleName(String moduleName) { @Override public void duringAnalysis(DuringAnalysisAccess access) { resourceRegistryImpl().flushConditionalConfiguration(access); - if (resourcePatternWorkSet.isEmpty() && injectResourceWorkSet.isEmpty()) { + if (resourcePatternWorkSet.isEmpty()) { return; } access.requireAnalysisIteration(); - for (Map.Entry entry : injectResourceWorkSet.entrySet()) { - var resourceLocation = entry.getKey(); - var moduleName = resourceLocation.module.isNamed() ? resourceLocation.module.getName() : null; - Resources.registerResource(moduleName, resourceLocation.path, entry.getValue()); - } - injectResourceWorkSet.clear(); - ResourcePattern[] includePatterns = compilePatterns(resourcePatternWorkSet); ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns); DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext(); From 5d7f468f5401edaf8f8dc9c4efe97b5b9a3b7f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 13 Sep 2022 16:06:25 +0200 Subject: [PATCH 6/6] Fix --list-modules to print to System.out --- .../oracle/svm/hosted/NativeImageClassLoaderSupport.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java index f75e559b5709..5966939e9ada 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java @@ -403,6 +403,7 @@ void processClassLoaderOptions() { private static void processListModulesOption(ModuleLayer layer) { Class launcherHelperClass = ReflectionUtil.lookupClass(false, "sun.launcher.LauncherHelper"); + Method initOutputMethod = ReflectionUtil.lookupMethod(launcherHelperClass, "initOutput", boolean.class); Method showModuleMethod = ReflectionUtil.lookupMethod(launcherHelperClass, "showModule", ModuleReference.class); boolean first = true; @@ -411,6 +412,11 @@ private static void processListModulesOption(ModuleLayer layer) { .sorted(Comparator.comparing(ResolvedModule::name)) .collect(Collectors.toList()); if (first) { + try { + initOutputMethod.invoke(null, false); + } catch (ReflectiveOperationException e) { + throw VMError.shouldNotReachHere("Unable to use " + initOutputMethod + " to set printing with " + showModuleMethod + " to System.out.", e); + } first = false; } else if (!resolvedModules.isEmpty()) { System.out.println(); @@ -419,7 +425,7 @@ private static void processListModulesOption(ModuleLayer layer) { try { showModuleMethod.invoke(null, resolvedModule.reference()); } catch (ReflectiveOperationException e) { - throw VMError.shouldNotReachHere("Unable to " + showModuleMethod + " for printing list of modules.", e); + throw VMError.shouldNotReachHere("Unable to use " + showModuleMethod + " for printing list of modules.", e); } } }