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 /**
2576 // Extra safety: check the types
2577 Object current = unsafe.getReference(this, offset);
2578 if (current.getClass() != obj.getClass()) {
2579 throw new IllegalStateException("Wrong field type");
2580 }
2581
2582 unsafe.putReference(this, offset, obj);
2583 }
2584
2585 /**
2586 * Called only by the VM, during -Xshare:dump.
2587 *
2588 * @implNote This is done while the JVM is running in single-threaded mode,
2589 * and at the very end of Java bytecode execution. We know that no more classes
2590 * will be loaded and none of the fields modified by this method will be used again.
2591 */
2592 private void resetArchivedStates() {
2593 if (parallelLockMap != null) {
2594 reinitObjectField("parallelLockMap", new ConcurrentHashMap<>());
2595 }
2596 reinitObjectField("packages", new ConcurrentHashMap<>());
2597 reinitObjectField("package2certs", new ConcurrentHashMap<>());
2598 classes.clear();
2599 classes.trimToSize();
2600 classLoaderValueMap = null;
2601 }
2602 }
2603
2604 /*
2605 * A utility class that will enumerate over an array of enumerations.
2606 */
2607 final class CompoundEnumeration<E> implements Enumeration<E> {
2608 private final Enumeration<E>[] enums;
2609 private int index;
2610
2611 public CompoundEnumeration(Enumeration<E>[] enums) {
2612 this.enums = enums;
2613 }
2614
2615 private boolean next() {
2616 while (index < enums.length) {
2617 if (enums[index] != null && enums[index].hasMoreElements()) {
2618 return true;
2619 }
2620 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 /**
2581 // Extra safety: check the types
2582 Object current = unsafe.getReference(this, offset);
2583 if (current.getClass() != obj.getClass()) {
2584 throw new IllegalStateException("Wrong field type");
2585 }
2586
2587 unsafe.putReference(this, offset, obj);
2588 }
2589
2590 /**
2591 * Called only by the VM, during -Xshare:dump.
2592 *
2593 * @implNote This is done while the JVM is running in single-threaded mode,
2594 * and at the very end of Java bytecode execution. We know that no more classes
2595 * will be loaded and none of the fields modified by this method will be used again.
2596 */
2597 private void resetArchivedStates() {
2598 if (parallelLockMap != null) {
2599 reinitObjectField("parallelLockMap", new ConcurrentHashMap<>());
2600 }
2601
2602 if (CDS.isDumpingPackages()) {
2603 if (System.getProperty("cds.debug.archived.packages") != null) {
2604 for (Map.Entry<String, NamedPackage> entry : packages.entrySet()) {
2605 String key = entry.getKey();
2606 NamedPackage value = entry.getValue();
2607 System.out.println("Archiving " +
2608 (value instanceof Package ? "Package" : "NamedPackage") +
2609 " \"" + key + "\" for " + this);
2610 }
2611 }
2612 } else {
2613 reinitObjectField("packages", new ConcurrentHashMap<>());
2614 reinitObjectField("package2certs", new ConcurrentHashMap<>());
2615 }
2616
2617 classes.clear();
2618 classes.trimToSize();
2619 classLoaderValueMap = null;
2620 libraries.clear();
2621 }
2622 }
2623
2624 /*
2625 * A utility class that will enumerate over an array of enumerations.
2626 */
2627 final class CompoundEnumeration<E> implements Enumeration<E> {
2628 private final Enumeration<E>[] enums;
2629 private int index;
2630
2631 public CompoundEnumeration(Enumeration<E>[] enums) {
2632 this.enums = enums;
2633 }
2634
2635 private boolean next() {
2636 while (index < enums.length) {
2637 if (enums[index] != null && enums[index].hasMoreElements()) {
2638 return true;
2639 }
2640 index++;
|