public static ClassLoader getSystemClassLoader() Returns the system class loader for delegation. This is the default delegation parent for new ClassLoader instances, and is typically the class loader used to start the application.
This method is first invoked early in the runtime’s startup sequence, at which point it creates the system class loader and sets it as the context class loader of the invoking Thread.
The default system class loader is an implementation-dependent instance of this class.
默认的系统类加载器是一个与这个类实现相关的实例
If the system property “java.system.class.loader” is defined when this method is first invoked then the value of that property is taken to be the name of a class that will be returned as the system class loader. The class is loaded using the default system class loader and must define a public constructor that takes a single parameter of type ClassLoader which is used as the delegation parent. An instance is then created using this constructor with the default system class loader as the parameter. The resulting class loader is defined to be the system class loader.
If a security manager is present, and the invoker’s class loader is not null and the invoker’s class loader is not the same as or an ancestor of the system class loader, then this method invokes the security manager’s checkPermission method with a RuntimePermission(“getClassLoader”) permission to verify access to the system class loader. If not, a SecurityException will be thrown.
安全略过,主要是介绍一些安全接入的权限是否可以接入
伏笔: 1、【上下文加载器】 2、定义ClassLoader类型的构造器 方法体:
1 2 3 4 5 6 7 8 9 10 11 12
public static ClassLoader getSystemClassLoader() { initSystemClassLoader();//初始化系统类加载器 if (scl == null) { return null; } //下边的是安全相关的,不做介绍 SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkClassLoaderPermission(scl, Reflection.getCallerClass()); } return scl; }
PS: sclSet、scl 成员变量介绍: // The class loader for the system // @GuardedBy("ClassLoader.class") 系统类加载器在ClassLoader的引用 private static ClassLoader scl;
// Set to true once the system class loader has been set // @GuardedBy("ClassLoader.class") //如果系统类加载器被加载过,即scl成员变量不是null,那么sclSet的值为true private static boolean sclSet;
private static synchronized void initSystemClassLoader() { //系统类加载器是否被设置 if (!sclSet) { //双重判断,即sclSet是true,但是系统类加载器是null,排除非法异常 if (scl != null) throw new IllegalStateException("recursive invocation"); //通过sun.misc.Launcher获取系统类加载器。sun.misc.Launcher是系统类加载器,扩展类加载器上层的一个概念,并且Oracle不是开源的 sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); try { scl = AccessController.doPrivileged( new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { oops = oops.getCause(); } } if (oops != null) { if (oops instanceof Error) { throw (Error) oops; } else { // wrap the exception throw new Error(oops); } } } sclSet = true; } }
Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the parameter loader is null, the class is loaded through the bootstrap class loader. The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.
If name denotes a primitive type or void, an attempt will be made to locate a user-defined class in the unnamed package whose name is name. Therefore, this method cannot be used to obtain any of the Class objects representing primitive types or void.
If name denotes an array class, the component type of the array class is loaded but not initialized.
如果name对应的是一个数组类型,这个数组的组件类型会被加载但是不会初始化。
For example, in an instance method the expression: Class.forName(“Foo”) is equivalent to: Class.forName(“Foo”, true, this.getClass().getClassLoader()) Note that this method throws errors related to loading, linking or initializing as specified in Sections 12.2, 12.3 and 12.4 of The Java Language Specification. Note that this method does not check whether the requested class is accessible to its caller.
If the loader is null, and a securiy manager is present, and the caller’s class loader is not null, then this method calls the security manager’s checkPermission method with a RuntimePermissin(“getClassLoader”) permission to ensure it’s ok to access the bootstrap class loader.
public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { Class<?> caller = null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { // Reflective call to get caller class is only needed if a security manager // is present. Avoid the overhead of making this call otherwise. //获取调用此forName方法的类的Class对象A caller = Reflection.getCallerClass(); if (sun.misc.VM.isSystemDomainLoader(loader)) { //获取A的类加载器 ClassLoader ccl = ClassLoader.getClassLoader(caller); //安全检查 if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } //name:要被加载的|initialize:是否初始化|loader:指定的类加载器(自定义加载器此处是系统类加载器)|caller调用者的Class对象 return forName0(name, initialize, loader, caller); } //forName0是一个本地方法 /** Called after security check for system loader access checks have been made. */ private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;