1. JVM运行时数据区
除了方法区和堆属于线程共享,其它属于线程私有。
1.1. 程序计数器
Java文件经过javac
编译成字节码文件后,通过字节码解释器执行字节码指令时,存在线程上下文切换。程序计数器用于记录字节指令的行号,这样线程上下文切换之后,字节码解释器才会记得上一个线程执行到哪个位置。
1.2. 虚拟机栈
- Java方法
- 递归调用方法存在
StackoverflowError
- 操作数栈,动态链接
- 疑问:频繁出栈和入栈是否会影响应用性能?
1.3. 本地方法栈
非Java方法
举例:CAS是一条CPU原子指令,类似数据库乐观锁的作用,JUC。
1.4. 方法区
存储类信息,常量(常量池,hashSet实现不允许重复),静态变量等。
存在OM
1.5. 堆
1)负责数组和实例对象创建和存储(分配内存)。
2)存在OM
3)堆结构:
- 新生代
- Eden 8
- Survivor 2
- Survivor From 1
- Survivor To 1
- 老年代
4)-Xmx -Xms
5)HotSpot 使用永久代实现方法区,目的是想让GC管理这块内存。
6)即便JVM提供自动分配和释放内存,程序依然存在内存泄漏和内存溢出的问题。
2. 对象创建流程
2.1. 检查
- 若常量池中存在类符号引用,则类已加载,直接分配内存
2.2. 加载
2.3. 分配内存
- 指针碰撞
- 空闲列表 CAS
2.4. 初始化
2.5. 执行<init>
- static代码块
3. Java对象内存布局
3.1. 对象头
3.2. 实例数据
3.3. 对齐填充
4. 如何访问对象
4.1. 直接指针访问
- 访问效率高,不方便GC回收
4.2. 对象句柄访问
- 方便GC回收,访问效率低
5. GC回收如何对象?
- 配置虚拟机启动参数。配置参数之后,程序运行期间,若发生GC,就会打印GC日志详情。
vm options: -verbose:gc -XX+PrintGcDetails
- 在程序中通过调用静态方法,触发GC
System.gc();
5.1. 引用计数法
- 优点是简单方便,缺点是无法检测循环引用。
5.2. 可达性分析法
- GCRoute,引用链
- HotSpot 采用这种方式。
6. 垃圾回收算法
6.1. 标记清除算法
- 被标记的垃圾:不存在引用链
- 存在问题:1)清除之后的内存是不连续的。2)标记和清除效率低。
6.2. 复制算法
- 两大内存区域(Eden、Survivor),搬运
- 主要负责回收新生代对象。这是因为新生代区域内大部分对象是会被回收的,只有少部分对象需要被保留,被保留到Survivor中。
- Survivor To 用来保存 Eden 和 Survivor From 存活的对象,然后再转移到 Survivor From ,等待第二次回收。
- 若Survivor To 空间不足时,采取分配担保,将对象转移到老年代。
6.3. 标记-整理算法
- 覆盖,然后清除垃圾???
- 适用于老年代
6.4. 分代收集算法
- 新生代使用复制算法,老年代使用标记-整理算法或标记清除算法
7. 垃圾回收器
7.1. Serial
- 用户线程,GC线程
- stop the work
- 单线程,垃圾回收时,必须暂停其它工作线程,直到垃圾回收结束。
- 客户端
- 适用于桌面端应用。因为桌面端应用内存小,回收时间比较短,只要不太频繁就可以接受。
7.2. ParNew
- Serial 多线程版本
- stop the work
- 服务器端
- 使用
-XX:ParallelGCThreads
参数限制垃圾收集的线程数,对应CPU核数。线程数太多导致频繁的上下文切换,浪费资源。 - 并行和并发
- 适用于新生代
- 多线程操作存在上下文切换问题。若电脑是单核CPU,那么使用Serial效率更高,若电脑是多核CPU,那么建议使用 ParNew并行处理,要注意限制垃圾收集的线程数,尽量避免不必要的上下文切换。
7.3. Parallel Scavenge
- 新生代收集器 复制算法
- stop the work
- 并行多线程垃圾回收器(与ParNew一样)
- 吞吐量优先
- 设置GC停顿时间,较小会发生频繁GC
- 设置吞吐量 99%,用户线程占99%,合适时性能最优
7.4. Serial old
- 单线程
- 老年代
- 标记-整理算法
- Serial 使用复制算法,Serial old 使用标记-整理算法
7.5. Parallel old
- 多线程,并行
- 老年代
- 标记-整理算法
- Parallel Scavenge 使用复制算法,Parallel old 使用标记-整理算法
7.6. CMS
- 并发标记和并发清除能够与用户线程一起执行。
- 初始标记和重新标记 stop the work
- 最短回收停顿时间
- BS架构常用这种方式。
- 单核CPU没有优势
- 标记清除算法存在内存碎片
网友评论