Skip to content

Commit 3cae6b4

Browse files
committed
[GR-62314] Register libraries from base layer in extension layers
PullRequest: graal/20068
2 parents c75743d + 1c1036d commit 3cae6b4

File tree

5 files changed

+110
-25
lines changed

5 files changed

+110
-25
lines changed

substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ struct SharedLayerSnapshot {
268268
fields @13 :List(PersistedAnalysisField);
269269
nextLayerNumber @14 :Int32;
270270
staticFinalFieldFoldingSingleton @15 :StaticFinalFieldFoldingSingleton;
271+
registeredJNILibraries @16 :List(Text);
271272
}
272273

273274
struct StaticFinalFieldFoldingSingleton {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ private static IntStream streamInts(PrimitiveList.Int.Reader reader) {
304304
return IntStream.range(0, reader.size()).map(reader::get);
305305
}
306306

307-
private static Stream<String> streamStrings(TextList.Reader reader) {
307+
public static Stream<String> streamStrings(TextList.Reader reader) {
308308
return IntStream.range(0, reader.size()).mapToObj(i -> reader.get(i).toString());
309309
}
310310

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ private static void initInts(IntFunction<PrimitiveList.Int.Builder> builderSuppl
372372
}
373373
}
374374

375-
private static void initStringList(IntFunction<TextList.Builder> builderSupplier, Stream<String> strings) {
375+
public static void initStringList(IntFunction<TextList.Builder> builderSupplier, Stream<String> strings) {
376376
Object[] array = strings.toArray();
377377
TextList.Builder builder = builderSupplier.apply(array.length);
378378
for (int i = 0; i < array.length; i++) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -4539,7 +4539,7 @@ public final org.capnproto.StructList.Reader<com.oracle.svm.hosted.imagelayer.Sh
45394539

45404540

45414541
public static class SharedLayerSnapshot {
4542-
public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)5,(short)8);
4542+
public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)5,(short)9);
45434543
public static final class Factory extends org.capnproto.StructFactory<Builder, Reader> {
45444544
public Factory() {
45454545
}
@@ -4715,6 +4715,18 @@ public final void setStaticFinalFieldFoldingSingleton(com.oracle.svm.hosted.imag
47154715
public final com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.StaticFinalFieldFoldingSingleton.Builder initStaticFinalFieldFoldingSingleton() {
47164716
return _initPointerField(com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.StaticFinalFieldFoldingSingleton.factory,7, 0);
47174717
}
4718+
public final boolean hasRegisteredJNILibraries() {
4719+
return !_pointerFieldIsNull(8);
4720+
}
4721+
public final org.capnproto.TextList.Builder getRegisteredJNILibraries() {
4722+
return _getPointerField(org.capnproto.TextList.factory, 8, null, 0);
4723+
}
4724+
public final void setRegisteredJNILibraries(org.capnproto.TextList.Reader value) {
4725+
_setPointerField(org.capnproto.TextList.factory, 8, value);
4726+
}
4727+
public final org.capnproto.TextList.Builder initRegisteredJNILibraries(int size) {
4728+
return _initPointerField(org.capnproto.TextList.factory, 8, size);
4729+
}
47184730
}
47194731

47204732
public static final class Reader extends org.capnproto.StructReader {
@@ -4810,6 +4822,13 @@ public com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder
48104822
return _getPointerField(com.oracle.svm.hosted.imagelayer.SharedLayerSnapshotCapnProtoSchemaHolder.StaticFinalFieldFoldingSingleton.factory,7,null, 0);
48114823
}
48124824

4825+
public final boolean hasRegisteredJNILibraries() {
4826+
return !_pointerFieldIsNull(8);
4827+
}
4828+
public final org.capnproto.TextList.Reader getRegisteredJNILibraries() {
4829+
return _getPointerField(org.capnproto.TextList.factory, 8, null, 0);
4830+
}
4831+
48134832
}
48144833

48154834
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java

+87-22
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
import java.nio.file.NoSuchFileException;
3333
import java.nio.file.Path;
3434
import java.util.Collection;
35+
import java.util.EnumSet;
36+
import java.util.HashSet;
3537
import java.util.List;
38+
import java.util.Set;
3639
import java.util.SortedMap;
3740
import java.util.SortedSet;
3841
import java.util.TreeMap;
@@ -41,17 +44,6 @@
4144
import java.util.concurrent.ConcurrentMap;
4245
import java.util.stream.Stream;
4346

