--- old/src/hotspot/share/classfile/vmSymbols.hpp 2020-03-09 16:05:46.000000000 -0700 +++ new/src/hotspot/share/classfile/vmSymbols.hpp 2020-03-09 16:05:46.000000000 -0700 @@ -65,7 +65,6 @@ template(java_lang_Cloneable, "java/lang/Cloneable") \ template(java_lang_Throwable, "java/lang/Throwable") \ template(java_lang_ClassLoader, "java/lang/ClassLoader") \ - template(java_lang_ClassLoader_NativeLibrary, "java/lang/ClassLoader\x024NativeLibrary") \ template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \ template(java_lang_Boolean, "java/lang/Boolean") \ template(java_lang_Character, "java/lang/Character") \ @@ -130,6 +129,7 @@ template(java_util_Iterator, "java/util/Iterator") \ template(java_lang_Record, "java/lang/Record") \ \ + template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \ template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \ template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \ \ --- old/src/hotspot/share/prims/jni.cpp 2020-03-09 16:05:47.000000000 -0700 +++ new/src/hotspot/share/prims/jni.cpp 2020-03-09 16:05:47.000000000 -0700 @@ -397,13 +397,13 @@ // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed // in the correct class context. if (k->class_loader() == NULL && - k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) { + k->name() == vmSymbols::jdk_internal_loader_NativeLibraries()) { JavaValue result(T_OBJECT); JavaCalls::call_static(&result, k, vmSymbols::getFromClass_name(), vmSymbols::void_class_signature(), CHECK_NULL); - // When invoked from JNI_OnLoad, NativeLibrary::getFromClass returns + // When invoked from JNI_OnLoad, NativeLibraries::getFromClass returns // a non-NULL Class object. When invoked from JNI_OnUnload, // it will return NULL to indicate no context. oop mirror = (oop) result.get_jobject(); --- old/src/hotspot/share/prims/nativeLookup.cpp 2020-03-09 16:05:48.000000000 -0700 +++ new/src/hotspot/share/prims/nativeLookup.cpp 2020-03-09 16:05:48.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,7 +159,7 @@ // If the loader is null we have a system class, so we attempt a lookup in // the native Java library. This takes care of any bootstrapping problems. - // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_00024NativeLibrary_find + // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_findNative // gets found the first time around - otherwise an infinite loop can occure. This is // another VM/library dependency Handle loader(THREAD, method->method_holder()->class_loader()); --- old/src/java.base/macosx/classes/apple/security/KeychainStore.java 2020-03-09 16:05:49.000000000 -0700 +++ new/src/java.base/macosx/classes/apple/security/KeychainStore.java 2020-03-09 16:05:49.000000000 -0700 @@ -106,7 +106,7 @@ private static final Debug debug = Debug.getInstance("keystore"); static { - jdk.internal.loader.BootLoader.loadLibrary("osxsecurity"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("osxsecurity"); } private static void permissionCheck() { --- old/src/java.base/macosx/classes/sun/nio/fs/UTIFileTypeDetector.java 2020-03-09 16:05:50.000000000 -0700 +++ new/src/java.base/macosx/classes/sun/nio/fs/UTIFileTypeDetector.java 2020-03-09 16:05:50.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,6 @@ } static { - jdk.internal.loader.BootLoader.loadLibrary("nio"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("nio"); } } --- old/src/java.base/share/classes/java/lang/ClassLoader.java 2020-03-09 16:05:50.000000000 -0700 +++ new/src/java.base/share/classes/java/lang/ClassLoader.java 2020-03-09 16:05:50.000000000 -0700 @@ -39,11 +39,8 @@ import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.cert.Certificate; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Deque; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -59,13 +56,14 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import jdk.internal.loader.BuiltinClassLoader; -import jdk.internal.perf.PerfCounter; import jdk.internal.loader.BootLoader; +import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.ClassLoaders; +import jdk.internal.loader.NativeLibrary; +import jdk.internal.loader.NativeLibraries; +import jdk.internal.perf.PerfCounter; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; -import jdk.internal.ref.CleanerFactory; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.util.StaticProperty; @@ -2377,328 +2375,64 @@ return null; } - /** - * The inner class NativeLibrary denotes a loaded native library instance. - * Every classloader contains a vector of loaded native libraries in the - * private field {@code nativeLibraries}. The native libraries loaded - * into the system are entered into the {@code systemNativeLibraries} - * vector. - * - *

Every native library requires a particular version of JNI. This is - * denoted by the private {@code jniVersion} field. This field is set by - * the VM when it loads the library, and used by the VM to pass the correct - * version of JNI to the native methods.

