JVM内存管理
JVM内存管理,一般是指 堆内存(Heap)的管理,因为栈(stack)、PC寄存器(PC Register)、本地方法栈(Native Method Stack)都是和线程一样的生命周期
栈
-Xss 设置栈内存大小
栈是不需要垃圾回收的,尽管说垃圾回收是java内存管理的一个很热的话题,栈中的对象如果用垃圾回收的观点来看,他永远是live状态,是可以reachable的,所以也不需要回收,他占有的空间随着Thread的结束而释放
堆
堆内存分为以下几个区:
Old Space 、 Eden 、From Space、To Space
其中 Eden区里面存着是新生的对象,From Space和To Space中存放着是每次垃圾回收后存活下来的对象,所以每次垃圾回收后,Eden区会被清空。 存活下来的对象先是放到From Space,当From Space满了之后移动到To Space。当To Space满了之后移动到Old Space。Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来的对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor复制过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,jvm提供对Survivor区复制次数的配置(-XX:MaxTenuringThreshold参数),即经过多少次复制后仍然存活的对象会被放到老年区,通过增加两个Survivor区复制的次数可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。
-Xms和-Xmx来指定堆内存最小值和最大值
通过-Xmn来指定Young Generation的大小
通过-XX:NewRatio来指定Eden区的大小,在Xms和Xmx相等的情况下,该参数不需要设置
通过-XX:SurvivorRatio来设置Eden和一个Survivor区的比值
垃圾回收
JVM中会在以下情况触发回收
-
对象没有被引用
-
作用域发生未捕捉异常
-
程序正常执行完毕
-
程序执行了System.exit()
-
程序发生意外终止
如何确定某个对象是垃圾
1.引用计数法:对象配备一个整形计数器,引用一次+1,引用失效-1,计数器=0,表示对象不再被使用
2.可达性分析:GC Roots,如果一个对象不能达到GC Roots的时候,说明可以被回收
垃圾回收算法
1.标记清除法:标记阶段(标记出所有可达对象),清除阶段(回收未被标记的对象所占用的空间) 标记清除法2.复制算法:将内存容量分成两块,每次只使用其中一块,当这块内存用完的时候,将存活的对象复制到另外一块,然后再把已使用的内存空间一次性清理掉 复制算法注意:标记清除算法先通过根节点标记所有可达对象,然后清除所有不可达对象,完成垃圾回收
缺点:效率低,内存碎片化严重(后续大对象找不到可利用的空间)
3.标记整理法:与标记清除法一样,区别在与完成标记后,不是直接清理可回收对象,而是将存活对象都移向内存的一端,然后清理掉端边界以后的内存 标记整理法优点:算法实现简单,效率高,不易产生碎片
缺点:内存使用空间被压缩到一半
注意:标记整理算法的最终效果等同于标记清除算法执行完成后,再进行一次内存碎片的整理,因此也叫标记清除压缩算法
4.分代收集法:
核心思想:根据对象的存活生命周期将内存划分为若干不同的区域
新生代:每次垃圾回收时都有大量对象被回收
老年代:每次垃圾回收时只有少量对象需要被回收
新生代一般采用复制算法
老年代采用标记整理算法
注意:在堆之外还有一个永久代(Permanent Generation),它用来存储class类,方法,常量描述等。对永久代的回收主要包括废弃常量和无用的类
垃圾收集器
新生代垃圾收集器有Serial、ParNew、Parallel Scavenge,G1,属于老年代的垃圾收集器有CMS、Serial Old、Parallel Old和G1.其中的G1是一种既可以对新生代对象也可以对老年代对象进行回收的垃圾收集器。
Serial 单线程垃圾收集器,针对新生代的收集器,采用复制算法
ParNew Serial收集器的多线程版本,采用复制算法,伴随着CPU数量的增加,收集效率也会大大增加
Parallel Scavenge 并行收集器,采用复制算法,关注系统吞吐量
G1收集器(整个Java堆:包括新生代和老年代)
特点
并行与并发
分代收集(仍然保留了分代的概念)
空间整合(整体上属于“标记-整理”算法,不会导致空间碎片)
可预测的停顿(比CMS更先进的地方在于能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒)
Serial Old serial的老年代版本,采用标记整理算法 单线程
Parallel Old Parallel Scavenge的老年代版本,采用标记整理算法 多线程
CMS收集器 以最小回收时间停顿为目标的并发回收器,采用标记清除算法
垃圾收集器一览表
名称 | 收集目标 | 算法 | 线程支持 | 其他 |
---|---|---|---|---|
Serial | 新生代 | 复制算法 | 单线程 | 单线程收集器 |
Serial Old | 老年代 | 标记整理算法 | 单线程 | Serial的老年代版本 |
ParNew | 新生代 | 复制算法 | 多线程 | Serial收集器的多线程版本,可与CMS配合使用 |
Parallel Scavenge | 新生代 | 复制算法 | 多线程 | 类似ParNew收集器,更关注系统吞吐量 |
Parallel Old | 老年代 | 标记整理算法 | 多线程 | 与Parallel Scavenge收集器配合使用,特点:“吞吐量优先”,在注重吞吐量和CPU资源敏感的场合,都可以使用这个组合 |
CMS收集器 | 老年代 | 标记清除算法 | 多线程 | 以最小回收时间停顿为目标的并发回收器 |
G1 | 新生代、老年代 | 标记整理算法 | 多线程 | 面向服务端的收集器,能充分利用CPU和多核环境; 并行与并发收集器,它能够建立可预测的停顿时间模型。 |