NOTE
7.4 类生命周期
1. 类生命周期 主要有加载、连接、初始化、使用、卸载这几个步骤 1.1. 加载 当我们的代码需要使用一个类的时候,这个类不在JVM中的时候就会加载 1.1.1. 由谁加载 由类加载器负责加载类加载器 1.1.1.1. 类加载器分类 - 启动类加载器负责加载JAVA HOME/lib - 扩展类加载
这是历史学习笔记,可能存在过时或不完整的理解。
1. 类生命周期
主要有加载、连接、初始化、使用、卸载这几个步骤


1.1. 加载
当我们的代码需要使用一个类的时候,这个类不在JVM中的时候就会加载
1.1.1. 由谁加载
由类加载器负责加载类加载器

1.1.1.1. 类加载器分类

- 启动类加载器负责加载JAVA_HOME/lib
- 扩展类加载器负责加载JAVA_HOME/lib/ext
- 应用类加载器负责用户类路径(ClassPath)所指定的类
1.1.1.2. 双亲委派模型
类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载
1.1.1.2.1. 为什么有双亲委派模型
安全。 举个例子,String类不可变的,如果我们自己定义了一个可变的String类放在classpath目录下,那么程序运行时加载的到底时哪个类呢?
1.1.2. 加载过程
- 通过一个类的全限定名来获取定义此类的二进制字节流。
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
1.2. 连接
1.2.1. 验证
根据JVM规范,检验加载进来的“.class”文件中的内容,是否符合指定的规范
1.2.2. 准备
为类变量分配内存并设置默认的初始值(数据类型的零值/final值) 类变量指用static修饰的变量,他们被分配在方法区中 注意实例变量不在这个阶段分配
- 例子1
public static int val = 100;
这里会将val初始化为0而不是100
- 例子2
public final static int val = 300;
这个会初始化val为300而不是0
1.2.3. 解析
虚拟机将常量池内的符号引用替换为直接引用的过程
1.3. 初始化
执行类的初始化代码。 类的初始化代码包括:static属性的赋值、static代码块 初始化规则如下: 类初始化顺序.md
- 例子1
public static int val = 100;
这里会将val初始化为100
- 例子2
public static int val2 = 100;
staic
{
val2 = 200;
}
这里会将val初始化为200
1.4. 使用
new 出来把对象实例分配在堆内存中,由栈帧中的局部变量指向它 对象在内存中的布局.md
1.5. 卸载
如果一个实例没有引用指向他,会被gc回收 垃圾回收.md
2. 问题
2.1. 如何对“.class”文件处理保证不被人拿到以后反编译获取公司源代码?
- 编译时,就可以采用一些小工具对字节码加密,或者做混淆等处理
- 类加载的时候,对加密的类,考虑采用自定义的类加载器来解密文件即可
2.2. Tomcat这种Web容器中的类加载器应该如何设计实现?
打破了双亲委派机制,每个Web应用都有一个对应的WebApp类加载器,由这个WebApp类加载器负责加载Web应用的类,不会有父类加载器加载