3 垃圾收集器与内存分配策略

来源:互联网 发布:centos python3 编辑:程序博客网 时间:2024/04/30 12:43

概述:

程序计数器,虚拟机栈,本地方法栈三个区域随着线程而生,随着线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题没因为方法结束或者线程结束时,内存自然就跟着回收了。而java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,这部分内存的分配和回收是动态的。垃圾收集器所关注的是这部分内存。

判断对象是否已死

引用计数法:给对象中添加一个引用计数器,每当有一个地方引用它,计数值就加一;当引用失效时就减一;任何时刻计数器值为零的对象就是不可能再被使用的。
引用计数算法的实现简单,判定效率也很高,在大部分情况下它都是一个不错的算法。但是,至少在主流java虚拟机里面没有选用引用技术算法来管理内存,其中最主要的原因就是它很难解决对象之间相互循环引用的问题。
可达性分析算法:这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这这些节点向下搜索,搜索所走过的路径称为引用链(Reference chain),当一个对象到GC Roots没有任何引用链相连时(用图论的话来说,就是从GC Roots到这个对象不可达),则证明此对象是不可用的。
关于引用
在JDK1.2以前java中的引用的定义很传统:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块地址代表着一个引用。
在JDK1.2以后,java对引用的概念进行了扩充,将引用分为,强引用,软引用,弱引用,虚引用四种。
对象回收过程要经历两次标记阶段,如果第一次标记之后能被引用则可以移除回收标记。
关于Finalize方法
不要依赖Finalize方法释放资源。
垃圾收集算法
1标记-清除算法
算法分标记和清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有标记的对象。主要不足有两个:一个是效率问题,标记和清除两个过程的效率都不高。另一个是空间问题,标记清除后会有大量不连续的内存碎皮,导致以后再程序运行中需要分配比较大对象时,无法找到足够的连续内存而不得不处罚另一次垃圾收集动作。
2复制算法
为了解决效率问题,一种称为“复制”的收集算法出现了,它将可用内存容量划分为大小相等的两块,每次只使用其中一块。当这一块内存用完了,就将还存在的对象复制到另一块上面,然后再把已经使用过的内存空间一次清理掉。(据研究表明虚拟机中新生代的98%的对象是朝生夕死的)
现在的商业虚拟机都采用这种收集算法来回收新生代。HotSpot虚拟机默认Eden和Survior大小比例为8:1,新生代中可用内存为整个新生代容量的(80%+10%),只有10%的内存会被“浪费”,但也可能存在存活对象大于10%的情况,所以当survior空间不够用时,需要依赖其他内存进行担保分配(直接进入老年代内存空间)。

3标记-整理算法
复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。而且老年代对象存活率较高不能直接采用这种算法。
根据老年代的特点,提出了“标记-整理”算法,标记过程跟标记-清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端易懂,然后直接清理掉端边界以外的内存。
4分代收集算法
当前商业虚拟机的垃圾收集都采用“分代收集”,根据存活周期的不同将内存划分为几块,一般是把java堆分为新生代和老年代,,这样可以根据各个年代的特点采用最适合的收集算法。
垃圾收集器
Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商,不同版本的虚拟机所提供的垃圾收集器可能会有很大的差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所有的收集器。
Serial收集器
ParNew收集器
Parallel Scavenge收集器
Serial Old收集器
CMS收集器
G1收集器
以上收集器各有特点,如高并发,低停顿,高吞吐..

内存分配策略

Java技术体系中所提倡的自动内存管理最终可以归结为自动化的解决了两个问题:给对象分配内存以及回收分配给对象的内存。
对象的内存分配,往大方向上讲,就是在堆上分配(但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配)对象主要分配在新生代的Eden区上,少数情况下也可能会直接分配在老年代中,分配的规则不是百分百固定,取决于垃圾收集器组合及虚拟机中与内存相关的参数设置。
以下是最普遍的内存分配规则:
1 对象优先在Eden区分配
2 大对象直接进入老年代
3 长期存活的对象将进入老年代
4 动态对象年龄判定 (即判定老年代的标准是动态的)
5 空间分配担保

小结:内存回收和垃圾收集器在很多时候都是影响系统性能,并发能力的主要因素之一,虚拟机之所以提供多种不同的收集器以及大量的调节参数,是因为只有根据实际应用实现方式选择最优的收集方式才能获取最高的性能。

0 0
原创粉丝点击