- * - * @see ClassLoader - * @since 1.2 - */ - static class NativeLibrary { - // the class from which the library is loaded, also indicates - // the loader this native library belongs. - final Class fromClass; - // the canonicalized name of the native library. - // or static library name - final String name; - // Indicates if the native library is linked into the VM - final boolean isBuiltin; - - // opaque handle to native library, used in native code. - long handle; - // the version of JNI environment the native library requires. - int jniVersion; - - native boolean load0(String name, boolean isBuiltin); - - native long findEntry(String name); - - NativeLibrary(Class fromClass, String name, boolean isBuiltin) { - this.name = name; - this.fromClass = fromClass; - this.isBuiltin = isBuiltin; - } - - /* - * Loads the native library and registers for cleanup when its - * associated class loader is unloaded - */ - boolean load() { - if (handle != 0) { - throw new InternalError("Native library " + name + " has been loaded"); - } - - if (!load0(name, isBuiltin)) return false; - - // register the class loader for cleanup when unloaded - // builtin class loaders are never unloaded - ClassLoader loader = fromClass.getClassLoader(); - if (loader != null && - loader != getBuiltinPlatformClassLoader() && - loader != getBuiltinAppClassLoader()) { - CleanerFactory.cleaner().register(loader, - new Unloader(name, handle, isBuiltin)); - } - return true; - } - - static boolean loadLibrary(Class fromClass, String name, boolean isBuiltin) { - ClassLoader loader = - fromClass == null ? null : fromClass.getClassLoader(); - - synchronized (loadedLibraryNames) { - Map libs = - loader != null ? loader.nativeLibraries() : systemNativeLibraries(); - if (libs.containsKey(name)) { - return true; - } - - if (loadedLibraryNames.contains(name)) { - throw new UnsatisfiedLinkError("Native Library " + name + - " already loaded in another classloader"); - } - - /* - * When a library is being loaded, JNI_OnLoad function can cause - * another loadLibrary invocation that should succeed. - * - * We use a static stack to hold the list of libraries we are - * loading because this can happen only when called by the - * same thread because this block is synchronous. - * - * If there is a pending load operation for the library, we - * immediately return success; otherwise, we raise - * UnsatisfiedLinkError. - */ - for (NativeLibrary lib : nativeLibraryContext) { - if (name.equals(lib.name)) { - if (loader == lib.fromClass.getClassLoader()) { - return true; - } else { - throw new UnsatisfiedLinkError("Native Library " + - name + " is being loaded in another classloader"); - } - } - } - NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin); - // load the native library - nativeLibraryContext.push(lib); - try { - if (!lib.load()) return false; - } finally { - nativeLibraryContext.pop(); - } - // register the loaded native library - loadedLibraryNames.add(name); - libs.put(name, lib); - } - return true; - } - - // Invoked in the VM to determine the context class in JNI_OnLoad - // and JNI_OnUnload - static Class getFromClass() { - return nativeLibraryContext.peek().fromClass; - } - - // native libraries being loaded - static Deque nativeLibraryContext = new ArrayDeque<>(8); - - /* - * The run() method will be invoked when this class loader becomes - * phantom reachable to unload the native library. - */ - static class Unloader implements Runnable { - // This represents the context when a native library is unloaded - // and getFromClass() will return null, - static final NativeLibrary UNLOADER = - new NativeLibrary(null, "dummy", false); - final String name; - final long handle; - final boolean isBuiltin; - - Unloader(String name, long handle, boolean isBuiltin) { - if (handle == 0) { - throw new IllegalArgumentException( - "Invalid handle for native library " + name); - } - - this.name = name; - this.handle = handle; - this.isBuiltin = isBuiltin; - } - - @Override - public void run() { - synchronized (loadedLibraryNames) { - /* remove the native library name */ - loadedLibraryNames.remove(name); - nativeLibraryContext.push(UNLOADER); - try { - unload(name, isBuiltin, handle); - } finally { - nativeLibraryContext.pop(); - } - - } - } - } - - // JNI FindClass expects the caller class if invoked from JNI_OnLoad - // and JNI_OnUnload is NativeLibrary class - static native void unload(String name, boolean isBuiltin, long handle); - } - - /** - * Holds system and user library paths derived from the - * {@code java.library.path} and {@code sun.boot.library.path} system - * properties. The system properties are eagerly read at bootstrap, then - * lazily parsed on first use to avoid initialization ordering issues. - */ - private static class LibraryPaths { - static final String[] USER = - ClassLoaderHelper.parsePath(StaticProperty.javaLibraryPath()); - static final String[] SYS = - ClassLoaderHelper.parsePath(StaticProperty.sunBootLibraryPath()); - } + private final NativeLibraries libraries = new NativeLibraries(this); // Invoked in the java.lang.Runtime class to implement load and loadLibrary. - static void loadLibrary(Class fromClass, String name, - boolean isAbsolute) { - ClassLoader loader = - (fromClass == null) ? null : fromClass.getClassLoader(); - - if (isAbsolute) { - if (loadLibrary0(fromClass, new File(name))) { - return; - } - throw new UnsatisfiedLinkError("Can't load library: " + name); - } - if (loader != null) { - String libfilename = loader.findLibrary(name); - if (libfilename != null) { - File libfile = new File(libfilename); - if (!libfile.isAbsolute()) { - throw new UnsatisfiedLinkError( + static NativeLibrary loadLibrary(Class fromClass, File file) { + ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); + NativeLibraries libs = loader != null ? loader.libraries : BootLoader.getNativeLibraries(); + NativeLibrary nl = libs.loadLibrary(fromClass, file); + if (nl != null) { + return nl; + } + throw new UnsatisfiedLinkError("Can't load library: " + file); + } + static NativeLibrary loadLibrary(Class fromClass, String name) { + ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); + if (loader == null) { + NativeLibrary nl = BootLoader.getNativeLibraries().loadLibrary(fromClass, name); + if (nl != null) { + return nl; + } + throw new UnsatisfiedLinkError("no " + name + + " in java.library.path: " + StaticProperty.sunBootLibraryPath()); + } + + NativeLibraries libs = loader.libraries; + // First load from the file returned from ClassLoader::findLibrary, if found. + String libfilename = loader.findLibrary(name); + if (libfilename != null) { + File libfile = new File(libfilename); + if (!libfile.isAbsolute()) { + throw new UnsatisfiedLinkError( "ClassLoader.findLibrary failed to return an absolute path: " + libfilename); - } - if (loadLibrary0(fromClass, libfile)) { - return; - } - throw new UnsatisfiedLinkError("Can't load " + libfilename); - } - } - for (String sysPath : LibraryPaths.SYS) { - File libfile = new File(sysPath, System.mapLibraryName(name)); - if (loadLibrary0(fromClass, libfile)) { - return; - } - libfile = ClassLoaderHelper.mapAlternativeName(libfile); - if (libfile != null && loadLibrary0(fromClass, libfile)) { - return; - } - } - if (loader != null) { - for (String userPath : LibraryPaths.USER) { - File libfile = new File(userPath, System.mapLibraryName(name)); - if (loadLibrary0(fromClass, libfile)) { - return; - } - libfile = ClassLoaderHelper.mapAlternativeName(libfile); - if (libfile != null && loadLibrary0(fromClass, libfile)) { - return; - } } + NativeLibrary nl = libs.loadLibrary(fromClass, libfile); + if (nl != null) { + return nl; + } + throw new UnsatisfiedLinkError("Can't load " + libfilename); + } + // Then load from system library path and java library path + NativeLibrary nl = libs.loadLibrary(fromClass, name); + if (nl != null) { + return nl; } + // Oops, it failed throw new UnsatisfiedLinkError("no " + name + - " in java.library.path: " + Arrays.toString(LibraryPaths.USER)); - } - - private static native String findBuiltinLib(String name); - - private static boolean loadLibrary0(Class fromClass, final File file) { - // Check to see if we're attempting to access a static library - String name = findBuiltinLib(file.getName()); - boolean isBuiltin = (name != null); - if (!isBuiltin) { - name = AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - try { - return file.exists() ? file.getCanonicalPath() : null; - } catch (IOException e) { - return null; - } - } - }); - if (name == null) { - return false; - } - } - return NativeLibrary.loadLibrary(fromClass, name, isBuiltin); + " in java.library.path: " + StaticProperty.javaLibraryPath()); } /* * Invoked in the VM class linking code. */ private static long findNative(ClassLoader loader, String entryName) { - Map libs = - loader != null ? loader.nativeLibraries() : systemNativeLibraries(); - if (libs.isEmpty()) - return 0; - - // the native libraries map may be updated in another thread - // when a native library is being loaded. No symbol will be - // searched from it yet. - for (NativeLibrary lib : libs.values()) { - long entry = lib.findEntry(entryName); - if (entry != 0) return entry; - } - return 0; - } - - // All native library names we've loaded. - // This also serves as the lock to obtain nativeLibraries - // and write to nativeLibraryContext. - private static final Set loadedLibraryNames = new HashSet<>(); - - // Native libraries belonging to system classes. - private static volatile Map systemNativeLibraries; - - // Native libraries associated with the class loader. - private volatile Map nativeLibraries; - - /* - * Returns the native libraries map associated with bootstrap class loader - * This method will create the map at the first time when called. - */ - private static Map systemNativeLibraries() { - Map libs = systemNativeLibraries; - if (libs == null) { - synchronized (loadedLibraryNames) { - libs = systemNativeLibraries; - if (libs == null) { - libs = systemNativeLibraries = new ConcurrentHashMap<>(); - } - } - } - return libs; - } - - /* - * Returns the native libraries map associated with this class loader - * This method will create the map at the first time when called. - */ - private Map nativeLibraries() { - Map libs = nativeLibraries; - if (libs == null) { - synchronized (loadedLibraryNames) { - libs = nativeLibraries; - if (libs == null) { - libs = nativeLibraries = new ConcurrentHashMap<>(); - } - } + if (loader == null) { + return BootLoader.getNativeLibraries().lookup(entryName); + } else { + return loader.libraries.lookup(entryName); } - return libs; } // -- Assertion management -- --- old/src/java.base/share/classes/java/lang/Runtime.java 2020-03-09 16:05:51.000000000 -0700 +++ new/src/java.base/share/classes/java/lang/Runtime.java 2020-03-09 16:05:51.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import java.util.StringTokenizer; import jdk.internal.access.SharedSecrets; +import jdk.internal.loader.NativeLibrary; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -733,16 +734,17 @@ load0(Reflection.getCallerClass(), filename); } - void load0(Class fromClass, String filename) { + NativeLibrary load0(Class fromClass, String filename) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkLink(filename); } - if (!(new File(filename).isAbsolute())) { + File file = new File(filename); + if (!file.isAbsolute()) { throw new UnsatisfiedLinkError( "Expecting an absolute path of the library: " + filename); } - ClassLoader.loadLibrary(fromClass, filename, true); + return ClassLoader.loadLibrary(fromClass, file); } /** @@ -795,7 +797,7 @@ loadLibrary0(Reflection.getCallerClass(), libname); } - void loadLibrary0(Class fromClass, String libname) { + NativeLibrary loadLibrary0(Class fromClass, String libname) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkLink(libname); @@ -804,7 +806,7 @@ throw new UnsatisfiedLinkError( "Directory separator should not appear in library name: " + libname); } - ClassLoader.loadLibrary(fromClass, libname, false); + return ClassLoader.loadLibrary(fromClass, libname); } /** --- old/src/java.base/share/classes/java/lang/System.java 2020-03-09 16:05:52.000000000 -0700 +++ new/src/java.base/share/classes/java/lang/System.java 2020-03-09 16:05:52.000000000 -0700 @@ -2276,11 +2276,6 @@ public void setCause(Throwable t, Throwable cause) { t.setCause(cause); } - - public void loadLibrary(Class caller, String library) { - assert library.indexOf(java.io.File.separatorChar) < 0; - ClassLoader.loadLibrary(caller, library, false); - } }); } } --- old/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java 2020-03-09 16:05:53.000000000 -0700 +++ new/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java 2020-03-09 16:05:53.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ * Load net library into runtime. */ static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); } private static volatile boolean checkedReusePort; --- old/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java 2020-03-09 16:05:54.000000000 -0700 +++ new/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java 2020-03-09 16:05:54.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,7 @@ * Load net library into runtime. */ static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); } private static volatile boolean checkedReusePort; --- old/src/java.base/share/classes/java/net/DatagramPacket.java 2020-03-09 16:05:55.000000000 -0700 +++ new/src/java.base/share/classes/java/net/DatagramPacket.java 2020-03-09 16:05:55.000000000 -0700 @@ -56,7 +56,7 @@ * Perform class initialization */ static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); init(); } --- old/src/java.base/share/classes/java/net/InetAddress.java 2020-03-09 16:05:56.000000000 -0700 +++ new/src/java.base/share/classes/java/net/InetAddress.java 2020-03-09 16:05:56.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Objects; import java.util.Scanner; -import java.security.AccessController; import java.io.File; import java.io.ObjectStreamException; import java.io.ObjectStreamField; @@ -317,7 +316,7 @@ } else { preferIPv6Address = PREFER_IPV4_VALUE; } - jdk.internal.loader.BootLoader.loadLibrary("net"); + LoadLibraryAction.privilegedLoadLibrary("net"); SharedSecrets.setJavaNetInetAddressAccess( new JavaNetInetAddressAccess() { public String getOriginalHostName(InetAddress ia) { --- old/src/java.base/share/classes/java/net/NetworkInterface.java 2020-03-09 16:05:57.000000000 -0700 +++ new/src/java.base/share/classes/java/net/NetworkInterface.java 2020-03-09 16:05:56.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ private static final int defaultIndex; /* index of defaultInterface */ static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); init(); defaultInterface = DefaultInterface.getDefault(); --- old/src/java.base/share/classes/java/util/zip/ZipUtils.java 2020-03-09 16:05:57.000000000 -0700 +++ new/src/java.base/share/classes/java/util/zip/ZipUtils.java 2020-03-09 16:05:57.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -276,7 +276,7 @@ * Loads zip native library, if not already laoded */ static void loadLibrary() { - jdk.internal.loader.BootLoader.loadLibrary("zip"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("zip"); } private static final Unsafe unsafe = Unsafe.getUnsafe(); --- old/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java 2020-03-09 16:05:58.000000000 -0700 +++ new/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java 2020-03-09 16:05:58.000000000 -0700 @@ -34,7 +34,6 @@ import java.nio.charset.Charset; import java.security.AccessControlContext; import java.security.ProtectionDomain; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -312,12 +311,4 @@ * @param cause set t's cause to new value */ void setCause(Throwable t, Throwable cause); - - /** - * Privileged System.loadLibrary - * - * @param caller on behalf of which the library is being loaded - * @param library name of the library to load - */ - void loadLibrary(Class caller, String library); } --- old/src/java.base/share/classes/jdk/internal/loader/BootLoader.java 2020-03-09 16:05:59.000000000 -0700 +++ new/src/java.base/share/classes/jdk/internal/loader/BootLoader.java 2020-03-09 16:05:59.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,10 @@ private static final ConcurrentHashMap CLASS_LOADER_VALUE_MAP = new ConcurrentHashMap<>(); + // native libraries loaded by the boot class loader + private static final NativeLibraries NATIVE_LIBS + = new NativeLibraries(null); + /** * Returns the unnamed module for the boot loader. */ @@ -93,6 +97,13 @@ } /** + * Returns NativeLibraries for the boot class loader. + */ + public static NativeLibraries getNativeLibraries() { + return NATIVE_LIBS; + } + + /** * Returns {@code true} if there is a class path associated with the * BootLoader. */ @@ -129,23 +140,6 @@ } /** - * Loads a library from the system path. - */ - public static void loadLibrary(String library) { - if (System.getSecurityManager() == null) { - SharedSecrets.getJavaLangAccess().loadLibrary(BootLoader.class, library); - } else { - AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Void run() { - SharedSecrets.getJavaLangAccess().loadLibrary(BootLoader.class, library); - return null; - } - }); - } - } - - /** * Returns a URL to a resource in a module defined to the boot loader. */ public static URL findResource(String mn, String name) throws IOException { --- old/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2020-03-09 16:06:00.000000000 -0700 +++ new/src/java.base/share/classes/sun/net/sdp/SdpSupport.java 2020-03-09 16:06:00.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,6 @@ private static native void convert0(int fd) throws IOException; static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); } } --- old/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java 2020-03-09 16:06:01.000000000 -0700 +++ new/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java 2020-03-09 16:06:00.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,7 @@ return NetProperties.getBoolean(key); }}); if (b != null && b.booleanValue()) { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); hasSystemProxies = init(); } } --- old/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2020-03-09 16:06:02.000000000 -0700 +++ new/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2020-03-09 16:06:01.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -432,8 +432,8 @@ public static void load() { } static { - jdk.internal.loader.BootLoader.loadLibrary("net"); - jdk.internal.loader.BootLoader.loadLibrary("nio"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("nio"); initIDs(); IOV_MAX = iovMax(); --- old/src/java.base/share/native/libjava/ClassLoader.c 2020-03-09 16:06:02.000000000 -0700 +++ new/src/java.base/share/native/libjava/ClassLoader.c 2020-03-09 16:06:02.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ #include "jvm.h" #include "check_classname.h" #include "java_lang_ClassLoader.h" -#include "java_lang_ClassLoader_NativeLibrary.h" #include static JNINativeMethod methods[] = { @@ -254,266 +253,3 @@ return JVM_FindLoadedClass(env, loader, name); } } - -static jfieldID handleID; -static jfieldID jniVersionID; -static void *procHandle; - -static jboolean initIDs(JNIEnv *env) -{ - if (handleID == 0) { - jclass this = - (*env)->FindClass(env, "java/lang/ClassLoader$NativeLibrary"); - if (this == 0) - return JNI_FALSE; - handleID = (*env)->GetFieldID(env, this, "handle", "J"); - if (handleID == 0) - return JNI_FALSE; - jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); - if (jniVersionID == 0) - return JNI_FALSE; - procHandle = getProcessHandle(); - } - return JNI_TRUE; -} - -typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); -typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); - -/* - * Support for finding JNI_On(Un)Load_ if it exists. - * If cname == NULL then just find normal JNI_On(Un)Load entry point - */ -static void *findJniFunction(JNIEnv *env, void *handle, - const char *cname, jboolean isLoad) { - const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; - const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; - const char **syms; - int symsLen; - void *entryName = NULL; - char *jniFunctionName; - int i; - size_t len; - - // Check for JNI_On(Un)Load<_libname> function - if (isLoad) { - syms = onLoadSymbols; - symsLen = sizeof(onLoadSymbols) / sizeof(char *); - } else { - syms = onUnloadSymbols; - symsLen = sizeof(onUnloadSymbols) / sizeof(char *); - } - for (i = 0; i < symsLen; i++) { - // cname + sym + '_' + '\0' - if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) > - FILENAME_MAX) { - goto done; - } - jniFunctionName = malloc(len); - if (jniFunctionName == NULL) { - JNU_ThrowOutOfMemoryError(env, NULL); - goto done; - } - buildJniFunctionName(syms[i], cname, jniFunctionName); - entryName = JVM_FindLibraryEntry(handle, jniFunctionName); - free(jniFunctionName); - if(entryName) { - break; - } - } - - done: - return entryName; -} - -/* - * Class: java_lang_ClassLoader_NativeLibrary - * Method: load0 - * Signature: (Ljava/lang/String;Z)Z - */ -JNIEXPORT jboolean JNICALL -Java_java_lang_ClassLoader_00024NativeLibrary_load0 - (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin) -{ - const char *cname; - jint jniVersion; - jthrowable cause; - void * handle; - jboolean loaded = JNI_FALSE; - - if (!initIDs(env)) - return JNI_FALSE; - - cname = JNU_GetStringPlatformChars(env, name, 0); - if (cname == 0) - return JNI_FALSE; - handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname); - if (handle) { - JNI_OnLoad_t JNI_OnLoad; - JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle, - isBuiltin ? cname : NULL, - JNI_TRUE); - if (JNI_OnLoad) { - JavaVM *jvm; - (*env)->GetJavaVM(env, &jvm); - jniVersion = (*JNI_OnLoad)(jvm, NULL); - } else { - jniVersion = 0x00010001; - } - - cause = (*env)->ExceptionOccurred(env); - if (cause) { - (*env)->ExceptionClear(env); - (*env)->Throw(env, cause); - if (!isBuiltin) { - JVM_UnloadLibrary(handle); - } - goto done; - } - - if (!JVM_IsSupportedJNIVersion(jniVersion) || - (isBuiltin && jniVersion < JNI_VERSION_1_8)) { - char msg[256]; - jio_snprintf(msg, sizeof(msg), - "unsupported JNI version 0x%08X required by %s", - jniVersion, cname); - JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg); - if (!isBuiltin) { - JVM_UnloadLibrary(handle); - } - goto done; - } - (*env)->SetIntField(env, this, jniVersionID, jniVersion); - } else { - cause = (*env)->ExceptionOccurred(env); - if (cause) { - (*env)->ExceptionClear(env); - (*env)->SetLongField(env, this, handleID, (jlong)0); - (*env)->Throw(env, cause); - } - goto done; - } - (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle)); - loaded = JNI_TRUE; - - done: - JNU_ReleaseStringPlatformChars(env, name, cname); - return loaded; -} - -/* - * Class: java_lang_ClassLoader_NativeLibrary - * Method: unload - * Signature: (Ljava/lang/String;ZJ)V - */ -JNIEXPORT void JNICALL -Java_java_lang_ClassLoader_00024NativeLibrary_unload -(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jlong address) -{ - const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; - void *handle; - JNI_OnUnload_t JNI_OnUnload; - const char *cname; - - if (!initIDs(env)) - return; - cname = JNU_GetStringPlatformChars(env, name, 0); - if (cname == NULL) { - return; - } - handle = jlong_to_ptr(address); - JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle, - isBuiltin ? cname : NULL, - JNI_FALSE); - if (JNI_OnUnload) { - JavaVM *jvm; - (*env)->GetJavaVM(env, &jvm); - (*JNI_OnUnload)(jvm, NULL); - } - if (!isBuiltin) { - JVM_UnloadLibrary(handle); - } - JNU_ReleaseStringPlatformChars(env, name, cname); -} - -/* - * Class: java_lang_ClassLoader_NativeLibrary - * Method: findEntry - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL -Java_java_lang_ClassLoader_00024NativeLibrary_findEntry - (JNIEnv *env, jobject this, jstring name) -{ - jlong handle; - const char *cname; - jlong res; - - if (!initIDs(env)) - return jlong_zero; - - handle = (*env)->GetLongField(env, this, handleID); - cname = (*env)->GetStringUTFChars(env, name, 0); - if (cname == 0) - return jlong_zero; - res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname)); - (*env)->ReleaseStringUTFChars(env, name, cname); - return res; -} -/* - * Class: java_lang_ClassLoader - * Method: findBuiltinLib - * Signature: (Ljava/lang/String;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL -Java_java_lang_ClassLoader_findBuiltinLib - (JNIEnv *env, jclass cls, jstring name) -{ - const char *cname; - char *libName; - size_t prefixLen = strlen(JNI_LIB_PREFIX); - size_t suffixLen = strlen(JNI_LIB_SUFFIX); - size_t len; - jstring lib; - void *ret; - const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; - - if (name == NULL) { - JNU_ThrowInternalError(env, "NULL filename for native library"); - return NULL; - } - procHandle = getProcessHandle(); - cname = JNU_GetStringPlatformChars(env, name, 0); - if (cname == NULL) { - return NULL; - } - // Copy name Skipping PREFIX - len = strlen(cname); - if (len <= (prefixLen+suffixLen)) { - JNU_ReleaseStringPlatformChars(env, name, cname); - return NULL; - } - libName = malloc(len + 1); //+1 for null if prefix+suffix == 0 - if (libName == NULL) { - JNU_ReleaseStringPlatformChars(env, name, cname); - JNU_ThrowOutOfMemoryError(env, NULL); - return NULL; - } - if (len > prefixLen) { - strcpy(libName, cname+prefixLen); - } - JNU_ReleaseStringPlatformChars(env, name, cname); - - // Strip SUFFIX - libName[strlen(libName)-suffixLen] = '\0'; - - // Check for JNI_OnLoad_libname function - ret = findJniFunction(env, procHandle, libName, JNI_TRUE); - if (ret != NULL) { - lib = JNU_NewStringPlatform(env, libName); - free(libName); - return lib; - } - free(libName); - return NULL; -} --- old/src/java.base/unix/classes/sun/net/PortConfig.java 2020-03-09 16:06:03.000000000 -0700 +++ new/src/java.base/unix/classes/sun/net/PortConfig.java 2020-03-09 16:06:03.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ private PortConfig() {} static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); String os = GetPropertyAction.privilegedGetProperty("os.name"); if (os.startsWith("Linux")) { defaultLower = 32768; --- old/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java 2020-03-09 16:06:04.000000000 -0700 +++ new/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java 2020-03-09 16:06:04.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,7 +259,7 @@ static native String fallbackDomain0(); static { - jdk.internal.loader.BootLoader.loadLibrary("net"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("net"); } } --- old/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java 2020-03-09 16:06:05.000000000 -0700 +++ new/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java 2020-03-09 16:06:05.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -626,7 +626,7 @@ throws UnixException; static { - jdk.internal.loader.BootLoader.loadLibrary("nio"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("nio"); } } --- old/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java 2020-03-09 16:06:06.000000000 -0700 +++ new/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java 2020-03-09 16:06:06.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -650,7 +650,7 @@ private static native int init(); static { - jdk.internal.loader.BootLoader.loadLibrary("nio"); + sun.security.action.LoadLibraryAction.privilegedLoadLibrary("nio"); capabilities = init(); } } --- old/test/jdk/java/lang/ClassLoader/LibraryPathProperty.java 2020-03-09 16:06:07.000000000 -0700 +++ new/test/jdk/java/lang/ClassLoader/LibraryPathProperty.java 2020-03-09 16:06:07.000000000 -0700 @@ -28,7 +28,7 @@ * Quoted entries should get unquoted on Windows. * Empty entries should be replaced with dot. * @library /test/lib - * @modules java.base/java.lang:open + * @modules java.base/jdk.internal.loader:open * @build jdk.test.lib.Platform * @run main LibraryPathProperty */ @@ -44,7 +44,7 @@ static Method method; public static void main(String[] args) throws Throwable { - Class klass = Class.forName("java.lang.ClassLoaderHelper"); + Class klass = Class.forName("jdk.internal.loader.ClassLoaderHelper"); method = klass.getDeclaredMethod("parsePath", String.class); method.setAccessible(true); --- old/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java 2020-03-09 16:06:08.000000000 -0700 +++ /dev/null 2020-03-09 16:06:08.000000000 -0700 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.File; -import java.util.ArrayList; - -class ClassLoaderHelper { - - private ClassLoaderHelper() {} - - /** - * Returns an alternate path name for the given file - * such that if the original pathname did not exist, then the - * file may be located at the alternate location. - * For mac, this replaces the final .dylib suffix with .jnilib - */ - static File mapAlternativeName(File lib) { - String name = lib.toString(); - int index = name.lastIndexOf('.'); - if (index < 0) { - return null; - } - return new File(name.substring(0, index) + ".jnilib"); - } - - /** - * Parse a PATH env variable. - * - * Empty elements will be replaced by dot. - */ - static String[] parsePath(String ldPath) { - char ps = File.pathSeparatorChar; - ArrayList paths = new ArrayList<>(); - int pathStart = 0; - int pathEnd; - while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) { - paths.add((pathStart < pathEnd) ? - ldPath.substring(pathStart, pathEnd) : "."); - pathStart = pathEnd + 1; - } - int ldLen = ldPath.length(); - paths.add((pathStart < ldLen) ? - ldPath.substring(pathStart, ldLen) : "."); - return paths.toArray(new String[paths.size()]); - } -} --- /dev/null 2020-03-09 16:06:08.000000000 -0700 +++ new/src/java.base/macosx/classes/jdk/internal/loader/ClassLoaderHelper.java 2020-03-09 16:06:07.000000000 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.loader; + +import java.io.File; +import java.util.ArrayList; + +class ClassLoaderHelper { + + private ClassLoaderHelper() {} + + /** + * Returns an alternate path name for the given file + * such that if the original pathname did not exist, then the + * file may be located at the alternate location. + * For mac, this replaces the final .dylib suffix with .jnilib + */ + static File mapAlternativeName(File lib) { + String name = lib.toString(); + int index = name.lastIndexOf('.'); + if (index < 0) { + return null; + } + return new File(name.substring(0, index) + ".jnilib"); + } + + /** + * Parse a PATH env variable. + * + * Empty elements will be replaced by dot. + */ + static String[] parsePath(String ldPath) { + char ps = File.pathSeparatorChar; + ArrayList paths = new ArrayList<>(); + int pathStart = 0; + int pathEnd; + while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) { + paths.add((pathStart < pathEnd) ? + ldPath.substring(pathStart, pathEnd) : "."); + pathStart = pathEnd + 1; + } + int ldLen = ldPath.length(); + paths.add((pathStart < ldLen) ? + ldPath.substring(pathStart, ldLen) : "."); + return paths.toArray(new String[paths.size()]); + } +} --- /dev/null 2020-03-09 16:06:08.000000000 -0700 +++ new/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java 2020-03-09 16:06:08.000000000 -0700 @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.loader; + +import jdk.internal.ref.CleanerFactory; +import jdk.internal.util.StaticProperty; + +import java.io.File; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Native libraries are loaded via {@link System#loadLibrary(String)}, + * {@link System#load(String)}, {@link Runtime#loadLibrary(String)} and + * {@link Runtime#load(String)}. They are caller-sensitive. + * + * Each class loader has a NativeLibraries instance to register all of its + * loaded native libraries. System::loadLibrary (and other APIs) only + * allows a native library to be loaded by one class loader, i.e. one + * NativeLibraries instance. Any attempt to load a native library that + * has already been loaded by a class loader with another class loader + * will fail. + */ +public final class NativeLibraries { + + private final Map libraries = new ConcurrentHashMap<>(); + private final ClassLoader loader; + private final Class caller; // may be null. If not null, this is used as + // fromClass as a fast-path. See loadLibrary(String name). + private final boolean searchJavaLibraryPath; + + public NativeLibraries(ClassLoader loader) { + this(loader, null, loader != null ? true : false); + } + public NativeLibraries(ClassLoader loader, Class caller, boolean searchJavaLibraryPath) { + if (caller != null && caller.getClassLoader() != loader) { + throw new IllegalArgumentException(caller.getName() + " must be defined by " + loader); + } + this.loader = loader; + this.caller = caller; + this.searchJavaLibraryPath = searchJavaLibraryPath; + } + + /* + * Look up the address of the given symbol name from the native libraries + * loaded in this NativeLibraries instance. + */ + public long lookup(String name) { + if (libraries.isEmpty()) + return 0; + + // the native libraries map may be updated in another thread + // when a native library is being loaded. No symbol will be + // searched from it yet. + for (NativeLibrary lib : libraries.values()) { + long entry = lib.findEntry(name); + if (entry != 0) return entry; + } + return 0; + } + + /* + * Load a native library from the given file. Returns null if file does not exist. + * + * @param fromClass the caller class calling System::loadLibrary + * @param file the path of the native library + * @throws UnsatisfiedLinkError if any error in loading the native library + */ + public NativeLibrary loadLibrary(Class fromClass, File file) { + // Check to see if we're attempting to access a static library + String name = findBuiltinLib(file.getName()); + boolean isBuiltin = (name != null); + if (!isBuiltin) { + name = AccessController.doPrivileged(new PrivilegedAction<>() { + public String run() { + try { + return file.exists() ? file.getCanonicalPath() : null; + } catch (IOException e) { + return null; + } + } + }); + if (name == null) { + return null; + } + } + return loadLibrary(fromClass, name, isBuiltin); + } + + /** + * Returns a NativeLibrary of the given name. + * + * @param fromClass the caller class calling System::loadLibrary + * @param name library name + * @param isBuiltin built-in library + * @throws UnsatisfiedLinkError if the native library has already been loaded + * and registered in another NativeLibraries + */ + private NativeLibrary loadLibrary(Class fromClass, String name, boolean isBuiltin) { + ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); + if (this.loader != loader) { + throw new InternalError(fromClass.getName() + " not allowed to load library"); + } + + synchronized (loadedLibraryNames) { + // find if this library has already been loaded and registered in this NativeLibraries + NativeLibrary cached = libraries.get(name); + if (cached != null) { + return cached; + } + + // cannot be loaded by other class loaders + if (loadedLibraryNames.contains(name)) { + throw new UnsatisfiedLinkError("Native Library " + name + + " already loaded in another classloader"); + } + + /* + * When a library is being loaded, JNI_OnLoad function can cause + * another loadLibrary invocation that should succeed. + * + * We use a static stack to hold the list of libraries we are + * loading because this can happen only when called by the + * same thread because this block is synchronous. + * + * If there is a pending load operation for the library, we + * immediately return success; otherwise, we raise + * UnsatisfiedLinkError. + */ + for (NativeLibraryImpl lib : nativeLibraryContext) { + if (name.equals(lib.name())) { + if (loader == lib.fromClass.getClassLoader()) { + return lib; + } else { + throw new UnsatisfiedLinkError("Native Library " + + name + " is being loaded in another classloader"); + } + } + } + + NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin); + // load the native library + nativeLibraryContext.push(lib); + try { + if (!lib.open()) return null; + } finally { + nativeLibraryContext.pop(); + } + // register the loaded native library + loadedLibraryNames.add(name); + libraries.put(name, lib); + return lib; + } + } + + /** + * Loads a native library from the system library path and java library path. + * + * @param name library name + * + * @throws UnsatisfiedLinkError if the native library has already been loaded + * and registered in another NativeLibraries + */ + public NativeLibrary loadLibrary(String name) { + assert caller != null; + return loadLibrary(caller, name); + } + + /** + * Loads a native library from the system library path and java library path. + * + * @param name library name + * @param fromClass the caller class calling System::loadLibrary + * + * @throws UnsatisfiedLinkError if the native library has already been loaded + * and registered in another NativeLibraries + */ + public NativeLibrary loadLibrary(Class fromClass, String name) { + NativeLibrary lib = findFromPaths(LibraryPaths.SYS_PATHS, fromClass, name); + if (lib == null && searchJavaLibraryPath) { + lib = findFromPaths(LibraryPaths.USER_PATHS, fromClass, name); + } + return lib; + } + + private NativeLibrary findFromPaths(String[] paths, Class fromClass, String name) { + for (String path : paths) { + File libfile = new File(path, System.mapLibraryName(name)); + NativeLibrary nl = loadLibrary(fromClass, libfile); + if (nl != null) { + return nl; + } + libfile = ClassLoaderHelper.mapAlternativeName(libfile); + if (libfile != null) { + nl = loadLibrary(fromClass, libfile); + if (nl != null) { + return nl; + } + } + } + return null; + } + + /** + * NativeLibraryImpl denotes a loaded native library instance. + * Each NativeLibraries contains a map of loaded native libraries in the + * private field {@code libraries}. + * + * Every native library requires a particular version of JNI. This is + * denoted by the private {@code jniVersion} field. This field is set by + * the VM when it loads the library, and used by the VM to pass the correct + * version of JNI to the native methods. + */ + static class NativeLibraryImpl implements NativeLibrary { + // the class from which the library is loaded, also indicates + // the loader this native library belongs. + final Class fromClass; + // the canonicalized name of the native library. + // or static library name + final String name; + // Indicates if the native library is linked into the VM + final boolean isBuiltin; + + // opaque handle to native library, used in native code. + long handle; + // the version of JNI environment the native library requires. + int jniVersion; + + NativeLibraryImpl(Class fromClass, String name, boolean isBuiltin) { + this.fromClass = fromClass; + this.name = name; + this.isBuiltin = isBuiltin; + } + + @Override + public String name() { + return name; + } + + @Override + public long findEntry(String name) { + return findEntry0(this, name); + } + + /* + * Loads the native library and registers for cleanup when its + * associated class loader is unloaded + */ + boolean open() { + if (handle != 0) { + throw new InternalError("Native library " + name + " has been loaded"); + } + + if (!load(this, name, isBuiltin)) return false; + + // register the class loader for cleanup when unloaded + // builtin class loaders are never unloaded + ClassLoader loader = fromClass != null ? fromClass.getClassLoader() : null; + if (loader != null && + loader != ClassLoaders.platformClassLoader() && + loader != ClassLoaders.appClassLoader()) { + CleanerFactory.cleaner().register(loader, new Unloader(name, handle, isBuiltin)); + } + return true; + } + } + + /* + * The run() method will be invoked when this class loader becomes + * phantom reachable to unload the native library. + */ + static class Unloader implements Runnable { + // This represents the context when a native library is unloaded + // and getFromClass() will return null, + static final NativeLibraryImpl UNLOADER = + new NativeLibraryImpl(null, "dummy", false); + + final String name; + final long handle; + final boolean isBuiltin; + + Unloader(String name, long handle, boolean isBuiltin) { + if (handle == 0) { + throw new IllegalArgumentException( + "Invalid handle for native library " + name); + } + + this.name = name; + this.handle = handle; + this.isBuiltin = isBuiltin; + } + + @Override + public void run() { + synchronized (NativeLibraries.loadedLibraryNames) { + /* remove the native library name */ + NativeLibraries.loadedLibraryNames.remove(name); + NativeLibraries.nativeLibraryContext.push(UNLOADER); + try { + unload(name, isBuiltin, handle); + } finally { + NativeLibraries.nativeLibraryContext.pop(); + } + } + } + } + + /* + * Holds system and user library paths derived from the + * {@code java.library.path} and {@code sun.boot.library.path} system + * properties. The system properties are eagerly read at bootstrap, then + * lazily parsed on first use to avoid initialization ordering issues. + */ + static class LibraryPaths { + // The paths searched for libraries + static final String[] SYS_PATHS = ClassLoaderHelper.parsePath(StaticProperty.sunBootLibraryPath()); + static final String[] USER_PATHS = ClassLoaderHelper.parsePath(StaticProperty.javaLibraryPath()); + } + + // All native libraries we've loaded. + // This also serves as the lock to obtain nativeLibraries + // and write to nativeLibraryContext. + private static final Set loadedLibraryNames = new HashSet<>(); + + // native libraries being loaded + private static Deque nativeLibraryContext = new ArrayDeque<>(8); + + // Invoked in the VM to determine the context class in JNI_OnLoad + // and JNI_OnUnload + private static Class getFromClass() { + if (nativeLibraryContext.isEmpty()) { // only default library + return Object.class; + } + return nativeLibraryContext.peek().fromClass; + } + + // JNI FindClass expects the caller class if invoked from JNI_OnLoad + // and JNI_OnUnload is NativeLibrary class + private static native boolean load(NativeLibraryImpl impl, String name, boolean isBuiltin); + private static native void unload(String name, boolean isBuiltin, long handle); + private static native String findBuiltinLib(String name); + private static native long findEntry0(NativeLibraryImpl lib, String name); +} --- /dev/null 2020-03-09 16:06:09.000000000 -0700 +++ new/src/java.base/share/classes/jdk/internal/loader/NativeLibrary.java 2020-03-09 16:06:09.000000000 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.loader; + +/** + * NativeLibrary represents a loaded native library instance. + */ +public interface NativeLibrary { + String name(); + + /* + * Finds the address of the entry of the given name. Returns 0 + * if not found. + */ + long findEntry(String name); + + /* + * Finds the address of the entry of the given name. + * + * @throws NoSuchMethodException if the named entry is not found. + */ + default long lookup(String name) throws NoSuchMethodException { + long addr = findEntry(name); + if (0 == addr) { + throw new NoSuchMethodException("Cannot find symbol " + name + " in library " + name()); + } + return addr; + } +} --- /dev/null 2020-03-09 16:06:10.000000000 -0700 +++ new/src/java.base/share/classes/sun/security/action/LoadLibraryAction.java 2020-03-09 16:06:10.000000000 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.action; + +import jdk.internal.loader.BootLoader; + +import java.io.*; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A convenience class for loading a native library as a privileged action. + */ +public class LoadLibraryAction implements PrivilegedAction { + private final String name; + LoadLibraryAction(String name) { + this.name = name; + } + + @Override + public Void run() { + BootLoader.getNativeLibraries().loadLibrary(name); + return null; + } + + /** + * Convenience method to load a native library without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * Note: This should only be used by modules defined to the boot loader. + * + * @param name the library name + */ + public static void privilegedLoadLibrary(String name) { + assert name.indexOf(File.separatorChar) < 0; + if (System.getSecurityManager() == null) { + BootLoader.getNativeLibraries().loadLibrary(name); + } else { + AccessController.doPrivileged(new LoadLibraryAction(name)); + } + } +} --- /dev/null 2020-03-09 16:06:11.000000000 -0700 +++ new/src/java.base/share/native/libjava/NativeLibraries.c 2020-03-09 16:06:10.000000000 -0700 @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "jvm.h" +#include "jdk_internal_loader_NativeLibraries.h" +#include + +typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); +typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); + +static jfieldID handleID; +static jfieldID jniVersionID; +static void *procHandle; + + +static jboolean initIDs(JNIEnv *env) +{ + if (handleID == 0) { + jclass this = + (*env)->FindClass(env, "jdk/internal/loader/NativeLibraries$NativeLibraryImpl"); + if (this == 0) + return JNI_FALSE; + handleID = (*env)->GetFieldID(env, this, "handle", "J"); + if (handleID == 0) + return JNI_FALSE; + jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); + if (jniVersionID == 0) + return JNI_FALSE; + procHandle = getProcessHandle(); + } + return JNI_TRUE; +} + + +/* + * Support for finding JNI_On(Un)Load_ if it exists. + * If cname == NULL then just find normal JNI_On(Un)Load entry point + */ +static void *findJniFunction(JNIEnv *env, void *handle, + const char *cname, jboolean isLoad) { + const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; + const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; + const char **syms; + int symsLen; + void *entryName = NULL; + char *jniFunctionName; + int i; + size_t len; + + // Check for JNI_On(Un)Load<_libname> function + if (isLoad) { + syms = onLoadSymbols; + symsLen = sizeof(onLoadSymbols) / sizeof(char *); + } else { + syms = onUnloadSymbols; + symsLen = sizeof(onUnloadSymbols) / sizeof(char *); + } + for (i = 0; i < symsLen; i++) { + // cname + sym + '_' + '\0' + if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) > + FILENAME_MAX) { + goto done; + } + jniFunctionName = malloc(len); + if (jniFunctionName == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + goto done; + } + buildJniFunctionName(syms[i], cname, jniFunctionName); + entryName = JVM_FindLibraryEntry(handle, jniFunctionName); + free(jniFunctionName); + if(entryName) { + break; + } + } + + done: + return entryName; +} + +/* + * Class: jdk_internal_loader_NativeLibraries + * Method: load + * Signature: (Ljava/lang/String;Z)Z + */ +JNIEXPORT jboolean JNICALL +Java_jdk_internal_loader_NativeLibraries_load + (JNIEnv *env, jobject this, jobject lib, jstring name, jboolean isBuiltin) +{ + const char *cname; + jint jniVersion; + jthrowable cause; + void * handle; + jboolean loaded = JNI_FALSE; + + if (!initIDs(env)) + return JNI_FALSE; + + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == 0) + return JNI_FALSE; + handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname); + if (handle) { + JNI_OnLoad_t JNI_OnLoad; + JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_TRUE); + if (JNI_OnLoad) { + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + jniVersion = (*JNI_OnLoad)(jvm, NULL); + } else { + jniVersion = 0x00010001; + } + + cause = (*env)->ExceptionOccurred(env); + if (cause) { + (*env)->ExceptionClear(env); + (*env)->Throw(env, cause); + if (!isBuiltin) { + JVM_UnloadLibrary(handle); + } + goto done; + } + + if (!JVM_IsSupportedJNIVersion(jniVersion) || + (isBuiltin && jniVersion < JNI_VERSION_1_8)) { + char msg[256]; + jio_snprintf(msg, sizeof(msg), + "unsupported JNI version 0x%08X required by %s", + jniVersion, cname); + JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg); + if (!isBuiltin) { + JVM_UnloadLibrary(handle); + } + goto done; + } + (*env)->SetIntField(env, lib, jniVersionID, jniVersion); + } else { + cause = (*env)->ExceptionOccurred(env); + if (cause) { + (*env)->ExceptionClear(env); + (*env)->SetLongField(env, lib, handleID, (jlong)0); + (*env)->Throw(env, cause); + } + goto done; + } + (*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle)); + loaded = JNI_TRUE; + + done: + JNU_ReleaseStringPlatformChars(env, name, cname); + return loaded; +} + +/* + * Class: jdk_internal_loader_NativeLibraries + * Method: unload + * Signature: (Ljava/lang/String;ZJ)V + */ +JNIEXPORT void JNICALL +Java_jdk_internal_loader_NativeLibraries_unload +(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jlong address) +{ + const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; + void *handle; + JNI_OnUnload_t JNI_OnUnload; + const char *cname; + + if (!initIDs(env)) + return; + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == NULL) { + return; + } + handle = jlong_to_ptr(address); + JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_FALSE); + if (JNI_OnUnload) { + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + (*JNI_OnUnload)(jvm, NULL); + } + if (!isBuiltin) { + JVM_UnloadLibrary(handle); + } + JNU_ReleaseStringPlatformChars(env, name, cname); +} + + +/* + * Class: jdk_internal_loader_NativeLibraries + * Method: findEntry0 + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL +Java_jdk_internal_loader_NativeLibraries_findEntry0 + (JNIEnv *env, jobject this, jobject lib, jstring name) +{ + jlong handle; + const char *cname; + jlong res; + + if (!initIDs(env)) + return jlong_zero; + + handle = (*env)->GetLongField(env, lib, handleID); + cname = (*env)->GetStringUTFChars(env, name, 0); + if (cname == 0) + return jlong_zero; + res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname)); + (*env)->ReleaseStringUTFChars(env, name, cname); + return res; +} + +/* + * Class: jdk_internal_loader_NativeLibraries + * Method: findBuiltinLib + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_jdk_internal_loader_NativeLibraries_findBuiltinLib + (JNIEnv *env, jclass cls, jstring name) +{ + const char *cname; + char *libName; + size_t prefixLen = strlen(JNI_LIB_PREFIX); + size_t suffixLen = strlen(JNI_LIB_SUFFIX); + size_t len; + jstring lib; + void *ret; + const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; + + if (name == NULL) { + JNU_ThrowInternalError(env, "NULL filename for native library"); + return NULL; + } + procHandle = getProcessHandle(); + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == NULL) { + return NULL; + } + // Copy name Skipping PREFIX + len = strlen(cname); + if (len <= (prefixLen+suffixLen)) { + JNU_ReleaseStringPlatformChars(env, name, cname); + return NULL; + } + libName = malloc(len + 1); //+1 for null if prefix+suffix == 0 + if (libName == NULL) { + JNU_ReleaseStringPlatformChars(env, name, cname); + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } + if (len > prefixLen) { + strcpy(libName, cname+prefixLen); + } + JNU_ReleaseStringPlatformChars(env, name, cname); + + // Strip SUFFIX + libName[strlen(libName)-suffixLen] = '\0'; + + // Check for JNI_OnLoad_libname function + ret = findJniFunction(env, procHandle, libName, JNI_TRUE); + if (ret != NULL) { + lib = JNU_NewStringPlatform(env, libName); + free(libName); + return lib; + } + free(libName); + return NULL; +} + + --- old/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java 2020-03-09 16:06:11.000000000 -0700 +++ /dev/null 2020-03-09 16:06:11.000000000 -0700 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.File; -import java.util.ArrayList; - -class ClassLoaderHelper { - - private ClassLoaderHelper() {} - - /** - * Returns an alternate path name for the given file - * such that if the original pathname did not exist, then the - * file may be located at the alternate location. - * For most platforms, this behavior is not supported and returns null. - */ - static File mapAlternativeName(File lib) { - return null; - } - - /** - * Parse a PATH env variable. - * - * Empty elements will be replaced by dot. - */ - static String[] parsePath(String ldPath) { - char ps = File.pathSeparatorChar; - ArrayList paths = new ArrayList<>(); - int pathStart = 0; - int pathEnd; - while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) { - paths.add((pathStart < pathEnd) ? - ldPath.substring(pathStart, pathEnd) : "."); - pathStart = pathEnd + 1; - } - int ldLen = ldPath.length(); - paths.add((pathStart < ldLen) ? - ldPath.substring(pathStart, ldLen) : "."); - return paths.toArray(new String[paths.size()]); - } -} --- /dev/null 2020-03-09 16:06:11.000000000 -0700 +++ new/src/java.base/unix/classes/jdk/internal/loader/ClassLoaderHelper.java 2020-03-09 16:06:11.000000000 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.loader; + +import java.io.File; +import java.util.ArrayList; + +class ClassLoaderHelper { + + private ClassLoaderHelper() {} + + /** + * Returns an alternate path name for the given file + * such that if the original pathname did not exist, then the + * file may be located at the alternate location. + * For most platforms, this behavior is not supported and returns null. + */ + static File mapAlternativeName(File lib) { + return null; + } + + /** + * Parse a PATH env variable. + * + * Empty elements will be replaced by dot. + */ + static String[] parsePath(String ldPath) { + char ps = File.pathSeparatorChar; + ArrayList paths = new ArrayList<>(); + int pathStart = 0; + int pathEnd; + while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) { + paths.add((pathStart < pathEnd) ? + ldPath.substring(pathStart, pathEnd) : "."); + pathStart = pathEnd + 1; + } + int ldLen = ldPath.length(); + paths.add((pathStart < ldLen) ? + ldPath.substring(pathStart, ldLen) : "."); + return paths.toArray(new String[paths.size()]); + } +} --- old/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java 2020-03-09 16:06:12.000000000 -0700 +++ /dev/null 2020-03-09 16:06:12.000000000 -0700 @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -import java.io.File; - -class ClassLoaderHelper { - - private ClassLoaderHelper() {} - - /** - * Returns an alternate path name for the given file - * such that if the original pathname did not exist, then the - * file may be located at the alternate location. - * For most platforms, this behavior is not supported and returns null. - */ - static File mapAlternativeName(File lib) { - return null; - } - - /** - * Parse a PATH env variable. Windows allows quoted elements in a PATH, - * so special care needs to be taken. - * - * Empty elements will be replaced by dot. - */ - static String[] parsePath(String ldPath) { - int ldLen = ldPath.length(); - char ps = File.pathSeparatorChar; - int psCount = 0; - - if (ldPath.indexOf('\"') >= 0) { - // First, remove quotes put around quoted parts of paths. - // Second, use a quotation mark as a new path separator. - // This will preserve any quoted old path separators. - char[] buf = new char[ldLen]; - int bufLen = 0; - for (int i = 0; i < ldLen; ++i) { - char ch = ldPath.charAt(i); - if (ch == '\"') { - while (++i < ldLen && - (ch = ldPath.charAt(i)) != '\"') { - buf[bufLen++] = ch; - } - } else { - if (ch == ps) { - psCount++; - ch = '\"'; - } - buf[bufLen++] = ch; - } - } - ldPath = new String(buf, 0, bufLen); - ldLen = bufLen; - ps = '\"'; - } else { - for (int i = ldPath.indexOf(ps); i >= 0; - i = ldPath.indexOf(ps, i + 1)) { - psCount++; - } - } - - String[] paths = new String[psCount + 1]; - int pathStart = 0; - for (int j = 0; j < psCount; ++j) { - int pathEnd = ldPath.indexOf(ps, pathStart); - paths[j] = (pathStart < pathEnd) ? - ldPath.substring(pathStart, pathEnd) : "."; - pathStart = pathEnd + 1; - } - paths[psCount] = (pathStart < ldLen) ? - ldPath.substring(pathStart, ldLen) : "."; - return paths; - } -} --- /dev/null 2020-03-09 16:06:12.000000000 -0700 +++ new/src/java.base/windows/classes/jdk/internal/loader/ClassLoaderHelper.java 2020-03-09 16:06:12.000000000 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.loader; + +import java.io.File; + +class ClassLoaderHelper { + + private ClassLoaderHelper() {} + + /** + * Returns an alternate path name for the given file + * such that if the original pathname did not exist, then the + * file may be located at the alternate location. + * For most platforms, this behavior is not supported and returns null. + */ + static File mapAlternativeName(File lib) { + return null; + } + + /** + * Parse a PATH env variable. Windows allows quoted elements in a PATH, + * so special care needs to be taken. + * + * Empty elements will be replaced by dot. + */ + static String[] parsePath(String ldPath) { + int ldLen = ldPath.length(); + char ps = File.pathSeparatorChar; + int psCount = 0; + + if (ldPath.indexOf('\"') >= 0) { + // First, remove quotes put around quoted parts of paths. + // Second, use a quotation mark as a new path separator. + // This will preserve any quoted old path separators. + char[] buf = new char[ldLen]; + int bufLen = 0; + for (int i = 0; i < ldLen; ++i) { + char ch = ldPath.charAt(i); + if (ch == '\"') { + while (++i < ldLen && + (ch = ldPath.charAt(i)) != '\"') { + buf[bufLen++] = ch; + } + } else { + if (ch == ps) { + psCount++; + ch = '\"'; + } + buf[bufLen++] = ch; + } + } + ldPath = new String(buf, 0, bufLen); + ldLen = bufLen; + ps = '\"'; + } else { + for (int i = ldPath.indexOf(ps); i >= 0; + i = ldPath.indexOf(ps, i + 1)) { + psCount++; + } + } + + String[] paths = new String[psCount + 1]; + int pathStart = 0; + for (int j = 0; j < psCount; ++j) { + int pathEnd = ldPath.indexOf(ps, pathStart); + paths[j] = (pathStart < pathEnd) ? + ldPath.substring(pathStart, pathEnd) : "."; + pathStart = pathEnd + 1; + } + paths[psCount] = (pathStart < ldLen) ? + ldPath.substring(pathStart, ldLen) : "."; + return paths; + } +}