Java相关文章
- Java内存模型
- Java中String特性
- Java对象内存布局
- JVM结构
- JVM垃圾回收器
- Java19虚拟线程新特性
- Java线程生命周期与常见方法
- Java线程池笔记
- 浅谈synchronized锁原理
- 浅谈AQS原理
- ThreadLocal原理
Java类加载机制
- 类加载机制
- 加载、验证、准备、解析、初始化
- 加载
- 指将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。
- 验证
- 确保被夹在类的正确性,文件格式验证、元数据验证、字节码验证、符号音乐验证
- 准备:
- 为类的静态变量分配内存并赋默认值
- 只对static修饰的静态变量进行内存分配、福默认值
- 对final的静态字面值常量直接赋初值
- 内存分配的对象。Java 中的变量有类变量和类成员变量两种类型,类变量指的是被static修饰的变量,而其他所有类型的变量都属于类成员变量。在准备阶段,JVM只会为类变量分配内存,而不会为类成员变量分配内存。类成员变量的内存分配需要等到初始化阶段才开始。
- 初始化的类型。在准备阶段,JVM 会为类变量分配内存,并为其初始化。但是这里的初始化指的是为变量赋予 Java 语言中该数据类型的零值,而不是用户代码里初始化的值。
- 解析
- 解析阶段JVM 针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类引用进行解析。这个阶段的主要任务是将其在常量池中的符号引用替换成直接其在内存中的直接引用
- 初始化
- 初始化是为类的静态变量赋予正确的初始值,准备阶段和初始化阶段看似有点矛盾,其实是不矛盾的。
- 如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的。
双亲委派模型
- Java的类加载器
- 启动类加载器
- 扩展类加载器
- 应用类加载器
- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式
为什么要引入双亲委派机制
- 防止出现多分相同的字节码,类加载器和类确定唯一性
- 使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一
- 避免了多份同样字节码的加载
- 保证核心api不会被篡改
为什么打破双亲委派机制
- 以Tomcat为例,一个Tomcat可以运行多个web服务,为了保证各个服务的同名类的加载安全,Tomcat给每个 Web 应用创建一个类加载器实例(WebAppClassLoader),该加载器重写了loadClass方法,优先加载当前应用目录下的类,如果当前找不到了,才一层一层往上找,实现web隔离
- 如何自定义类加载器
- 继承ClassLoader类重写findClass方法