当前位置:网站首页>JVM(3) 类加载
JVM(3) 类加载
2022-06-29 19:16:00 【Demon_bh】
类加载
1、类加载阶段
1) 加载
- 将类的字节码载入方法区(元空间jdk1.8),内部采用C++
- 有父类先加载父类
- 反射是通过对象头class地址找到元空间中Class类对象,从中获取_fields, _methods等信息!
2) 连接
1、验证:字节码是否符合规范
2、准备:给类static变量分配空间,确认默认值==(static int a = 10)==
- static 变量确认默认值和赋值是两个步骤,确认默认值在准备阶段完成a值为0,赋值在初始化阶段完成a值为10
- 但如果 static 变量 是 final 的基本类型,以及字符串常量,那么赋值在准备阶段完成
- 如果 static 变量是 final 的,但属于引用类型,那么赋值也会在初始化阶段完成将常量池中的符号引用解析为直接引用
3、解析:将常量池中的符号引用解析为直接引用(确定引用类的地址)
3) 初始化
初始化即调用 () 方法 ,该方法包含类中所有静态变量的赋值与所有静态代码块执行,虚拟机会保证这个类的『构造方法』的线程安全。
*类初始化是【懒惰的】:
- main 方法所在的类,总会被首先初始化
- 首次访问这个类的静态变量或静态方法时
- 子类初始化,如果父类还没初始化,会引发
- 子类访问父类的静态变量,只会触发父类的初始化
- Class.forName
- new 会导致初始化
不会导致类初始化的情况:
- 访问类的 static final 静态常量(基本类型和字符串)不会触发初始化(连接阶段)
- 类对象.class 不会触发初始化(加载阶段)
- 创建该类的数组不会触发初始化
*利用类加载初始化特性实现懒汉单例模式
public class Singleton {
//私有构造器,不能被外部调用
private Singleton() {
}
// 内部类中保存单例
private static class LazyHolder {
static final Singleton INSTANCE = new Singleton();
}
// 第一次调用 getInstance 方法,才会导致内部类加载和初始化其静态成员
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
特点:
- 懒惰实例化
- 初始化时的线程安全是由类加载器保障的
2、类加载器
- Bootstrap ClassLoader jre/lib (C++编写,无法直接访问)
- Extension ClassLoader jre/lib/ext
- Application ClassLoader classpath (系统类加载器)
- 自定义类加载器 自定义
特点:
- 每个类加载器都有一个独立的类命名空间
- 任意一个类,都需要类本身+加载此类的类加载器共同确定唯一性
**双亲委派模式
工作过程:一个类加载器收到了加载类的请求,他首先把这个请求委派给上级类加载器去完成,每层都是如此,直到传递给顶层的启动类加载器,只有当上层类加载器无法完成加载请求(搜索范围中没有这个类)时,下层加载器才会尝试自己加载。
优点:
- 如Object类,他的位置只能被最顶层的启动类加载器加载,所以无论哪个类加载器要加载这个类,最终都是由启动类加载器加载,这保证了Object类在各种类加载器环境中的都是同一个。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先查找该类是否已经被该类加载器加载过了
Class<?> c = findLoadedClass(name);
// 如果没有被加载过
if (c == null) {
long t0 = System.nanoTime();
try {
// 看是否被它的上级加载器加载过了 Extension 的上级是Bootstarp,但它显示为null
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 看是否被启动类加载器加载过
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
//捕获异常,但不做任何处理
}
if (c == null) {
// 如果还是没有找到,先让拓展类加载器调用 findClass 方法去找到该类,如果还是没找到,就抛出异常
// 然后让应用类加载器去找 classpath 下找该类
long t1 = System.nanoTime();
c = findClass(name);
// 记录时间
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
==在加载JDBC数据库驱动时,使用的是应用程序类加载器(没使用启动类加载器,打破了双亲委派模式)
边栏推荐
- 开发者任务中心上线!千元豪礼送不停!
- 小米笔试真题一
- AI场景存储优化:云知声超算平台基于 JuiceFS 的存储实践
- With these four security testing tools, software security testing can be said so easy!
- TP5 where queries whether a field in the database contains a value. Fuzzy queries are performed without the like method
- 数据库是什么?数据库详细笔记!带你走进数据库~你想知道的这里都有!
- Canonical的工程师们正努力解决Firefox Snap的性能问题
- 求职大厂被拒?腾讯高手总结了11条被拒的原因!
- [笔记]再笔记--边干边学Verilog HDL –008
- 【️爬虫必备->Scrapy框架从黑铁到王者️】初篇——万字博文详解(建议收藏)
猜你喜欢
随机推荐
福昕软件受邀亮相2022先进制造业数智发展论坛
出逃与进军,临期食品的「双面江湖」
誰在抖音文玩裏趁亂打劫?
虎符限币种提现 用户曲线出金即亏损
全局变量和静态变量的初始化
JS-判断数组键名是否存在
创作者基金会 6 月份亮点
sql server备份以及还原的命令操作
细说GaussDB(DWS)复杂多样的资源负载管理手段
Canonical的工程师们正努力解决Firefox Snap的性能问题
Seven cattle image access parameters (thumbnails are small in size to avoid wasting traffic)
Selenium WebDriver的高级特性
Determination of concurrent number of pressure measurement
云上未来,数智导航:阿里云研究院报告合集
Win11策略服务被禁用怎么办?Win11策略服务被禁用的解决方法
Docker compose deploy the flask project and build the redis service
Rejected by a large company? Tencent experts summarized 11 reasons for being rejected!
[software testing] 01 -- software life cycle and software development model
docker compose 部署Flask项目并构建redis服务
构建增强现实移动应用程序的六款顶级工具