44-
import jdk.graal.compiler.debug.DebugContext;
45-
import jdk.graal.compiler.debug.DebugContext.Activation;
46-
import jdk.graal.compiler.debug.DebugContext.Scope;
47-
import jdk.graal.compiler.debug.Indent;
48-
import jdk.graal.compiler.nodes.ValueNode;
49-
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
50-
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
51-
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin;
52-
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
53-
import jdk.graal.compiler.options.Option;
54-
import jdk.graal.compiler.phases.util.Providers;
5547
import org.graalvm.nativeimage.ImageSingletons;
5648
import org.graalvm.nativeimage.Platforms;
5749
import org.graalvm.nativeimage.impl.InternalPlatform;
@@ -61,8 +53,13 @@
6153
import com.oracle.svm.core.SubstrateOptions;
6254
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
6355
import com.oracle.svm.core.feature.InternalFeature;
56+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
6457
import com.oracle.svm.core.jdk.JNIRegistrationUtil;
6558
import com.oracle.svm.core.jdk.NativeLibrarySupport;
59+
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
60+
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
61+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
62+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
6663
import com.oracle.svm.core.option.HostedOptionKey;
6764
import com.oracle.svm.core.util.InterruptImageBuilding;
6865
import com.oracle.svm.core.util.VMError;
@@ -72,7 +69,21 @@
7269
import com.oracle.svm.hosted.c.NativeLibraries;
7370
import com.oracle.svm.hosted.c.codegen.CCompilerInvoker;
7471
import com.oracle.svm.hosted.c.util.FileUtils;
72+
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
73+
import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader;
74+
import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter;
7575

76+
import jdk.graal.compiler.debug.DebugContext;
77+
import jdk.graal.compiler.debug.DebugContext.Activation;
78+
import jdk.graal.compiler.debug.DebugContext.Scope;
79+
import jdk.graal.compiler.debug.Indent;
80+
import jdk.graal.compiler.nodes.ValueNode;
81+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
82+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
83+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin;
84+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
85+
import jdk.graal.compiler.options.Option;
86+
import jdk.graal.compiler.phases.util.Providers;
7687
import jdk.internal.loader.BootLoader;
7788
import jdk.vm.ci.meta.ResolvedJavaMethod;
7889

@@ -86,14 +97,24 @@ public static class Options {
8697
public static final HostedOptionKey<Boolean> CreateJvmShim = new HostedOptionKey<>(false);
8798
}
8899

89-
private final ConcurrentMap<String, Boolean> registeredLibraries = new ConcurrentHashMap<>();
90100
private NativeLibraries nativeLibraries = null;
101+
private JNIRegistrationSupportSingleton jniRegistrationSupportSingleton = null;
91102
private boolean isSunMSCAPIProviderReachable = false;
92103

93104
public static JNIRegistrationSupport singleton() {
94105
return ImageSingletons.lookup(JNIRegistrationSupport.class);
95106
}
96107

108+
@Override
109+
public void afterRegistration(AfterRegistrationAccess access) {
110+
if (ImageLayerBuildingSupport.firstImageBuild()) {
111+
jniRegistrationSupportSingleton = new JNIRegistrationSupportSingleton();
112+
ImageSingletons.add(JNIRegistrationSupportSingleton.class, jniRegistrationSupportSingleton);
113+
} else {
114+
jniRegistrationSupportSingleton = JNIRegistrationSupportSingleton.singleton();
115+
}
116+
}
117+
97118
@Override
98119
public void beforeAnalysis(BeforeAnalysisAccess access) {
99120
nativeLibraries = ((BeforeAnalysisAccessImpl) access).getNativeLibraries();
@@ -105,6 +126,11 @@ public void afterAnalysis(AfterAnalysisAccess access) {
105126
var optSunMSCAPIClass = optionalClazz(access, "sun.security.mscapi.SunMSCAPI");
106127
isSunMSCAPIProviderReachable = optSunMSCAPIClass.isPresent() && access.isReachable(optSunMSCAPIClass.get());
107128
}
129+
if (ImageLayerBuildingSupport.buildingExtensionLayer()) {
130+
for (String library : jniRegistrationSupportSingleton.baseLayerRegisteredLibraries) {
131+
addLibrary(library);
132+
}
133+
}
108134
}
109135

