1 /*
2 * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2019, Azul Systems, Inc. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
41 import java.util.Enumeration;
42 import java.util.HashMap;
43 import java.util.Map;
44 import java.util.NoSuchElementException;
45 import java.util.Objects;
46 import java.util.Set;
47 import java.util.Spliterator;
48 import java.util.Spliterators;
49 import java.util.WeakHashMap;
50 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.function.Supplier;
52 import java.util.stream.Stream;
53 import java.util.stream.StreamSupport;
54
55 import jdk.internal.loader.BootLoader;
56 import jdk.internal.loader.BuiltinClassLoader;
57 import jdk.internal.loader.ClassLoaders;
58 import jdk.internal.loader.NativeLibrary;
59 import jdk.internal.loader.NativeLibraries;
60 import jdk.internal.perf.PerfCounter;
61 import jdk.internal.misc.Unsafe;
62 import jdk.internal.misc.VM;
63 import jdk.internal.reflect.CallerSensitive;
64 import jdk.internal.reflect.CallerSensitiveAdapter;
65 import jdk.internal.reflect.Reflection;
66 import jdk.internal.util.StaticProperty;
67
68 /**
69 * A class loader is an object that is responsible for loading classes. The
70 * class {@code ClassLoader} is an abstract class. Given the <a
71 * href="#binary-name">binary name</a> of a class, a class loader should attempt to
72 * locate or generate data that constitutes a definition for the class. A
73 * typical strategy is to transform the name into a file name and then read a
74 * "class file" of that name from a file system.
75 *
76 * <p> Every {@link java.lang.Class Class} object contains a {@link
77 * Class#getClassLoader() reference} to the {@code ClassLoader} that defined
78 * it.
79 *
80 * <p> {@code Class} objects for array classes are not created by class
1832 * @throws Error
1833 * If the system property "{@code java.system.class.loader}"
1834 * is defined but the named class could not be loaded, the
1835 * provider class does not define the required constructor, or an
1836 * exception is thrown by that constructor when it is invoked. The
1837 * underlying cause of the error can be retrieved via the
1838 * {@link Throwable#getCause()} method.
1839 */
1840 public static ClassLoader getSystemClassLoader() {
1841 switch (VM.initLevel()) {
1842 case 0:
1843 case 1:
1844 case 2:
1845 // the system class loader is the built-in app class loader during startup
1846 return getBuiltinAppClassLoader();
1847 case 3:
1848 String msg = "getSystemClassLoader cannot be called during the system class loader instantiation";
1849 throw new IllegalStateException(msg);
1850 default:
1851 // system fully initialized
1852 assert VM.isBooted() && scl != null;
1853 return scl;
1854 }
1855 }
1856
1857 static ClassLoader getBuiltinPlatformClassLoader() {
1858 return ClassLoaders.platformClassLoader();
1859 }
1860
1861 static ClassLoader getBuiltinAppClassLoader() {
1862 return ClassLoaders.appClassLoader();
1863 }
1864
1865 /*
1866 * Initialize the system class loader that may be a custom class on the
1867 * application class path or application module path.
1868 *
1869 * @see java.lang.System#initPhase3
1870 */
1871 static synchronized ClassLoader initSystemClassLoader() {
1872 if (VM.initLevel() != 3) {
1873 throw new InternalError("system class loader cannot be set at initLevel " +
1874 VM.initLevel());
1875 }
1876
1877 // detect recursive initialization
1878 if (scl != null) {
1879 throw new IllegalStateException("recursive invocation");
1880 }
1881
1882 ClassLoader builtinLoader = getBuiltinAppClassLoader();
1883 String cn = System.getProperty("java.system.class.loader");
1884 if (cn != null) {
1885 try {
1886 // custom class loader is only supported to be loaded from unnamed module
1887 Constructor<?> ctor = Class.forName(cn, false, builtinLoader)
1888 .getDeclaredConstructor(ClassLoader.class);
1889 scl = (ClassLoader) ctor.newInstance(builtinLoader);
1890 } catch (Exception e) {
1891 Throwable cause = e;
1892 if (e instanceof InvocationTargetException) {
1893 cause = e.getCause();
1894 if (cause instanceof Error) {
1895 throw (Error) cause;
1896 }
1897 }
1898 if (cause instanceof RuntimeException) {
1899 throw (RuntimeException) cause;
1900 }
1901 throw new Error(cause.getMessage(), cause);
1902 }
1903 } else {
1904 scl = builtinLoader;
1905 }
1906 return scl;
1907 }
1908
1909 // Returns the class's class loader, or null if none.
1910 static ClassLoader getClassLoader(Class<?> caller) {
1911 // This can be null if the VM is requesting it
1912 if (caller == null) {
1913 return null;
1914 }
1915 // Circumvent security check since this is package-private
1916 return caller.getClassLoader0();
1917 }
1918
1919 // The system class loader
1920 // @GuardedBy("ClassLoader.class")
1921 private static volatile ClassLoader scl;
1922
1923 // -- Package --
1924
1925 /**
1926 * Define a Package of the given Class object.
1927 *
1928 * If the given class represents an array type, a primitive type or void,
1929 * this method returns {@code null}.
1930 *
1931 * This method does not throw IllegalArgumentException.
1932 */
1933 Package definePackage(Class<?> c) {
1934 if (c.isPrimitive() || c.isArray()) {
1935 return null;
1936 }
1937
1938 return definePackage(c.getPackageName(), c.getModule());
1939 }
1940
1941 /**
2561 /**
2562 * Attempts to atomically set a volatile field in this object. Returns
2563 * {@code true} if not beaten by another thread. Avoids the use of
2564 * AtomicReferenceFieldUpdater in this class.
2565 */
2566 private boolean trySetObjectField(String name, Object obj) {
2567 Unsafe unsafe = Unsafe.getUnsafe();
2568 Class<?> k = ClassLoader.class;
2569 long offset;
2570 offset = unsafe.objectFieldOffset(k, name);
2571 return unsafe.compareAndSetReference(this, offset, null, obj);
2572 }
2573
2574 /**
2575 * Called by the VM, during -Xshare:dump
2576 */
2577 private void resetArchivedStates() {
2578 if (parallelLockMap != null) {
2579 parallelLockMap.clear();
2580 }
2581 packages.clear();
2582 package2certs.clear();
2583 classes.clear();
2584 classLoaderValueMap = null;
2585 }
2586 }
2587
2588 /*
2589 * A utility class that will enumerate over an array of enumerations.
2590 */
2591 final class CompoundEnumeration<E> implements Enumeration<E> {
2592 private final Enumeration<E>[] enums;
2593 private int index;
2594
2595 public CompoundEnumeration(Enumeration<E>[] enums) {
2596 this.enums = enums;
2597 }
2598
2599 private boolean next() {
2600 while (index < enums.length) {
2601 if (enums[index] != null && enums[index].hasMoreElements()) {
2602 return true;
2603 }
2604 index++;
|
1 /*
2 * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2019, Azul Systems, Inc. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
41 import java.util.Enumeration;
42 import java.util.HashMap;
43 import java.util.Map;
44 import java.util.NoSuchElementException;
45 import java.util.Objects;
46 import java.util.Set;
47 import java.util.Spliterator;
48 import java.util.Spliterators;
49 import java.util.WeakHashMap;
50 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.function.Supplier;
52 import java.util.stream.Stream;
53 import java.util.stream.StreamSupport;
54
55 import jdk.internal.loader.BootLoader;
56 import jdk.internal.loader.BuiltinClassLoader;
57 import jdk.internal.loader.ClassLoaders;
58 import jdk.internal.loader.NativeLibrary;
59 import jdk.internal.loader.NativeLibraries;
60 import jdk.internal.perf.PerfCounter;
61 import jdk.internal.misc.CDS;
62 import jdk.internal.misc.Unsafe;
63 import jdk.internal.misc.VM;
64 import jdk.internal.reflect.CallerSensitive;
65 import jdk.internal.reflect.CallerSensitiveAdapter;
66 import jdk.internal.reflect.Reflection;
67 import jdk.internal.util.StaticProperty;
68
69 /**
70 * A class loader is an object that is responsible for loading classes. The
71 * class {@code ClassLoader} is an abstract class. Given the <a
72 * href="#binary-name">binary name</a> of a class, a class loader should attempt to
73 * locate or generate data that constitutes a definition for the class. A
74 * typical strategy is to transform the name into a file name and then read a
75 * "class file" of that name from a file system.
76 *
77 * <p> Every {@link java.lang.Class Class} object contains a {@link
78 * Class#getClassLoader() reference} to the {@code ClassLoader} that defined
79 * it.
80 *
81 * <p> {@code Class} objects for array classes are not created by class
1833 * @throws Error
1834 * If the system property "{@code java.system.class.loader}"
1835 * is defined but the named class could not be loaded, the
1836 * provider class does not define the required constructor, or an
1837 * exception is thrown by that constructor when it is invoked. The
1838 * underlying cause of the error can be retrieved via the
1839 * {@link Throwable#getCause()} method.
1840 */
1841 public static ClassLoader getSystemClassLoader() {
1842 switch (VM.initLevel()) {
1843 case 0:
1844 case 1:
1845 case 2:
1846 // the system class loader is the built-in app class loader during startup
1847 return getBuiltinAppClassLoader();
1848 case 3:
1849 String msg = "getSystemClassLoader cannot be called during the system class loader instantiation";
1850 throw new IllegalStateException(msg);
1851 default:
1852 // system fully initialized
1853 assert VM.isBooted() && Holder.scl != null;
1854 return Holder.scl;
1855 }
1856 }
1857
1858 static ClassLoader getBuiltinPlatformClassLoader() {
1859 return ClassLoaders.platformClassLoader();
1860 }
1861
1862 static ClassLoader getBuiltinAppClassLoader() {
1863 return ClassLoaders.appClassLoader();
1864 }
1865
1866 /*
1867 * Initialize the system class loader that may be a custom class on the
1868 * application class path or application module path.
1869 *
1870 * @see java.lang.System#initPhase3
1871 */
1872 static synchronized ClassLoader initSystemClassLoader() {
1873 if (VM.initLevel() != 3) {
1874 throw new InternalError("system class loader cannot be set at initLevel " +
1875 VM.initLevel());
1876 }
1877
1878 // detect recursive initialization
1879 if (Holder.scl != null) {
1880 throw new IllegalStateException("recursive invocation");
1881 }
1882
1883 ClassLoader builtinLoader = getBuiltinAppClassLoader();
1884 String cn = System.getProperty("java.system.class.loader");
1885 if (cn != null) {
1886 try {
1887 // custom class loader is only supported to be loaded from unnamed module
1888 Constructor<?> ctor = Class.forName(cn, false, builtinLoader)
1889 .getDeclaredConstructor(ClassLoader.class);
1890 Holder.scl = (ClassLoader) ctor.newInstance(builtinLoader);
1891 } catch (Exception e) {
1892 Throwable cause = e;
1893 if (e instanceof InvocationTargetException) {
1894 cause = e.getCause();
1895 if (cause instanceof Error) {
1896 throw (Error) cause;
1897 }
1898 }
1899 if (cause instanceof RuntimeException) {
1900 throw (RuntimeException) cause;
1901 }
1902 throw new Error(cause.getMessage(), cause);
1903 }
1904 } else {
1905 Holder.scl = builtinLoader;
1906 }
1907 return Holder.scl;
1908 }
1909
1910 // Returns the class's class loader, or null if none.
1911 static ClassLoader getClassLoader(Class<?> caller) {
1912 // This can be null if the VM is requesting it
1913 if (caller == null) {
1914 return null;
1915 }
1916 // Circumvent security check since this is package-private
1917 return caller.getClassLoader0();
1918 }
1919
1920 // Holder has the field(s) that need to be initialized during JVM bootstrap even if
1921 // the outer is aot-initialized.
1922 private static class Holder {
1923 // The system class loader
1924 // @GuardedBy("ClassLoader.class")
1925 private static volatile ClassLoader scl;
1926 }
1927
1928 // -- Package --
1929
1930 /**
1931 * Define a Package of the given Class object.
1932 *
1933 * If the given class represents an array type, a primitive type or void,
1934 * this method returns {@code null}.
1935 *
1936 * This method does not throw IllegalArgumentException.
1937 */
1938 Package definePackage(Class<?> c) {
1939 if (c.isPrimitive() || c.isArray()) {
1940 return null;
1941 }
1942
1943 return definePackage(c.getPackageName(), c.getModule());
1944 }
1945
1946 /**
2566 /**
2567 * Attempts to atomically set a volatile field in this object. Returns
2568 * {@code true} if not beaten by another thread. Avoids the use of
2569 * AtomicReferenceFieldUpdater in this class.
2570 */
2571 private boolean trySetObjectField(String name, Object obj) {
2572 Unsafe unsafe = Unsafe.getUnsafe();
2573 Class<?> k = ClassLoader.class;
2574 long offset;
2575 offset = unsafe.objectFieldOffset(k, name);
2576 return unsafe.compareAndSetReference(this, offset, null, obj);
2577 }
2578
2579 /**
2580 * Called by the VM, during -Xshare:dump
2581 */
2582 private void resetArchivedStates() {
2583 if (parallelLockMap != null) {
2584 parallelLockMap.clear();
2585 }
2586
2587 if (CDS.isDumpingPackages()) {
2588 if (System.getProperty("cds.debug.archived.packages") != null) {
2589 for (Map.Entry<String, NamedPackage> entry : packages.entrySet()) {
2590 String key = entry.getKey();
2591 NamedPackage value = entry.getValue();
2592 System.out.println("Archiving " +
2593 (value instanceof Package ? "Package" : "NamedPackage") +
2594 " \"" + key + "\" for " + this);
2595 }
2596 }
2597 } else {
2598 packages.clear();
2599 package2certs.clear();
2600 }
2601 classes.clear();
2602 classLoaderValueMap = null;
2603 libraries.clear();
2604 }
2605 }
2606
2607 /*
2608 * A utility class that will enumerate over an array of enumerations.
2609 */
2610 final class CompoundEnumeration<E> implements Enumeration<E> {
2611 private final Enumeration<E>[] enums;
2612 private int index;
2613
2614 public CompoundEnumeration(Enumeration<E>[] enums) {
2615 this.enums = enums;
2616 }
2617
2618 private boolean next() {
2619 while (index < enums.length) {
2620 if (enums[index] != null && enums[index].hasMoreElements()) {
2621 return true;
2622 }
2623 index++;
|