View on GitHub

heartCraft.github.io

一朵野花,随风摆荡

Java类加载机制

class声明周期

分为七个阶段:加载、验证、准备、解析、初始化、使用、卸载

​ 加载:把字节码转换为二进制字节流,加载到内存中;

​ 验证:大致可以分为:JVM规范校验,代码逻辑校验…

准备:JVM为类变量分配内存并初始化,这里的初始化是指该类型的默认值,而非代码中的初始化值。

​ 特例:final修饰的类变量赋值为字面量时,会在准备阶段就。

​ 解析:将其常量池中的符号引用替换为内存中的直接饮用

初始化:类初始化(类加载时只执行一次)。

​ 类初始化顺序:先父类初始化,再按代码中顺序,类变量赋值>静态代码块

​ 使用:初始化完成后,该类可以使用。当创建新对象时再进行对象初始化。

​ 对象初始化:先父类对象初始化,再按代码中顺序,类成员变量>普通代码块>构造函数

​ 卸载:JVM销毁创建的Class对象

ClassLoader(将字节码转换为内存中的Class对象)

每个class对象的内部都有一个classLoader字段,标识自己是由哪个classLoader加载的。

JVM 中内置了三个重要的 ClassLoader

可以用URLClassLoader实现自己的类加载器,ExtensionClassLoader 和 AppClassLoader都是URLClassLoader的子类。

ClassLoader.getSystemClassLoader()可以获取AppClassLoader。

ClassLoader传递性:当需要加载一个类时,JVM默认会使用(当前需要使用此类的)调用者Class对象的ClassLoader加载此类。

双亲委派:AppClassLoader 只负责加载Classpath下的类库,遇到未加载的系统类库时,加载工作会交给BootstrapClassLoader 和 ExtensionClassLoader 。

Class.forName:此方法多参数版本支持指定ClassLoader。此方法可以传入自定义的类加载器。

自定义类加载器:三个重要方法,loadClass()、findClass()、defineClass()。使用自定义类加载器会产生钻石依赖问题。

ClassLoader的意义:不同classLoader加载的同一字节码也是不同的类,所以能起到类隔离的作用。而parent属性和双亲委派的机制,又实现了共享的可能。

​ e.g. Thread类的contextClassLoader属性,通过设置该属性,可以隔离不同线程中使用的类。