110136
@Override
@@ -133,19 +159,23 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
133159
}
134160

135161
void registerLibrary(String libname) {
136-
if (libname != null && registeredLibraries.putIfAbsent(libname, Boolean.TRUE) == null) {
137-
/*
138-
* If a library is in our list of static standard libraries, add the library to the
139-
* linker command.
140-
*/
141-
if (NativeLibrarySupport.singleton().isPreregisteredBuiltinLibrary(libname)) {
142-
nativeLibraries.addStaticJniLibrary(libname);
143-
}
162+
if (libname != null && jniRegistrationSupportSingleton.registeredLibraries.putIfAbsent(libname, Boolean.TRUE) == null) {
163+
addLibrary(libname);
164+
}
165+
}
166+
167+
private void addLibrary(String libname) {
168+
/*
169+
* If a library is in our list of static standard libraries, add the library to the linker
170+
* command.
171+
*/
172+
if (NativeLibrarySupport.singleton().isPreregisteredBuiltinLibrary(libname)) {
173+
nativeLibraries.addStaticJniLibrary(libname);
144174
}
145175
}
146176

147177
public boolean isRegisteredLibrary(String libname) {
148-
return registeredLibraries.containsKey(libname);
178+
return jniRegistrationSupportSingleton.registeredLibraries.containsKey(libname);
149179
}
150180

151181
/** Adds exports that `jvm` shim should re-export. */
@@ -232,7 +262,13 @@ private void copyJDKLibraries(Path jdkLibDir) {
232262
DebugContext debug = accessImpl.getDebugContext();
233263
try (Scope s = debug.scope("copy");
234264
Indent i = debug.logAndIndent("from: %s", jdkLibDir)) {
235-
for (String libname : new TreeSet<>(registeredLibraries.keySet())) {
265+
for (String libname : new TreeSet<>(jniRegistrationSupportSingleton.registeredLibraries.keySet())) {
266+
if (jniRegistrationSupportSingleton.baseLayerRegisteredLibraries.contains(libname)) {
267+
/* Skip libraries copied in the base layer. */
268+
debug.log(DebugContext.INFO_LEVEL, "%s: SKIPPED", libname);
269+
continue;
270+
}
271+
236272
String library = System.mapLibraryName(libname);
237273

238274
if (NativeLibrarySupport.singleton().isPreregisteredBuiltinLibrary(libname)) {
@@ -334,4 +370,33 @@ private Path getImageImportLib() {
334370
assert Files.exists(importLib);
335371
return importLib;
336372
}
373+
374+
private static final class JNIRegistrationSupportSingleton implements LayeredImageSingleton {
375+
private final ConcurrentMap<String, Boolean> registeredLibraries = new ConcurrentHashMap<>();
376+
private final Set<String> baseLayerRegisteredLibraries = new HashSet<>();
377+
378+
public static JNIRegistrationSupportSingleton singleton() {
379+
return ImageSingletons.lookup(JNIRegistrationSupportSingleton.class);
380+
}
381+
382+
@Override
383+
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
384+
return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY;
385+
}
386+
387+
@Override
388+
public PersistFlags preparePersist(ImageSingletonWriter writer) {
389+
var snapshotWriter = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder();
390+
SVMImageLayerWriter.initStringList(snapshotWriter::initRegisteredJNILibraries, registeredLibraries.keySet().stream());
391+
return PersistFlags.CREATE;
392+
}
393+
394+
@SuppressWarnings("unused")
395+
public static Object createFromLoader(ImageSingletonLoader loader) {
396+
JNIRegistrationSupportSingleton singleton = new JNIRegistrationSupportSingleton();
397+
var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader();
398+
SVMImageLayerLoader.streamStrings(snapshotReader.getRegisteredJNILibraries()).forEach(singleton.baseLayerRegisteredLibraries::add);
399+
return singleton;
400+
}
401+
}
337402
}

0 commit comments

Comments
 (0)