JVM
JVM
jvm笔记
类加载器
启动类加载器(Bootstrap):
在Java环境下看不到,核心类
扩展类加载器(Extension):
扩展功能的一些 jar 包,类似第三方
应用类加载器(AppClassLoader):
程序员自己写的类
双亲委派机制
从上到下加载
先到启动类加载器查找,找到,执行,找不到,向下查找
如果应用程序类加载器同样找不到要加载的类,那么会抛出ClassNotFoundException
- 避免类的重复加载:父加载器加载了一个类,就不必让子加载器再去查找了。同时也保证了在整个 JVM 范围内全类名是类的唯一标识。
- 安全机制:避免恶意替换 JRE 定义的核心 API
方法栈
方法栈并不是某一个 JVM 的内存空间,而是我们描述方法被调用过程的一个逻辑概念。
栈帧
方法在本次执行过程中所用到的局部变量,形参等信息
- 本地变量(Local Variables):输入参数和输出参数以及方法内的变量。
- 栈操作(Operand Stack):记录出栈、入栈的操作。
- 栈帧数据(Frame Data):包括类文件、方法等等
栈帧的结构
方法每调用一次就生成一个栈帧
- 局部变量表:方法执行时的参数、方法体内声明的局部变量
- 0下标是this占用
- 操作数栈:存储中间运算结果,是一个临时存储空间
- 帧数据区:保存访问常量池指针,异常处理表
栈空间的线程私有
线程对栈内存空间的使用方式是彼此隔离的。每个线程都是在自己独享的空间内运行
某个栈溢出异常不会影响其他栈
堆空间
- 新创建的对象:进入 Eden 区。
- Eden 区的对象经过 GC 后没有被释放:进入 Survivor 区。
- Survivor 区分成 from 区和 to 区两个部分。
- Survivor 区在执行 GC 时:
- 将不释放的对象从 from 区复制到 to 区。
- 将 from 区整个标记为空闲。
- 交换 from 和 to 这两个指针。
- 口诀:复制必交换,谁空谁为 to。
- 新生代中的对象默认经历 15 次 GC 后,如果还幸存,则直接进入老年代。
- 如果幸存者区已经满了,即使某个对象尚不到 15 岁,仍然会被移动到老年代
垃圾回收
不再使用或获取不到的对象是垃圾对象。
没有引用的对象就是要清理的对象
GC 算法
内存碎片
不连续的存储空间
程序暂停(stop the world)
标记清除法
堆中的有效内存空间被耗尽的时候,就会暂停、挂起整个程序
标记:从根对象开始遍历所有的对象,然后将所有存活的对象标记为可达的对象。
清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。
- 优点:实现简单
- 缺点:效率低,因为标记和清除两个动作都要遍历所有的对象
- 垃圾收集后有可能会造成大量的内存碎片
- 垃圾回收时会造成应用程序暂停
复制算法
将原有的内存空间一分为二,
from区和to区,to区每次都是空的
每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另一个内存空间中,并依次排列,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收。
- 优点2:清理后,内存无碎片
- 缺点:浪费了一半的内存空间