文章目录
- 1、JVM的位置
- 2、JVM的体系结构
- 3、JVM组件
- 3.1、类加载器(加载class文件)
- 3.1.1、类加载器的执行步骤
- 3.2、PC寄存器
- 3.3、方法区
- 3.4、栈
- 3.5、堆
- 4、GC算法
- 4.1、引用计数法
- 4.2、复制算法
- 1、模型
- 2、原理图
- 4.3、标记清除
- 4.4、标记压缩
- 总结:
1、JVM的位置
2、JVM的体系结构
3、JVM组件
3.1、类加载器(加载class文件)
类是模板 对象是具体的
1、虚拟机自带的加载器
2、启动类(根)加载器(java程序获取不到,rt.jar)——BOOT
3、扩展类加载器(\jre\lib\ext)——EXC
4、应用程序加载器()——App
5、双亲委派机制
3.1.1、类加载器的执行步骤
1、类加载器收到类加载的请求
2、将这个请求向上委托给父类加载器去完成,一直向上委托,直到到启动类加载器
3、启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子类加载器进行加载
4、重复步骤3
如果都找不到的话,就会报Class Not Found
null:java调用不到 C、C++
总结:
- APP–>EXC–>BOOT(最终执行)
- BOOT EXC APP
Native关键字的作用
3.2、PC寄存器
程序计数器,是线程私有的,就是一个指针。
寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制。
3.3、方法区
static、final、Class、常量池
3.4、栈
栈:栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存也就是释放,对于栈来说,不存在垃圾回收问题
一旦线程结束,栈就Over!
栈:8大基本类型+对象引用+实例的方法
栈运行原理:栈帧
栈满:StackOverflowError
3.5、堆
一个JVM只有一个堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件后,一般会把什么东西放到堆中?类,方法,常量,变量,保存我们所有引用类型的真实对象;
堆内存中还要细分为三个区域:
- 新生区(伊甸园区)
- 养老区 old
- 永久区 Perm
GC垃圾回收主要是在伊甸园区和养老区
OOM堆内存不够
元空间逻辑上存在:物理上不存在
发生OOM:
1、尝试扩大堆内存结果
2、分析内存,看一下哪个地方出现了问题。
GC垃圾回收
JVM在进行GC时,并不是对这三个区域统一回收,大部分时候,回收都是新生代
- Eden
- 幸存区
- 老年区
GC两种类:轻GC(普通的GC),重GC(全局GC)
GC题目:
- JVM的内存模型和分区,详细到每个区都放什么
- 堆里面的分区有哪些?新生区,幸存区,老年区,说说他们的特点!
- GC算法有哪些?标记清除法,复制算法,引用计数器,怎么用的?
- 轻GC和重GC分别在什么时候发生?
4、GC算法
4.1、引用计数法
4.2、复制算法
1、模型
2、原理图
- 好处:没有内存的碎片
- 坏处:浪费内存空间,多了一半空间永久是空的
复制算法最佳使用场景:对于对象存活度较低的场景:新生区
4.3、标记清除
- 优点:不需要额外的空间!
- 缺点:两次扫描,严重浪费时间,会产生内存碎片
4.4、标记压缩
优化:可以先进行多次清除之后,在进行标记压缩
总结:
内存效率(时间复杂度):复制算法>标记清除算法>标记压缩算法
内存整齐度:复制算法=标记压缩算法>标记清除算法
内存利用率:标记压缩算法=标记清除算法>复制算法
GC:分代收集算法
年轻代:
- 存活率低
- 复制算法
老年代:
- 区域大:存活率高
- 标记清除算法和标记压缩算法混合实现