Class文件结构
魔数
主次版本号
常量池
访问标志
类索引
字段表
方法表
属性表
类加载
类加载过程:加载、验证、准备、解析、初始化。
加载:将class文件以二进制文件流的形式加载到JVM
验证:文件格式验证、元数据验证、字节码验证和符号引用验证
准备:
解析:
初始化:
双亲委派模型
向上委托、向下委派。好处:保证程序的安全性、类加载的顺序性。
启动类加载器:加载JAVA_HOME/lib目录下的类
扩展累加载器:加载JAVA_HOME/lib/ext目录下的类
应用类(系统类)加载器:
自定义类加载器:
运行时数据区
运行时数据区包括:程序计数器、堆、方法区、虚拟机栈、本地方法栈
堆、方法区是线程共享的;程序计数器、虚拟机栈、本地方法栈都是线程私有的;
堆:线程共享;唯一目的是存放对象实例。在空间不足时会抛出OOM异常。通过-Xmx和-Xms设置初始容量和最大容量。
方法区:线程共享。用以存储虚拟机加载的类型信息、常量......
运行时常量池:方法区的一部分。
栈帧:用以支持虚拟机进行方法调用和方法执行背后的数据结构。存储了方法的局部变量表、操作数栈、动态链接和方法返回地址。
调用一次方法生成一个栈帧。本地方法栈是为了JNI(调用本地方法)服务。
垃圾回收
可达性分析算法
“GC Roots”作为起始节点,根据引用关系向下搜索,搜索所走过的路径成为“引用链”;
GC Roots有哪些
- 虚拟机栈中引用的对象;
- 方法区中静态属性引用的对象;方法区中常量引用的对象;
- Sync锁持有的对象;
- Java虚拟机中内部使用的引用。
引用类型
强、软、弱、虚
软引用:在空间不足时,会被回收。有用对象但不是必须的。
弱引用:最多存活到下次GC。
虚引用:幽灵引用,最弱的引用方式,不影响。
对象不可达后一定会被回收吗?
分代收集理论
弱分代假说:大部分对象都是朝生夕死;
强分代假说:熬过越多次收集的对象越不容易消亡;
跨代引用:跨代引用占比极少;
垃圾回收算法
标记清除
标记复制
标记整理
安全点
GC时需要所有线程到达安全点,例如:方法调用、循环跳转、异常跳转
记忆集和卡表
用以解决“跨代引用”问题
三色标记
白色:对象不可达;
黑色:对象存在引用;
灰色:还没扫描完成(并发标记可能产生新引用指向对象)
垃圾收集器
年轻代(新生代)
Serial:一个线程工作的收集器(指在GC时必须暂停其他线程);
ParNew:实质上是Serial的多线程版本;
Parallel Scavenge:关注吞吐量的收集器。
老年代收集器
Serial Old:采取标记-整理算法。基本废弃。
Parallel Old:标记-整理。与Parallel Scaveng配合,关注吞吐量。
CMS
CMS是一种以最短回收停顿时间为目标的收集器,基于标记-清除。
收集过程:
a. 初始标记:需要“stop the world”,仅标记GC Roots,速度极快;
b. 并发标记:遍历整个对象图,耗时较长;与用户线程并发执行。
c. 重新标记:“stop the world”,
d. 并发清除:“stop the world”
G1--Garbage First
开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。
G1仍然遵循分代收集理论,每一个Region都可以根据需要,成为eden、s、或老年代,根据不同类型的Region进行不同的处理策略。还有一类特殊区域,H区,专门用来存储大对象。超过region区域一半大小的对象就是大对象,region空间大小可以通过-XX:G1HeapRegionSize设定,取值范围为1M-32M。
G1可预测停顿时间。
G1执行过程:
初始标记:
并发标记:
最终标记:
筛选回收:可以根据计算的回收效益来筛选回收。
内存分配策略
一个对象从Eden,经过15次MinorGC到老年代的过程。。。
哪些情况下对象会进入老年代
大对象直接进入老年代;
长期存活的对象(默认15岁)也将进入老年代;
其他一些情况,如:年龄相同的对象占所有对象大小的一半以上,该年龄及以上的对象进入老年代。