笔记:Java 性能优化权威指南 第3章 JVM概览

一、JVM 的基本架构

JIT编译器 (Just-In-Time Compiler, 即时编译器):Client 或 Server

垃圾收集器:Serial、Parallel、CMS、G1

JVM Runtime:


32 位JVM 的最大内存约为2.5~3G .

64 位JVM 的指针压缩:-XX:+UseCompressedOops。64位寻址导致JVM内部Java对象表示(oops)的长度由32位变为64位,导致CPU高速缓存行中可用的oops变少,降低了CPU缓存的效率,使用压缩可以避免带来的损失。


二、JVM  Runtime

命令行选项:     -X 非标准项 ,  -XX 非稳定项 

VM 生命周期:  启动、执行程序、检查和清理未处理异常、退出

VM 类加载:

字节码验证:

类数据共享:

解释器:

异常处理:

线程管理:

C++堆管理:

Java本地接口:

JVM致命错误管理:

三、JVM 垃圾回收 


1、分代垃圾收集


弱分代假设:大多数分配对象的存活时间很短;存活时间久的对象很少引用存活时间短的对象。


新生代:一个Eden、两个Survivor。Minor GC 效率很。

老年代:Full GC  执行频率低,执行时间长。

永久代:存储元数据,例如类的数据结构、保留字符串等。


过早提升:Survivor中的存活对象溢出,多余的对象将被移到老年代,导致老年代中短期存活对象的增长,可能造成严重的性能问题。

提升失败:在Minor GC 中,如果老年代满了而无法容纳更多的对象,Minor GC 后将发生 Full GC。

  

2、垃圾收集器


Servial 收集器:   单线程。

新生代用复制算法,老年代使用标记-压缩算法。


Parallel 收集器: 吞吐量为先。

新生代用复制算法,老年代使用标记-压缩算法。

适用于批处理引擎、科学计算等。


CMS 收集器:      低延迟为先。

老年代使用标记-清理算法。

分为阶段:初始标记、并发标记、重新标记、并发预清除、并发清除

CMS 的缺点

a、空间不连续,需要一个空闲列表记录;

b、需要更大的Heap处理浮动垃圾;

c、缺乏压缩,形成空间碎片化。

如果CMS 失败,将采用Stop-The-Worl 收集方法。


G1 收集器:          CMS的替代者。G1中Heap不再划分成新生代、老年代,而是分为相同尺寸的区,优先收集垃圾最多的区。


3、应用程序对垃圾收集器的影响


内存分配:Eden满,发生Minor GC;老年代满,发生Full GC;内存分配速率越高、垃圾收集触发越频繁。


存活数据的多少:Heap 中存活对象越多,收集器需要做的工作越多。


老年代中的引用更新:若老年代中引用发生了更新,将创建一个Old-to-Young的引用,导致在预清除或重新标记阶段产生一个需要遍历的对象。一些不好的编程习惯会造成这个问题:对象池化(对象长期存活)、容器类的初始尺寸太小(内部数组需要长期调整尺寸)等。


四、JIT编译器

Client  JIT:  启动快、编译快

Server JIT: 启动慢,但是启动后性能好,吞吐量高。


五、JVM自适应调优

Java 6 的自适应调优

32 位Linux 下 Client 模式:-client、SerialGC、-Xms(8M, 6M,1/64 RAM)、-Xmx(1/4 RAM)

64 位Linux 下 Client 模式:-server、ParallelGC、-Xms(1/64 RAM)、-Xmx(1/4 RAM - 1G)


32 位Linux 下 Server模式:-server、ParallelGC、-Xms(1/64 RAM)、-Xmx(1/4 RAM -1G)

64 位Linux  下 Server模式:-server、ParallelGC、-Xms(1/64 RAM)、-Xmx(1/4 RAM -1G)


Throughout 收集器自动调整新生代空间: -XX:+UseAdaptiveSizePolicy





原文地址:https://www.cnblogs.com/leeeee/p/7276281.html