类加载过程
2024-03-20 10:05:47 6 举报
类加载过程
作者其他创作
大纲/内容
典型的案例:tomcat,相同的包名,相同的类名在jvm中是可以共存的,前提是类加载器不一样(架构不同版本的war包执行在同一个tomcat上)
Synchronized
找字面量对应的引用
Thread.currentThread().getContextClassLoader()
获取线程上下文类加载器
在DriverManger中有一个静态代码块,逻辑在这个里面实现的,还有就是类路径放到了配置文件中,不用Class.forName();
加载
采用双亲委派机制进行加载:1.防止类的重复加载2.沙箱安全机制,防止核心API库被随意篡改为什么要从下往上,不直接从下往上,95%的类都是我们字节写的,也就是都在应用类加载器中,第一次比较慢,从下网上询问有没有加载过,然后再从上往下进行加载
jvm内存
Class<?> c = findLoadedClass(name);查看类是否被加载
(通过字面量赋值)String a = \"abc\"
heap
连接
加载过后的文件已经到jvm中了
字符串常量池引用
Launcher类中的静态内部类(appClassLoader,ExtClassLoader)这里注意一个常识:类路径$Class指的是内部类
class对象
解析
验证
HelloWorld.java
没有竞争的情况下
扩展类加载器Extension ClassLoader
类加载器来完成
应用类加载器Application ClassLoader
对线头
实例对象
HelloWorld.class(字节码文件)
类加载是把字节码文件加载为class对象
8byte的倍数 ,减少堆内存的碎片空间
java命令
javac
记录数组对象的长度(只有数组才有)
mateSpace
ReentrantLock
也叫对象体
占用8字节64位
abc
向上委托在这里写的,这里只要重新方法,自定义家在逻辑就可以了(有沙箱安全机制,java。lang。string就打破不了)但是有个问题所有类的父类都是object,那不就怎么都实现不了?,这个可以在loadclass中写,不是这个包下面的类的还走原来的委派
有两个竞争的线程(竞争不激烈的情况下)
类型指针
加载:在硬盘中查找并通过io读入字节码文件到jvm内存中验证:验证字节码文件的准确性准备:为类的静态变量分配内存空间,并赋值默认值(常量 final static在编译的时候就会分配了)解析:把类中的符号引用转换为直接引用初始化:给静态变量赋值初始值
运行数据区,内存模型
引导类加载器(启动类加载器)bootstrap ClassLoader
同步锁(重量级锁),会指向一个Monitor对象,来登记和管理排队的线程
mark work
运行时常量池(字面量)
指向类元数据元数据
jdbc是如何打破的
每个对象都会有一个监视器锁(Monitor)当monitor被占用了,那么monitor数量就+1 也就是monitentier指令的时候如果该线程已经占有了monitor那么就+1如果不是本线程占有的,并且monitor的数量不为0就进入阻塞状态,当为0的时候就说明这个线程不再是这个锁的所有者,其他阻塞的线程就可以进行获取所有权
从META-INF/server/java.sql.Driver文件中获取Driver的全类名
准备
启动类加载器:加载jre/lib下的核心类库,rt.jar扩展类加载器:加载jre/lib/ext目录中的jar包应用类加载器:classpath下的字节码文件,也就是类路径下的class文件
填充数据
字符串常来那个池(存储的是字符串的引用)
地址空间
在syn优化之前reen性能比syn要好许多,但是自从syn进行优化了之后,引入了锁升级,官方推荐还是syn
向上委托
Class Metadata Address
tomcat是如何打破的,为什么要打破
哪个线程先占有就执行哪个(自旋锁),竞争锁失败,不阻塞自己,而是进行有限的空循环,叫自旋,如果自旋完成锁得到了失访,那就命中了,但是竞争激烈的话命中率就会很低,影响效率了(持有锁时间长,竞争激烈的情况下都不适合)
https://zhuanlan.zhihu.com/p/351226127
初始化
线程上下文类加载器破坏双亲委派机制
返回的是地址
有多个竞争的线程
直接指向
实例变量
重写loadClass方法
对象在Survivor区复制一次年龄+ 1,这也就是最大的分代年龄只能是15的原因了,因为对象头里是4位来存储
加载到jvm内存中
java关键字,使用简单,由jvm来实现
hashcode,gc标志,分代年龄
锁升级过程,不会一上来就来一个重量级锁
打破双亲委派机制方法
通过new来创建String b = a.intern(),返回的是字符串常量池中的引用,先从常量池中看有没有,有的话就会返回常量池中的地址,1.7之后放的都是引用,真正的对象在堆内存中
Java-Synchronized和ReentrantLock区别
通过new来创建String a = new String(\"abc\"),返回的是堆内存中字符串的引用会有两个对象创建,堆内存中开辟一块空间,字符串常量池中也会有个对象
独占
通过lock()与unlock()来进行手工加锁解锁,并配合try catch()来进行实现java层面的使用到了cAS
堆内存
window系统下的java.exe调用底层jvm.dll(c++文件,库文件),创建java虚拟机实现,然后创建引导类加载器Launcher,这里面帮我们创建其他类加载器
找对象
线程上下文类加载器也是一种加载器
字符串常量池,是JVM用来维护字符串实例的一个引用表。在HotSpot虚拟机中,它被实现为一个全局的StringTable,底层是一个c++的hashtable。它将字符串的字面量作为key,实际堆中创建的String对象的引用作为value。
创建实例的时候
0 条评论
下一页