Java的垃圾回收机制

2020-04-02  本文已影响0人  年迈的代码机器

在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。

什么是垃圾?

垃圾是指该对象没有被其他对象引用,那么该对象就是垃圾。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。

主要步骤:标记垃圾,清除(回收)垃圾

标记垃圾

标记垃圾的算法主要有两种, 引用计数法和可达性分析算法

引用算法:给对象添加一个引用计数器,每当有引用它,计数器就加 1;当引用失效,计数器就减 1;当计数器为 0 的对象就是不可能再被使用的,可以当做垃圾收集。

可达性分析算法:上述引用算法有一个缺点,当两个对象相互引用的时候,上述算法会造成内存泄漏,所以有了可达性算法。现存在一个名为GC Roots的对象作为起始点,当该对象到GC Roots没有引用链则说明未被引用,被标记为垃圾。(从离散数学中引入)

清除(回收)垃圾

回收垃圾的条件:
 1会在cpu空闲的时候自动进行回收
 2在堆内存存储满了之后
 3主动调用System.gc()后尝试进行回收

如何回收垃圾:
这里存在着四种垃圾回收算法,标记清除算法、复制算法、标记整理算法以及分代回收算法。

1、标记清除算法
最基础的一种算法,第一个步骤就是标记,第二步将标记的回收。
缺点:效率低,空间浪费(内存碎片)

2、复制算法
通俗的讲就是把内存分为A,B两块,A作为使用,B当作备胎。当A的内存使用完后,把A上未被使用的复制到B上,然后一次性清除A。
缺点: 没有了内存碎片,但是内存少了一半。

3、标记整理算法
比第一种标记清除算法多了整理。

4、分代回收算法(现在使用较多)
分代回收比较智能,体现在他可以根据不同场景选择上述三种不同的回收算法,达到高效。

如何确定场景?

根据对象的生命周期,jvm把内存分为三个区域:新生代,老年代,永久代。
新生代存放生命周期短的,老年代存放生命周期较长的,而永久代(jdk1.8之后更新没有永久代)存放静态文件。

如何选择回收算法?
在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法。只需要付出少量存活对象的复制成本就可以完成收集。
老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须用标记-清除或者标记-整理。

注:在jdk8的时候java废弃了永久代,但是并不意味着以上的结论失效,因为java提供了与永久代类似的叫做“元空间”的技术。详情请自己作为了解。

上一篇 下一篇

猜你喜欢

热点阅读