内存分配与回收_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 内存分配与回收

内存分配与回收

 2011/12/1 8:39:16  Fhappy  http://fhappy.iteye.com  我要评论(0)
  • 摘要:一、垃圾收集算法1、最常见的判断对象是否存活的方法有引用计数法和根搜索算法。(1)引用计数法中,每一个对象都有一个引用计数器,当它被引用时,计数器+1,当一个引用释放时,计数器的值-1。引用计数法的特点是简单、高效,但是它解决不了对象间互相引用的问题。(2)根搜索算法:从根集合出发,根据引用关系,不断地往下搜索。搜索路径就构成了引用链,在引用链上的对象都是存活对象。而根集合通过引用链到达不了的对象(从图论的角度看,即是不可达的对象),就是不会再被使用的对象,可以被回收。根集合包含的范围有
  • 标签:内存分配

?

一、垃圾收集算法

1、最常见的判断对象是否存活的方法有引用计数法和根搜索算法。

(1)?引用计数法中,每一个对象都有一个引用计数器,当它被引用时,计数器+1,当一个引用释放时,计数器的值-1。引用计数法的特点是简单、高效,但是它解决不了对象间互相引用的问题。

(2)?根搜索算法:从根集合出发,根据引用关系,不断地往下搜索。搜索路径就构成了引用链,在引用链上的对象都是存活对象。而根集合通过引用链到达不了的对象(从图论的角度看,即是不可达的对象),就是不会再被使用的对象,可以被回收。

根集合包含的范围有:

① 虚拟机栈中的引用对象(栈帧中的本地变量表)。

② 方法区中的常量池中的引用对象(包括类静态属性引用对象、常量属性引用对象)。

③ 本地方法栈中引用的对象。

?

2、垃圾收集算法

1)?复制算法

内存划分为同样大小的两份,每一次都只使用其中的一块内存,进行垃圾回收时,将该内存中存活的对象复制到另一块备用内存中,然后清除该块内存,作为下次垃圾回收时的备用内存。

2)?标记-清除法

? ? 每一次垃圾回收时,先将非存活对象标记,然后将这些非存活对象从内存中清除。此方法会产生空间碎片。

3)?标记-整理法

? ? 该方法在标记-清除的基础上,增加了整理步骤。每一次垃圾回收时,先将非存活对象标记,然后将这些对象从内存中清除,最后再将存活对象向内存的一端移动。避免产生大量的空间碎片。

?

?

二、Java虚拟机规范中内存区域划分

1、在Java虚拟机规范中,将内存区域划分为:

① Java虚拟机栈

每一个线程都在该区域创建一个栈,栈中包含栈帧(一般的,一个方法对应一个栈帧),栈帧中包含了本地变量表、操作数栈、动态链接,其他栈帧信息等。

② 本地方法栈

本地方法栈与Java虚拟机栈类似,在Sun?Spot的虚拟机实现中,该区域与Java虚拟机栈合并在一起。

③ 方法区

方法区中存放了与类有关的信息,比如类的名字,全限定名,继承的父类,实现的接口,属性等。

④ 程序计数器

指示当前执行的和下一条要执行的指令的位置。(字节码流中字节的相对偏移量)。

⑤ 

实例化的对象都是放在这个区域。进行垃圾回收的主要区域。

2、Sun?Spot的虚拟机实现中,堆中区域细分

a)?新生代。新生代又细分为EdenSurvivor1Survivor2

b)?老年代(或称旧生代)

?

三、垃圾收集器

1、新生代上的垃圾收集器

a)?Serial收集器

i.?串行收集器(单线程收集器),只有一个线程进行垃圾回收,当进行垃圾回收时,要将所有用户线程暂停。该收集器采用复制算法回收垃圾。

b)?ParNew收集器

i.?并行收集器,收集器采用多线程同时进行垃圾回收,但是当进行垃圾回收时,也要将所有用户线程暂停。采用复制算法回收垃圾。

c)?Parallel?Scavenger收集器

i.?并行回收收集器,与ParNew收集器一样是多线程的,但是它的侧重点与ParNew不同,Parallel?Scavenger注重的是吞吐量(用户程序占用CPU的时间与CPU总运行时间的比,[用户程序执行时间/(用户程序执行时间+垃圾回收执行时间)]),所以又称“吞吐量优先收集器”。采用复制算法回收垃圾。

2、老年代上的垃圾收集器

a)?Serial?Old收集器

i.?因为采用“标记-整理”算法进行垃圾回收,所以又称MSCMark-Sweep-Compact)收集器。串行回收垃圾,进行垃圾回收时,会暂停所有用户线程。

b)?Parallel?Old收集器

i.?它是Parallel?Scavenger的老年版本,属于多线程收集器,采用标记-整理算法。在回收垃圾时,也会暂停用户线程。

c)?CMS收集器

i.?并发收集器,采用“标记-整理”算法进行垃圾回收。CMS收集器的垃圾回收线程可以跟用户线程并发执行。

ii.?垃圾回收包含四个阶段:

1.?初始标记:标记一下GC?Roots可以直接关联到的对象,需要暂停用户线程,但是该过程速度很快;

2.?并发标记:进行根搜索的过程,与用户程序并发运行;

3.?重新标记:因为在并发标记的时候,用户程序和并发标记时同时进行的(单CPU条件下交替执行),为了修正并发标记期间,因用户程序继续运行而导致标记变动的那部分对象的标记记录。该阶段需要暂停用户线程。

4.?并发清除:清除垃圾对象,该过程与用户程序并发运行。

?

四、内存分配与回收策略

简要介绍几种基本的内存分配与回收策略。

1.?对象优先分配在Eden区域

在程序运行时,大部分对象都是朝生夕死的。将新创建的对象存放在新生代的Eden区域,那些存活期短的对象很快就可以被回收掉,有利于快速、高效地回收利用有限的内存。

2.?大对象直接分配在老年代

将大对象(比如说大数组)直接分配在老年代,是考虑到如果大对象分配在新生代而此时对象的存活期较长,那么新生代收集器采取复制算法进行垃圾回收时,复制大对象的成本将会很高(显然大对象的复制时间会比较长)。

3.?长期存活对象将进入老年代

某一个对象在每一次执行Minor?GC(新生代垃圾回收)都能存活下来,即这个对象的存活时间比较长,那么在每一次Minor?GC时它都会从From?Survivor复制到To?Survivor,为了避免长期存活的对象一次次的被复制,JVM采取的策略是在每一次Minor?GC后存活下来的对象的年龄就增加一岁,当它的年龄增加到一定程度时,就会被晋升到老年代中。

4.?动态对象年龄判定

为了更好地适应不同程序的运行,虚拟机并不总是要求对象存活年龄达到某一阈值才晋升到老年代中。动态对象年龄判定策略指的是:当Survivor区域中某一年龄的所有对象占Survivor区域的一半以上时,该年龄以及该年龄以上的对象将直接晋升到老年代中。

发表评论
用户名: 匿名