Skip to content

Commit bdb321b

Browse files
author
Esteban Ginez
committed
[GR-20680] Amend ResourcesFeature and NativeImage to support java.xml
1 parent 3e83a17 commit bdb321b

3 files changed

Lines changed: 69 additions & 23 deletions

File tree

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@
3535
import java.util.HashMap;
3636
import java.util.List;
3737
import java.util.Map;
38+
import java.util.Set;
3839

39-
import org.graalvm.nativeimage.hosted.Feature;
4040
import org.graalvm.nativeimage.ImageSingletons;
4141
import org.graalvm.nativeimage.Platform;
4242
import org.graalvm.nativeimage.Platforms;
43+
import org.graalvm.nativeimage.hosted.Feature;
4344

4445
import com.oracle.svm.core.annotate.AutomaticFeature;
4546
import com.oracle.svm.core.hub.DynamicHub;
@@ -56,6 +57,10 @@ public final class Resources {
5657

5758
static class ResourcesSupport {
5859
final Map<String, List<byte[]>> resources = new HashMap<>();
60+
61+
public Set<String> registeredResources() {
62+
return resources.keySet();
63+
}
5964
}
6065

6166
@AutomaticFeature
@@ -95,18 +100,17 @@ public static void registerResource(String name, InputStream is) {
95100
byte[] res = new byte[pos];
96101
System.arraycopy(arr, 0, res, 0, pos);
97102

98-
List<byte[]> list = support.resources.get(name);
99-
if (list == null) {
100-
list = new ArrayList<>();
101-
support.resources.put(name, list);
102-
}
103-
list.add(res);
103+
support.resources.computeIfAbsent(name, k -> new ArrayList<>()).add(res);
104104
}
105105

106106
public static List<byte[]> get(String name) {
107107
return ImageSingletons.lookup(ResourcesSupport.class).resources.get(name);
108108
}
109109

110+
public static Set<String> registeredResources() {
111+
return ImageSingletons.lookup(ResourcesSupport.class).registeredResources();
112+
}
113+
110114
public static URL createURL(String name, byte[] resourceBytes) {
111115
class Conn extends URLConnection {
112116
Conn(URL url) {

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public class NativeImage {
9797
static final boolean IS_AOT = Boolean.getBoolean("com.oracle.graalvm.isaot");
9898

9999
static final String platform = getPlatform();
100+
// resources.jar packs resources files needed for some jdk services such as xml serialization
101+
private static final Path RESOURCES_JAR_PATH_JAVA8 = Paths.get("jre", "lib", "resources.jar");
100102

101103
private static String getPlatform() {
102104
return (OS.getCurrent().className + "-" + SubstrateUtil.getArchitectureName()).toLowerCase();
@@ -704,7 +706,6 @@ private void prepareImageBuildArgs() {
704706
* non-system class and and triggers a warning.
705707
*/
706708
addImageBuilderJavaArgs("-Xshare:off");
707-
708709
config.getBuilderClasspath().forEach(this::addImageBuilderClasspath);
709710
config.getImageProvidedClasspath().forEach(this::addImageProvidedClasspath);
710711
String clibrariesBuilderArg = config.getBuilderCLibrariesPaths()
@@ -739,6 +740,7 @@ private void prepareImageBuildArgs() {
739740
}
740741

741742
config.getBuilderBootClasspath().forEach((Consumer<? super Path>) this::addImageBuilderBootClasspath);
743+
addCustomImageClasspath(config.getJavaHome().resolve(RESOURCES_JAR_PATH_JAVA8));
742744
}
743745

744746
config.getImageClasspath().forEach(this::addCustomImageClasspath);
@@ -1687,6 +1689,7 @@ public static void main(String[] args) {
16871689
if (!IS_AOT) {
16881690
ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.internal.vm.compiler", false);
16891691
ModuleSupport.exportAndOpenAllPackagesToUnnamed("com.oracle.graal.graal_enterprise", true);
1692+
ModuleSupport.exportAndOpenAllPackagesToUnnamed("java.xml", false);
16901693
}
16911694
NativeImage.main(args);
16921695
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,29 @@
2929
import java.io.FileInputStream;
3030
import java.io.IOException;
3131
import java.io.InputStream;
32+
import java.lang.module.ModuleReader;
33+
import java.lang.module.ModuleReference;
34+
import java.lang.module.ResolvedModule;
3235
import java.net.URISyntaxException;
3336
import java.net.URL;
3437
import java.net.URLClassLoader;
3538
import java.util.Arrays;
3639
import java.util.Collections;
3740
import java.util.Enumeration;
3841
import java.util.HashSet;
42+
import java.util.List;
3943
import java.util.Set;
4044
import java.util.concurrent.ConcurrentHashMap;
4145
import java.util.jar.JarEntry;
4246
import java.util.jar.JarFile;
4347
import java.util.regex.Pattern;
48+
import java.util.stream.Collectors;
4449

50+
import com.oracle.svm.core.util.VMError;
4551
import org.graalvm.compiler.debug.DebugContext;
4652
import org.graalvm.compiler.options.Option;
4753
import org.graalvm.compiler.options.OptionType;
54+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
4855
import org.graalvm.nativeimage.ImageSingletons;
4956
import org.graalvm.nativeimage.hosted.Feature;
5057

@@ -60,12 +67,16 @@
6067
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
6168
import com.oracle.svm.hosted.config.ConfigurationParserUtils;
6269

70+
6371
@AutomaticFeature
6472
public final class ResourcesFeature implements Feature {
6573

6674
public static class Options {
6775
@Option(help = "Regexp to match names of resources to be included in the image.", type = OptionType.User)//
6876
public static final HostedOptionKey<String[]> IncludeResources = new HostedOptionKey<>(new String[0]);
77+
78+
@Option(help = "Print included resources.", type = OptionType.User)//
79+
public static final HostedOptionKey<Boolean> PrintIncludedResources = new HostedOptionKey<>(false);
6980
}
7081

7182
private boolean sealed = false;
@@ -106,11 +117,20 @@ public void duringAnalysis(DuringAnalysisAccess access) {
106117
if (newResources.isEmpty()) {
107118
return;
108119
}
120+
109121
access.requireAnalysisIteration();
110-
for (String regExp : newResources) {
111-
if (regExp.length() == 0) {
112-
continue;
113-
}
122+
DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext();
123+
final Pattern[] patterns = newResources.stream()
124+
.filter(s -> s.length() > 0)
125+
.map(Pattern::compile)
126+
.collect(Collectors.toList())
127+
.toArray(new Pattern[]{});
128+
129+
if (JavaVersionUtil.JAVA_SPEC > 8) {
130+
findResourcesInModules(debugContext, patterns);
131+
}
132+
133+
for (Pattern pattern : patterns) {
114134

115135
/*
116136
* Since IncludeResources takes regular expressions it's safer to disallow passing
@@ -122,8 +142,6 @@ public void duringAnalysis(DuringAnalysisAccess access) {
122142
* @formatter:on
123143
*/
124144

125-
Pattern pattern = Pattern.compile(regExp);
126-
127145
final Set<File> todo = new HashSet<>();
128146
// Checkstyle: stop
129147
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -140,7 +158,6 @@ public void duringAnalysis(DuringAnalysisAccess access) {
140158
// Checkstyle: resume
141159
for (File element : todo) {
142160
try {
143-
DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext();
144161
if (element.isDirectory()) {
145162
scanDirectory(debugContext, element, "", pattern);
146163
} else {
@@ -157,6 +174,11 @@ public void duringAnalysis(DuringAnalysisAccess access) {
157174
@Override
158175
public void afterAnalysis(AfterAnalysisAccess access) {
159176
sealed = true;
177+
if (Options.PrintIncludedResources.getValue()) {
178+
for (String registeredResource : Resources.registeredResources()) {
179+
System.out.println(registeredResource);
180+
}
181+
}
160182
}
161183

162184
@Override
@@ -184,10 +206,7 @@ private void scanDirectory(DebugContext debugContext, File f, String relativePat
184206
} else {
185207
if (matches(patterns, relativePath)) {
186208
try (FileInputStream is = new FileInputStream(f)) {
187-
try (DebugContext.Scope s = debugContext.scope("registerResource")) {
188-
debugContext.log("ResourcesFeature: registerResource: " + relativePath);
189-
}
190-
Resources.registerResource(relativePath, is);
209+
registerResource(debugContext, relativePath, is);
191210
}
192211
}
193212
}
@@ -204,11 +223,25 @@ private static void scanJar(DebugContext debugContext, File element, Pattern...
204223
}
205224
if (matches(patterns, e.getName())) {
206225
try (InputStream is = jf.getInputStream(e)) {
207-
try (DebugContext.Scope s = debugContext.scope("registerResource")) {
208-
debugContext.log("ResourcesFeature: registerResource: " + e.getName());
209-
}
210-
Resources.registerResource(e.getName(), is);
226+
registerResource(debugContext, e.getName(), is);
227+
}
228+
}
229+
}
230+
}
231+
232+
private static void findResourcesInModules(DebugContext debugContext, Pattern[] patterns) {
233+
for (ResolvedModule resolvedModule : ModuleLayer.boot().configuration().modules()) {
234+
ModuleReference modRef = resolvedModule.reference();
235+
try (ModuleReader moduleReader = modRef.open()) {
236+
final List<String> resources = moduleReader.list()
237+
.filter(s -> matches(patterns, s))
238+
.collect(Collectors.toList());
239+
for (String resName : resources) {
240+
moduleReader.open(resName)
241+
.ifPresent(is -> registerResource(debugContext, resName, is));
211242
}
243+
} catch (IOException ex) {
244+
VMError.shouldNotReachHere("Can not read the resources of module", ex);
212245
}
213246
}
214247
}
@@ -221,4 +254,10 @@ private static boolean matches(Pattern[] patterns, String relativePath) {
221254
}
222255
return false;
223256
}
257+
258+
private static void registerResource(DebugContext debugContext, String resourceName, InputStream resourceStream) {
259+
debugContext.log(DebugContext.VERBOSE_LEVEL, "ResourcesFeature: registerResource: " + resourceName);
260+
Resources.registerResource(resourceName, resourceStream);
261+
}
262+
224263
}

0 commit comments

Comments
 (0)