Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import com.oracle.svm.core.jdk.JDK11OrLater;
import com.oracle.svm.core.jdk11.BootModuleLayerSupport;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.jdk.NativeImageClassLoaderSupportJDK11OrLater;
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;

Expand Down Expand Up @@ -209,7 +210,14 @@ private static Stream<String> extractRequiredModuleNames(Module m) {
}

private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Set<String> reachableModules, Set<Module> syntheticModules) {
Configuration cf = synthesizeRuntimeBootLayerConfiguration(cl.modulepath(), reachableModules);
/**
* For consistent module lookup we reuse the {@link ModuleFinder}s defined and used in
* {@link NativeImageClassLoaderSupportJDK11OrLater}.
*/
NativeImageClassLoaderSupportJDK11OrLater classLoaderSupport = (NativeImageClassLoaderSupportJDK11OrLater) cl.classLoaderSupport;
ModuleFinder beforeFinder = classLoaderSupport.modulepathModuleFinder;
ModuleFinder afterFinder = classLoaderSupport.upgradeAndSystemModuleFinder;
Configuration cf = synthesizeRuntimeBootLayerConfiguration(beforeFinder, afterFinder, reachableModules);
try {
ModuleLayer runtimeBootLayer = moduleLayerConstructor.newInstance(cf, List.of(), null);
Map<String, Module> nameToModule = moduleLayerFeatureUtils.synthesizeNameToModule(runtimeBootLayer, cl.getClassLoader());
Expand Down Expand Up @@ -307,10 +315,7 @@ private static List<Module> findApplicationModules(ModuleLayer runtimeBootLayer,
return applicationModules;
}

private static Configuration synthesizeRuntimeBootLayerConfiguration(List<Path> mp, Set<String> reachableModules) {
ModuleFinder beforeFinder = new BootModuleLayerModuleFinder();
ModuleFinder afterFinder = ModuleFinder.of(mp.toArray(Path[]::new));

private static Configuration synthesizeRuntimeBootLayerConfiguration(ModuleFinder beforeFinder, ModuleFinder afterFinder, Set<String> reachableModules) {
try {
ModuleFinder composed = ModuleFinder.compose(beforeFinder, afterFinder);
List<String> missingModules = new ArrayList<>();
Expand Down Expand Up @@ -346,27 +351,6 @@ private void patchRuntimeBootLayer(ModuleLayer runtimeBootLayer, Map<String, Mod
runtimeBootLayer.modules();
}

static class BootModuleLayerModuleFinder implements ModuleFinder {

@Override
public Optional<ModuleReference> find(String name) {
return ModuleLayer.boot()
.configuration()
.findModule(name)
.map(ResolvedModule::reference);
}

@Override
public Set<ModuleReference> findAll() {
return ModuleLayer.boot()
.configuration()
.modules()
.stream()
.map(ResolvedModule::reference)
.collect(Collectors.toSet());
}
}

private static final class HostedRuntimeModulePair {
static HostedRuntimeModulePair withReplicatedHostedModule(Module module) {
return new HostedRuntimeModulePair(module, module);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,33 +70,79 @@ public class NativeImageClassLoaderSupportJDK11OrLater extends AbstractNativeIma
private final List<Path> buildmp;

private final ClassLoader classLoader;

public final ModuleFinder upgradeAndSystemModuleFinder;
public final ModuleLayer moduleLayerForImageBuild;

public final ModuleFinder modulepathModuleFinder;

public NativeImageClassLoaderSupportJDK11OrLater(ClassLoader defaultSystemClassLoader, String[] classpath, String[] modulePath) {
super(defaultSystemClassLoader, classpath);

imagemp = Arrays.stream(modulePath).map(Paths::get).collect(Collectors.toUnmodifiableList());
buildmp = Optional.ofNullable(System.getProperty("jdk.module.path")).stream()
.flatMap(s -> Arrays.stream(s.split(File.pathSeparator))).map(Paths::get).collect(Collectors.toUnmodifiableList());

upgradeAndSystemModuleFinder = createUpgradeAndSystemModuleFinder();
ModuleLayer moduleLayer = createModuleLayer(imagemp.toArray(Path[]::new), classPathClassLoader);
adjustBootLayerQualifiedExports(moduleLayer);
moduleLayerForImageBuild = moduleLayer;

classLoader = getSingleClassloader(moduleLayer);

modulepathModuleFinder = ModuleFinder.of(modulepath().toArray(Path[]::new));
}

private static ModuleLayer createModuleLayer(Path[] modulePaths, ClassLoader parent) {
ModuleFinder finder = ModuleFinder.of(modulePaths);
List<Configuration> parents = List.of(ModuleLayer.boot().configuration());
Set<String> moduleNames = finder.findAll().stream().map(moduleReference -> moduleReference.descriptor().name()).collect(Collectors.toSet());
Configuration configuration = Configuration.resolve(finder, parents, finder, moduleNames);
private ModuleLayer createModuleLayer(Path[] modulePaths, ClassLoader parent) {
ModuleFinder modulePathsFinder = ModuleFinder.of(modulePaths);
Set<String> moduleNames = modulePathsFinder.findAll().stream().map(moduleReference -> moduleReference.descriptor().name()).collect(Collectors.toSet());

/**
* When building a moduleLayer for the module-path passed to native-image we need to be able
* to resolve against system modules that are not used by the moduleLayer in which the
* image-builder got loaded into. To do so we use {@link upgradeAndSystemModuleFinder} as
* {@code ModuleFinder after} in
* {@link Configuration#resolve(ModuleFinder, ModuleFinder, Collection)}.
*/
Configuration configuration = ModuleLayer.boot().configuration().resolve(modulePathsFinder, upgradeAndSystemModuleFinder, moduleNames);
/**
* For the modules we want to build an image for, a ModuleLayer is needed that can be
* accessed with a single classloader so we can use it for {@link ImageClassLoader}.
*/
return ModuleLayer.defineModulesWithOneLoader(configuration, List.of(ModuleLayer.boot()), parent).layer();
}

/**
* Gets a finder that locates the upgrade modules and the system modules, in that order. Upgrade
* modules are used when mx environment variable {@code MX_BUILD_EXPLODED=true} is used.
*/
private static ModuleFinder createUpgradeAndSystemModuleFinder() {
ModuleFinder finder = ModuleFinder.ofSystem();
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
if (upgradeModulePath != null) {
finder = ModuleFinder.compose(upgradeModulePath, finder);
}
return finder;
}

/**
* Creates a finder from a module path specified by the {@code prop} system property.
*/
private static ModuleFinder finderFor(String prop) {
String s = System.getProperty(prop);
if (s == null || s.isEmpty()) {
return null;
} else {
String[] dirs = s.split(File.pathSeparator);
Path[] paths = new Path[dirs.length];
int i = 0;
for (String dir : dirs) {
paths[i++] = Path.of(dir);
}
return ModuleFinder.of(paths);
}
}

private static void adjustBootLayerQualifiedExports(ModuleLayer layer) {
/*
* For all qualified exports packages of modules in the the boot layer we check if layer
Expand Down Expand Up @@ -350,41 +396,6 @@ public ClassLoader getClassLoader() {
return classLoader;
}

private static ModuleFinder upgradeAndSystemModuleFinder;

/**
* Creates a finder from a module path specified by the {@code prop} system property.
*/
private static ModuleFinder finderFor(String prop) {
String s = System.getProperty(prop);
if (s == null || s.isEmpty()) {
return null;
} else {
String[] dirs = s.split(File.pathSeparator);
Path[] paths = new Path[dirs.length];
int i = 0;
for (String dir : dirs) {
paths[i++] = Path.of(dir);
}
return ModuleFinder.of(paths);
}
}

/**
* Gets a finder that locates the upgrade modules and the system modules, in that order.
*/
private static ModuleFinder getUpgradeAndSystemModuleFinder() {
if (upgradeAndSystemModuleFinder == null) {
ModuleFinder finder = ModuleFinder.ofSystem();
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
if (upgradeModulePath != null) {
finder = ModuleFinder.compose(upgradeModulePath, finder);
}
upgradeAndSystemModuleFinder = finder;
}
return upgradeAndSystemModuleFinder;
}

private class ClassInitWithModules extends ClassInit {

ClassInitWithModules(ForkJoinPool executor, ImageClassLoader imageClassLoader) {
Expand All @@ -397,12 +408,12 @@ protected void init() {
"jdk.internal.vm.ci", "jdk.internal.vm.compiler", "com.oracle.graal.graal_enterprise",
"org.graalvm.sdk", "org.graalvm.truffle");

for (ModuleReference moduleReference : getUpgradeAndSystemModuleFinder().findAll()) {
for (ModuleReference moduleReference : upgradeAndSystemModuleFinder.findAll()) {
if (requiresInit.contains(moduleReference.descriptor().name())) {
initModule(moduleReference);
}
}
for (ModuleReference moduleReference : ModuleFinder.of(modulepath().toArray(Path[]::new)).findAll()) {
for (ModuleReference moduleReference : modulepathModuleFinder.findAll()) {
initModule(moduleReference);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.AfterAnalysisAccessImpl;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.util.ModuleSupport;

import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.ResolvedJavaMethod;
Expand All @@ -62,6 +63,8 @@ public class FallbackFeature implements Feature {
private final List<String> proxyCalls = new ArrayList<>();
private final List<String> serializationCalls = new ArrayList<>();

private final Set<Object> systemModuleDescriptors = ModuleSupport.getSystemModuleDescriptors();

private static class AutoProxyInvoke {
private final ResolvedJavaMethod method;
private final int bci;
Expand Down Expand Up @@ -103,7 +106,7 @@ private interface InvokeChecker {
void check(ReflectionInvocationCheck check, BytecodePosition invokeLocation);
}

private static class ReflectionInvocationCheck {
private class ReflectionInvocationCheck {
private final Method reflectionMethod;
private final InvokeChecker checker;
private AnalysisMethod trackedReflectionMethod;
Expand All @@ -120,10 +123,18 @@ void trackMethod(AnalysisMetaAccess metaAccess) {
}

void apply(BytecodePosition invokeLocation) {
ClassLoader classLoader = ((AnalysisMethod) invokeLocation.getMethod()).getDeclaringClass().getJavaClass().getClassLoader();
if (NativeImageSystemClassLoader.singleton().isNativeImageClassLoader(classLoader)) {
checker.check(this, invokeLocation);
Class<?> javaClass = ((AnalysisMethod) invokeLocation.getMethod()).getDeclaringClass().getJavaClass();
if (systemModuleDescriptors.contains(ModuleSupport.getModuleDescriptor(javaClass))) {
/* Ensure all JDK system modules are excluded from reporting reflection use. */
return;
}
ClassLoader classLoader = javaClass.getClassLoader();
if (!NativeImageSystemClassLoader.singleton().isNativeImageClassLoader(classLoader)) {
/* Classes not loaded by NativeImageClassLoader are also excluded. */
return;
}
/* Collect reflection use in application classes. */
checker.check(this, invokeLocation);
}

String locationString(BytecodePosition invokeLocation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@
*/
package com.oracle.svm.util;

import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand Down Expand Up @@ -124,4 +127,14 @@ public static void exportAndOpenPackageToUnnamed(String name, String pkg, boolea
public static String getModuleName(Class<?> clazz) {
return clazz.getModule().getName();
}

public static Object getModuleDescriptor(Class<?> clazz) {
return clazz.getModule().getDescriptor();
}

public static Set<Object> getSystemModuleDescriptors() {
return ModuleFinder.ofSystem().findAll().stream()
.map(ModuleReference::descriptor)
.collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
*/
package com.oracle.svm.util;

import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;

import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
Expand Down Expand Up @@ -86,4 +88,15 @@ public static String getModuleName(Class<?> clazz) {
assert JavaVersionUtil.JAVA_SPEC <= 8;
return null;
}

@SuppressWarnings("unused")
public static Object getModuleDescriptor(Class<?> clazz) {
assert JavaVersionUtil.JAVA_SPEC <= 8;
return null;
}

public static Set<Object> getSystemModuleDescriptors() {
assert JavaVersionUtil.JAVA_SPEC <= 8;
return Collections.emptySet();
}
}