一、类加载过程

  • 装载
  • 链接
  • 验证
  • 准备
  • 解析
  • 初始化

 

二、类初始化情况

1)创建类的实例,也就是new一个对象  

2)访问某个类或接口的静态变量,或者对该静态变量赋值  

3)调用类的静态方法  

4)反射(Class.forName("xx"))  

5)初始化一个类的子类(会首先初始化子类的父类)  

6)JVM启动时标明的启动类,即文件名和类名相同的那个类

 

三、类加载器

1)BootstrapClassLoader

加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

2)ExtensionClassLoader

加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

3)AppClassLoader

加载classpath中指定的jar包及目录中class

4)CustomClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader

加载过程中会先检查类是否被已加载,检查顺序是自底向上,从CustomClassLoader到BootStrapClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

 

四、双亲委派加载模型

  某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

  注意,双亲委派模型是Java设计者推荐给开发者的类加载器的实现方式,并不是强制规定的。大多数的类加载器都遵循这个模型,但是JDK中也有较大规模破坏双亲模型的情况,例如线程上下文类加载器(Thread Context ClassLoader)的出现。

(1)线程上下文类加载器,这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那么这个类加载器就是应用程序类加载器。JDBC就是采用了这种方式。 

(2)Tomcat的类加载机制不能算完全“正统”的双亲委派,WebappClassLoader内部重写了loadClassfindClass方法,实现了绕过“双亲委派”直接加载web应用内部的资源,当然可以通过在Context.xml文件中加上<Loader delegate = "true">开启正统的“双亲委派”加载机制。