|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package jdk.internal.loader; |
|
|
|
import java.io.IOException; |
|
import java.io.InputStream; |
|
import java.lang.module.ModuleReference; |
|
import java.net.MalformedURLException; |
|
import java.net.URI; |
|
import java.net.URL; |
|
import java.nio.file.Files; |
|
import java.nio.file.Path; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Arrays; |
|
import java.util.Enumeration; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.jar.JarInputStream; |
|
import java.util.jar.Manifest; |
|
import java.util.stream.Stream; |
|
|
|
import jdk.internal.access.JavaLangAccess; |
|
import jdk.internal.access.SharedSecrets; |
|
import jdk.internal.module.Modules; |
|
import jdk.internal.module.ServicesCatalog; |
|
import jdk.internal.util.StaticProperty; |
|
|
|
/** |
|
* Find resources and packages in modules defined to the boot class loader or |
|
* resources and packages on the "boot class path" specified via -Xbootclasspath/a. |
|
*/ |
|
|
|
public class BootLoader { |
|
private BootLoader() { } |
|
|
|
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); |
|
|
|
|
|
private static final Module UNNAMED_MODULE; |
|
private static final String JAVA_HOME = StaticProperty.javaHome(); |
|
|
|
static { |
|
JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
|
UNNAMED_MODULE = jla.defineUnnamedModule(null); |
|
jla.addEnableNativeAccess(UNNAMED_MODULE); |
|
setBootLoaderUnnamedModule0(UNNAMED_MODULE); |
|
} |
|
|
|
|
|
private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP |
|
= new ConcurrentHashMap<>(); |
|
|
|
|
|
private static final NativeLibraries NATIVE_LIBS |
|
= NativeLibraries.jniNativeLibraries(null); |
|
|
|
|
|
|
|
*/ |
|
public static Module getUnnamedModule() { |
|
return UNNAMED_MODULE; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static ServicesCatalog getServicesCatalog() { |
|
return ServicesCatalog.getServicesCatalog(ClassLoaders.bootLoader()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static ConcurrentHashMap<?, ?> getClassLoaderValueMap() { |
|
return CLASS_LOADER_VALUE_MAP; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static NativeLibraries getNativeLibraries() { |
|
return NATIVE_LIBS; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean hasClassPath() { |
|
return ClassLoaders.bootLoader().hasClassPath(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void loadModule(ModuleReference mref) { |
|
ClassLoaders.bootLoader().loadModule(mref); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static Class<?> loadClassOrNull(String name) { |
|
return JLA.findBootstrapClassOrNull(name); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static Class<?> loadClass(Module module, String name) { |
|
Class<?> c = loadClassOrNull(name); |
|
if (c != null && c.getModule() == module) { |
|
return c; |
|
} else { |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("removal") |
|
public static void loadLibrary(String name) { |
|
if (System.getSecurityManager() == null) { |
|
BootLoader.getNativeLibraries().loadLibrary(name); |
|
} else { |
|
AccessController.doPrivileged(new java.security.PrivilegedAction<>() { |
|
public Void run() { |
|
BootLoader.getNativeLibraries().loadLibrary(name); |
|
return null; |
|
} |
|
}); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static URL findResource(String mn, String name) throws IOException { |
|
return ClassLoaders.bootLoader().findResource(mn, name); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static InputStream findResourceAsStream(String mn, String name) |
|
throws IOException |
|
{ |
|
return ClassLoaders.bootLoader().findResourceAsStream(mn, name); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static URL findResource(String name) { |
|
return ClassLoaders.bootLoader().findResource(name); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static Enumeration<URL> findResources(String name) throws IOException { |
|
return ClassLoaders.bootLoader().findResources(name); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static Package definePackage(Class<?> c) { |
|
return getDefinedPackage(c.getPackageName()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static Package getDefinedPackage(String pn) { |
|
Package pkg = ClassLoaders.bootLoader().getDefinedPackage(pn); |
|
if (pkg == null) { |
|
String location = getSystemPackageLocation(pn.replace('.', '/')); |
|
if (location != null) { |
|
pkg = PackageHelper.definePackage(pn.intern(), location); |
|
} |
|
} |
|
return pkg; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static Stream<Package> packages() { |
|
return Arrays.stream(getSystemPackageNames()) |
|
.map(name -> getDefinedPackage(name.replace('/', '.'))); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
static class PackageHelper { |
|
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static Package definePackage(String name, String location) { |
|
Module module = findModule(location); |
|
if (module != null) { |
|
|
|
if (name.isEmpty()) |
|
throw new InternalError("empty package in " + location); |
|
return JLA.definePackage(ClassLoaders.bootLoader(), name, module); |
|
} |
|
|
|
|
|
URL url = toFileURL(location); |
|
Manifest man = url != null ? getManifest(location) : null; |
|
|
|
return ClassLoaders.bootLoader().defineOrCheckPackage(name, man, url); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static Module findModule(String location) { |
|
String mn = null; |
|
if (location.startsWith("jrt:/")) { |
|
|
|
mn = location.substring(5, location.length()); |
|
} else if (location.startsWith("file:/")) { |
|
|
|
Path path = Path.of(URI.create(location)); |
|
Path modulesDir = Path.of(JAVA_HOME, "modules"); |
|
if (path.startsWith(modulesDir)) { |
|
mn = path.getFileName().toString(); |
|
} |
|
} |
|
|
|
// return the Module object for the module name. The Module may |
|
// in the boot layer or a child layer for the case that the module |
|
|
|
if (mn != null) { |
|
String name = mn; |
|
return Modules.findLoadedModule(mn) |
|
.orElseThrow(() -> new InternalError(name + " not loaded")); |
|
} else { |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("removal") |
|
private static URL toFileURL(String location) { |
|
return AccessController.doPrivileged(new PrivilegedAction<>() { |
|
public URL run() { |
|
Path path = Path.of(location); |
|
if (Files.isRegularFile(path)) { |
|
try { |
|
return path.toUri().toURL(); |
|
} catch (MalformedURLException e) {} |
|
} |
|
return null; |
|
} |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("removal") |
|
private static Manifest getManifest(String location) { |
|
return AccessController.doPrivileged(new PrivilegedAction<>() { |
|
public Manifest run() { |
|
Path jar = Path.of(location); |
|
try (InputStream in = Files.newInputStream(jar); |
|
JarInputStream jis = new JarInputStream(in, false)) { |
|
return jis.getManifest(); |
|
} catch (IOException e) { |
|
return null; |
|
} |
|
} |
|
}); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private static native String[] getSystemPackageNames(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static native String getSystemPackageLocation(String name); |
|
private static native void setBootLoaderUnnamedModule0(Module module); |
|
} |