一.java 虚拟机中类加载过程
** 加载 ——》链接 ——》初始化**
- 加载
JVM 虚拟机将.class文件读入内存,并为之创建一个class 对象,任何类被使用时系统都会为其创建一个唯一存在的class对象。这个class 对象描述了这个类创建出来的对象的所有信息,包括构造方法,成员变量,成员方法等。 - .链接阶段
包括验证、准备以及解析三个阶段。
验证阶段,主要目的是确保被加载的类满足java 虚拟机规范(包括格式验证、语义验证、操作验证等),不会造成安全错误。
格式验证:验证是否符合class文件规范
语义验证:检查一个被标记为final的类型是否包含子类;检查一个类中的final方法视频被子类进行重写;确保父类和子类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)
操作验证:在操作数栈中的数据必须进行正确的操作,对常量池中的各种符号引用执行验证(通常在解析阶段执行,检查是否通过符号引用中描述的全限定名定位到指定类型上,以及类成员信息的访问修饰符是否允许访问等
准备阶段,负责为类的静态变量分配内存,并设置初始默认值。
解析阶段,将类的二进制数据中的符号引用替换为直接引用,例如
Math类中有一个add()方法,调用了Dog类的getAge()方法,
public void add(Dog dog){
return dog.getAge(); }
因此在Math类的二进制数据中,包含了一个对getAge方法的符号引用,
java虚拟机在加载Math类的过程中,会将这个符号引用替换为一个指针,该指针指向方法区中存储Dog类getAg()方法指令集的实际地址,这个指针就是直接引用。
3. 初始化
将类中的所有static变量和静态代码块执行一遍,如果执行的是静态变量,会使用用户设置的值替换准备阶段设置的初始值。
如果初始化一个类的时候,其父类还未初始化,则先初始化其父类。
如果包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
二、双亲委派模型
1.启动类加载器(bootstrap ClassLoader),这个类加载器通用C++语言实现,是虚拟机的一部分,加载jdk目录下的lib 文件中的jar包;
2.所有其他的类加载器,这些类加载器用Java 语言实现,独立于虚拟机外部,并且全部继承于抽象类Java.lang.ClassLoader(扩展类加载器,应用程序加载器,自定义类加载器)
扩展类加载器(Extension ClassLoader):这个类加载器是由ExtClassLoader实现的。它负责将
应用程序类加载器(Application ClassLoader):这个类加载器是由 AppClassLoader实现的。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
双亲委派的工作过程:如果一个类加载器收到了类加载的请求,它首先不会尝试加载这个类,而是把这个请求委派给父类加载器进行加载,每一个层次的加载器都是如此。因此所有的加载请求最终都会传到顶层的启动类加载器中,只有父类加载器反馈自己无法完成这个加载请求时(它搜索的范围没有找到所需的类),子加载器才会尝试自己去加载;
启动类加载器——》扩展类加载器——》应用程序类加载器
好处:避免重复加载可能导致的性能问题
保证了Java基础类库不会被覆盖,具有一定的安全性



