Java垃圾回收机制

来源:互联网 发布:工业大数据 李杰 下载 编辑:程序博客网 时间:2024/06/16 05:02

Java垃圾回收机制

参考;

https://mp.weixin.qq.com/s?__biz=MzIwODI3MTc2Ng==&mid=2649647405&idx=1&sn=46a48cedd1540a994cd316ca164e005a&chksm=8f1f69d4b868e0c25245676ac55dc8d1fcad3dfa4bc63a2e0835b0a1155f1d2320a45a7c7078#rd

 

java中几个常见的存储区域:

1.        方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域,叫做方法区。

2.        常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。

3.        堆区:用于存放类的对象实例,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 堆中不存放基本类型和对象引用,只存放对象本身 

4.        栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构,栈桢中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时,虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。

 

简介

安卓采用的是引用计数的方法来判断对象是否该回收:

优点:简单,高效,现在的objective-c用的就是这种算法。
缺点:很难处理循环引用,相互引用的两个对象则无法释放。

回收的对象包括:

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

l  方法区中的类静态属性引用的对象。

l  方法区中的常量引用的对象。

l  本地方法栈中JNI(Native方法)的引用对象

这里和堆区没有关系,只关系到栈区和方法区。

对象引用模型:


创建对象之之后会建立它所对应的引用树。

常见概念:

引用用类型:

强引用、软引用、弱引用、虚引用。

强引用((StrongReference)):只要有一个引用存在永远都不会被回收掉

软引用(SoftReference);内存空间不足会回收,如果还不够则会跑出没存溢出的异常。

弱引用(WeakReference):只能生存到下一次垃圾回收前。

虚引用(PhantomReference):无法通过虚引用来来获得一个对象的实例。               

应用:

强引用:我们一般用new创建的对象都是强引用。

软引用:可以用在图片三级缓存里面,帮助图片回收。

虚引用:和上面讲到的各种引用不是一回事的,他主要是为跟踪一个对象何时被GC回收。

 

Stop the world:

,GC的时候,其他所有的程序执行处于暂停状态,卡住了。这个卡顿是非常短(尤其是新生代),对程序的影响微乎其微(关于其他GC比如并发GC之类的,在此不讨论)。所以GC的卡顿问题由此而来,也是情有可原,暂时无可避免。

内存层面的垃圾回收算法:

l  标胶清除法

回收标记过的那部分内存空间。


l  复制算法

将内存按容量分为两块,例如A、B两块,每次只使用其中的一块,当要进行回收操作时,将A中还存活的对象复制到B块中(假设上次使用A),然后对A中所有对象清空就又构成一个完整的内存块。这种方法就避免了标记清除的内存碎片问题。


l  标记整理算法

在标记清除方法上进行的优化,主要是在标记完成后将这些存活的对象向一端移动,然后将末尾边界后的所有内存空间清除。


l  分带回收算法

分代回收算法实际上是把复制算法和标记整理法的结合,并不是真正一个新的算法,一般分为:老年代(Old Generation)和新生代(Young Generation),老年代就是很少垃圾需要进行回收的,新生代就是有很多的内存空间需要回收,所以不同代就采用不同的回收算法,以此来达到高效的回收算法。
新生代:由于新生代产生很多临时对象,大量对象需要进行回收,所以采用复制算法是最高效的。
老年代:回收的对象很少,都是经过几次标记后都不是可回收的状态转移到老年代的,所以仅有少量对象需要回收,故采用标记清除或者标记整理算法。
所以以上整个过程就达到了最高效的回收办法。

触发GC的类型

Java虚拟机会把每次触发GC的信息打印出来来帮助我们分析问题,所以掌握触发GC的类型是分析日志的基础。

GC_FOR_MALLOC 表示是在堆上分配对象时内存不足触发的GC。
GC_CONCURRENT 当我们应用程序的堆内存达到一定量,或者可以理解为快要满的时候,系统会自动触发GC操作来释放内存。
GC_EXPLICIT 表示是应用程序调用System.gc、VMRuntime.gc接口或者收到SIGUSR1信号时触发的GC。
GC_BEFORE_OOM 表示是在准备抛OOM异常之前进行的最后努力而触发的GC。

 

GC使用:

GC运行在一个优先级较低的线程, 我们一般的原则是:对占用大量内存的变量,使用完后主动将其置为NULL,可能的话主动调用一次GC:system.gc(),特别是一些static型的引用风险很大。

 

 

 

 

 

 

 

原创粉丝点击