JAVA——GC

来源:互联网 发布:试发型的软件 编辑:程序博客网 时间:2024/06/05 19:10

GC(资源回收机制)

一、GC工作机制

分配对象使用new关键字,对象创建时,GC就开始监控这个对象的地址、大小以及使用情况.

 

释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间.

 

GC采用有向图的方式记录和管理堆(heap)中的所有对象,回收算法不固定,时间不固定.

 

GC在JVM中通常是由一个或一组进程来实现的,它本身也和用户程序一样占用heap(堆)空间,运行时也占用CPU.当GC进程运行时,应用程序停止运行.

 

GC工作表现: GC运行时间长,java程序停顿时间长,回收率高,内存占用率低

GC工作时间短,java程序不卡顿,回收率低

GC回收算法设计:平衡停顿时间和回收率

 

增量式GC:

   增量式GC就是通过一定的回收算法,把一个长时间的中断,划分为很多个小的中断,通过这种方式减少GC对用户程序的影响

算法:Train GC算法:

   将堆中的所有对象按照创建和使用情况进行分组(分层),将使用频繁高和具有相关性的对象放在一队中,随着程序的运行,不断对组进行调整,先回收最近很少访问可回收的对象或对象组

 

二、程序如何与GC进行交互

引用强度:可达对象(被使用)>Soft>Weak>Phantom>不可达对象(NULL)

import java.lang.ref包:

SoftReference :只有在内存不够时,才回收这类内存,通过算法检查---->实现常用图片的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory

WeakReference Weak引用对象更容易、更快被 GC回收,GC在运行时一定回收Weak对象---->Weak引用对象常常用于Map结构中,引用数据量较大的对象,一旦为Null,立即回收

PhantomReference:不常用,辅助 finalize函数(只能执行一次)的使用,覆写Phantom对象的clear()方法以增加GC灵活性

 

三、编程习惯

尽早释放无用对象的引用,包括集合数据类型

尽少采用finalize方式回收资源

若需要使用经常使用的图片,可以使用soft应用类型,可以尽可能将图片保存在内存中,供程序调用,而不引起OutOfMemory.

注意全局变量和静态变量的使用,避免引起悬挂对象,造成内存浪费

System.gc()

使用增量式GC

 

四、堆内存:(队列)

   作用:程序运行时动态申请某个大小的内存空间

   新生代:刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中

   老年代:如果某个对象经历了几次垃圾回收之后还存活,就会被存放到老年代中

 

五、GC回收算法

1.追踪回收算法(tracing collector):

从根结点开始遍历对象的应用图。同时标记遍历到的对象。遍历完成后,没有被标记的对象就是目前未被引用,可以被回收。

2.压缩回收算法(Compacting Collector)?

把堆中活动的对象集中移动到堆的一端,就会在堆的另一端流出很大的空闲区域。这种处理简化了消除碎片的工作,但可能带来性能的损失。

3.复制回收算法(Coping Collector)

把堆均分成两个大小相同的区域,只使用其中的一个区域,直到该区域消耗完。此时垃圾回收器终端程序的执行,通过遍历把所有活动的对象复制到另一个区域,复制过程中它们是紧挨着布置的,这样也可以达到消除内存碎片的目的。复制结束后程序会继续运行,直到该区域被用完。

但是,这种方法有两个缺陷:

   (1)对于指定大小的堆,需要两倍大小的内存空间,

   (2)需要中断正在执行的程序,降低了执行效率

4.按代回收算法(Generational Collector)?

把堆分成若搞个子堆,每个子堆视为一代,算法在运行的过程中优先收集“年幼”的对象,如果某个对象经过多次回收仍然“存活”,就移动到高一级的堆,减少对其扫描次数

 

六、Java内存

1.私有内存区:私有内存区伴随线程的产生而产生,一旦线程中止,私有内存区也会自动消

(1)程序计数器

(2)虚拟机栈: 栈帧存储局部变量表(基本数据类型、对象引用、返回地址)、操作数栈、动态链接、方法返回地址和一些额外的附加信息。程序执行时栈帧入栈;执行完成后栈帧出栈

(3)本地方法栈:执行本地方法

2.共享内存区:

(1)方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。但是已经被最新的 JVM 取消了。现在,被加载的类作为元数据加载到底层操作系统的本地内存区

(2)Java堆:所有线程共享,几乎所有的对象实例和数组都在这类分配内存

原创粉丝点击