一、Java虚拟机内存模型
1、程序计数器:
每一线程都有一个独立的程序计数器,用于记录下一条要运行的指令。
2、Java虚拟机栈:
线程私有的内存空间,和Java线程在同一时间创建,保存方法的局部变量、部分结果,并参与方法的调用和返回。
可使用Jclasslib工具深入研究Class类文件的结构
3、本地方法栈:
管理本地方法的调用。在Sun的HotSpot虚拟机中,不区分本地方法栈和虚拟机栈。
4、Java堆:
几乎所有的对象和数组都是在堆上分配。分为新生代和老年代。其中新生代分为Eden和S0及S1。
5、方法区:
与堆空间类似,被JVM中所有的线程共享的。方法区主要保存的信息是累的元数据。
也可称为永久区,主要存放常量和类的定义信息。
二、JVM内存分配参数
1、设置最大堆内存
可以使用-Xmx参数指定。最大堆指的是新生代和老年代的大小之和的最大值,是Java应用程序的堆上限。
2、设置最小堆内存
使用-Xms设置系统的最小堆内存。
JVM会视图将系统内存尽可能限制在-Xms中,因此,当内存实际使用量触及-Xms指定的大小时,会触发FullGC。因此把-Xms值设置为-Xmx时,可以在系统运行初期,减少GC的次数和耗时。
3、设置新生代
参数-Xmn用于设置新生代大小。设置较大的新生代会减少老年代大小,影响系统性能。新生代大小一般设置为整个堆空间的1/4到1/3左右。
在HotSpot虚拟机中,-XX:NewSize用于设置新生代的初始大小,-XX:MaxNewSize用于设置新生代的最大值。通常只设置-Xmn即可,等同设置相同的-XX:NewSize和-XX:MaxNewSize。
4、设置持久代
不属于堆的一部分,使用-XX:MaxPermSize可以设置持久代的最大值,使用-XX:PermSize可设置持久代的初始大小。
5、设置线程栈
使用-XSS参数设置线程栈
6、堆的分配比例
-XX:MinHeapFreeRatio:设置堆空间最小空闲比例。当堆空间的空闲内存小于这个数值时,JVM会扩展堆空间。
-XX:MaxHeapFreeRatio:设置堆空间的最大空闲比例。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的值。
-XX:NewRatio:设置老年代和新生代的比例,它等于老年代除以新生代大小。
-XX:SurviorRatio:新生代中eden区与survivor区的比例。
-XX:TargetSurvivorRatio:设置survivor区的可使用率,当survivor区的空间使用率达到这个数值时,会将对象送入老年代。
三、垃圾收集基础
1、垃圾回收算法
①引用计数法:无法处理循环引用的问题,不适合用于JVM的垃圾回收。
②标记-清除算法
③复制算法——适用新生代
④标记-压缩算法(即标记-整理算法):——适用于老年代
⑤增量算法:让垃圾收集线程和应用程序交替执行。
⑥分代算法:新生代采用复制算法,老年代采用标记-整理算法。
2、垃圾收集器的类型
从不同角度分析垃圾收集器
线程数:串行垃圾回收器和并行垃圾回收器;
工作模式:并行垃圾回收器和并发垃圾回收器;
碎片处理:压缩垃圾回收器和非压缩垃圾回收器;
分代:新生代垃圾回收器和老年代垃圾回收期。
3、评价GC策略的指标
吞吐量、垃圾回收器负载、停顿时间、垃圾回收频率、反应时间、堆分配。
4、几种垃圾收集器
(1) 新生代串行收集器:最古老、最基本。采用复制算法。
特点:单线程垃圾回收,独占式。
在HotSpot虚拟机中,使用-XX:+UseSerialGC可以制定使用新生代串行手机和老年代串行收集器。
JVM在Client模式下允许,是默认的垃圾收集器。
(2)老年代串行收集器:标记-压缩算法。
-XX:+UseSerialGC:新生代、老年代都使用串行收集器。
-XX:+UseParNewGC:新生代使用并行收集器,老年代使用串行收集器。
-XX:+UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。
(3)并行收集器
工作在新生代的垃圾收集器,简单地将串行回收器多线程化。
-XX:+UseParNewGC:新生代使用并行收集器,老年代使用串行
-XX:+UseConMarkSweepGC:新生代使用并行收集器,老年代使用CMS
可使用-XX:ParallelGCThreads参数指定线程数量
(4)新生代并行回收收集器
使用复制算法,与并行收集器一样,都是多线程、独占式收集器。
主要特点:非常关注系统的吞吐量。
-XX:+UseParallelGC:新生代:并行回收,老年代:串行收集器。
-XX:+UseParallelOldGC:新生代和老年代都使用并行回收收集器。
可以通过-XX:MaxGCPauseMills和-XX:GCTimeRadio设置期望的停顿时间和吞吐量大小。
(5)老年代并行回收收集器
关注吞吐量,使用标记压缩算法,JDK1.6才可使用。
使用-XX:+UseParallelOldGC设置新生代和老年代都使用并行回收收集器。
(6)CMS收集器(Concurrent Mark Sweep)
特点:关注系统停顿时间,并发标记清除算法,是多线程并行回收的垃圾收集器。
主要步骤:初始标记、并发标记、重新标记、并发清理、并发重置。
通过-XX:CMSInitatingOccupancyFraction可以指定当老年代空间使用率达到多少进行一次CMS垃圾回收;
使用-XX:+UseCMSCompactAtFullCollection开关使CMS在垃圾回收后进行内存压缩;
使用-XX:+CMSFullGCsBeforeCompaction参数设定进行多少次CMS回收后,进行一次内存压缩。
(7)G1回收器
是目前最新的,实验性产品,吞吐量和停顿控制优于CMS,基于标记-压缩算法。
使用-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC启用G1回收器。
-XX:MaxGCPauseMillis=50
-XX:GCPauseInterralMills=200
指定在200ms内,停顿时间不超过50ms。折两个参数是G1回收器的目标,并不保证能执行。
眼见的吹翻了这家,吹伤了那家,只吹的水尽鹅飞罢!