javadoc的解释:
ClassLoader的每一个实例都会有一个与之关联的父ClassLoader,当被要求去寻找一个类或者资源的时候,ClassLoader的实例就会对于类或者是资源的寻找委托给他的父ClassLoader(在他自己尝试找这个类或者资源之前),并层层向上委托。
虚拟机内建的ClassLoader即Bootstrap根类加载器,他本身是没有双亲的,但是他可以作为一个类加载器的双亲。
支持并发加载类的类加载器,被称为 parallel capable class loaders ,被要求在类的初始化期间调用ClassLoader.registerAsParallelCapable()将自身注册为parallelcapableclassloader。 ClassLoader默认是并发类加载器,但他的子类如果是并发的,还依然需要注册。
当境委派模型并不是严格的层次委派模型时,要求类加载器必须是支持并行的类加载器,否则类加载就会导致死锁。因为加载器的锁(loader lock我也不知道咋翻译)在类的加载过程中一直不会释放。
一般来说jvm虚拟机加载类来源于本地文件系统(与操作系统跟平台相关),但也可能来源于其他资源,比如网络,或者运行时的动态生成。
在这种情况下,加载类的方法会把一个字节数组(调用 loadClassData() 返回byte[] ,通过defineClass(byte[])转为一个Class)转换为一个class对象,通过Class.newInstance 来创建对应对象。
class NetworkClassLoader extends ClassLoader { public Class findClass(String name) { private byte[] loadClassData(String name) { } |
由类加载器创建的对象,其方法或者构造器可能引用了其他未加载的类,为了确定这些引用是什么(注意这些引用对应的类还未被装入,需要确定这些引用是什么) jvm虚拟机会调用加载这个类的class的classloader 来加载这些引用(再次跳入第一步 开始递归)
1.获取ClassLoader
1 public class MyTest06 {
2
3 public static void main(String[] args) {
4 String str = new String("212");
5 C c = new C();
6 System.out.println(str.getClass().getClassLoader());
7 System.out.println(c.getClass().getClassLoader());
8 }
9
10 }
11 class C{
12
13 }//out: null
sun.misc.Launcher$AppClassLoader@2a139a55
第二个返回值说明自定义类C是由AppClassLoader 系统类加载器加载
第一个返回值说明String由Bootstrap根加载器加载
/** 如下是源码中对 getClassLoader() 方法的说明
* Returns the class loader for the class. Some implementations may use
* null to represent the bootstrap class loader. This method will return
* null in such implementations if this class was loaded by the bootstrap
* class loader.
* 如果类由bootstrap class loader加载 这个方法会返回null在一些jvm实现中
*
* <p> If a security manager is present, and the caller's class loader is
* not null and the caller's class loader is not the same as or an ancestor of
* the class loader for the class whose class loader is requested, then
* this method calls the security manager's {@code checkPermission}
* method with a {@code RuntimePermission("getClassLoader")}
* permission to ensure it's ok to access the class loader for the class.
*
* <p>If this object
* represents a primitive type or void, null is returned.
*
* @return the class loader that loaded the class or interface
* represented by this object.
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method denies
* access to the class loader for the class.
* @see java.lang.ClassLoader
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/
2.ClassLoader.loadClass()方法与Class.forName()方法
class CL{
static {
System.out.println("class cl");
}
}
public class MyTest07 {
public static void main(String[] args) throws Exception {
ClassLoader clazzloader = ClassLoader.getSystemClassLoader();
Class<?> clazz = clazzloader.loadClass("jvm.CL");
System.out.println("==================================");
System.out.println(clazz);
System.out.println("==================================");
Class<?> clazz2 = Class.forName("jvm.CL");
System.out.println("==================================");
System.out.println(clazz2);
}
}//out:
==================================
class jvm.CL
==================================
class cl
==================================
class jvm.CL
loadclass 只加载对应类,forName 会一并将类初始化
不过调用 clazz.newInstance()会初始化该类:
public class MyTest07 {
public static void main(String[] args) throws Exception {
ClassLoader clazzloader = ClassLoader.getSystemClassLoader();
Class<?> clazz = clazzloader.loadClass("jvm.CL");
System.out.println("==================================");
System.out.println(clazz);
System.out.println("==================================");
clazz.newInstance();
System.out.println("==================================");
Class<?> clazz2 = Class.forName("jvm.CL");
System.out.println("==================================");
System.out.println(clazz2);
}
}out:
==================================
class jvm.CL
==================================
class cl
==================================
==================================
class jvm.CL
3.HotSpot实现中用null代替根加载器Bootstrap
public class MyTest08 {
public static void main(String[] args) {
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);
while(classloader!=null) {
classloader= classloader.getParent();
System.out.println(classloader);
}
}
}//out:
sun.misc.Launcher$AppClassLoader@2a139a55
sun.misc.Launcher$ExtClassLoader@7852e922
null
4.数组的classloader,数组是JVM在运行时动态生成的类型,没有类加载器,如果调用getClassLoader会返回对应元素的类加载器。
public class MyTest09 {
public static void main(String[] args) {
String[] strs = new String[2];
System.out.println(strs.getClass().getClassLoader());
System.out.println("============================");
MyTest09[] ms = new MyTest09[2];
System.out.println(ms.getClass().getClassLoader());
System.out.println("============================");
int[] ints = new int[2];
System.out.println(ints.getClass().getClassLoader());
}
}//out:
null
============================
sun.misc.Launcher$AppClassLoader@2a139a55
============================
null
其中String类型的类加载器是Bootstrap 在HotSpot实现中被表现为null
源生类型则没有类加载器。
5.类加载器一般都会伴随一个安全管理器,来确保类加载过程中是安全的
来源:oschina
链接:https://my.oschina.net/u/4302179/blog/3588888