Java教程

二十四、java虚拟机垃圾处理机制

本文主要是介绍二十四、java虚拟机垃圾处理机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

垃圾回收

  • 垃圾收集发生的区域
  • 判定需要被回收的对象
    • 引用计数法
    • 可达性分析算法
    • 垃圾回收机制
    • 四种引用类型
    • 回收方法区

垃圾收集发生的区域

Java堆和方法区有显著的不确定性,只有在程序运行时才能知道程序究竟创建了哪些对象,创建了多少对象,所以这部分内存的分配和回收是动态的,垃圾收集器所关注的正是这部分内存该如何管理

判定需要被回收的对象

引用计数法

  • 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器加1;当引用失效,计数器减1;任何时刻计数器值都为0的对象就不能再被使用了
  • 优缺点:
    • 虽然会占用额外的内存空间用于计数,但原理简单,判定效率高,大多数情况下都是一个不错的算法
    • 需要考虑很多额外情况,否则无法保证其正确工作,例如单纯的引用计数法就很难解决对象之间相互循环引用的问题

可达性分析算法

  • 基本思路:通过一系列称为GC Roots 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程走过的路径称为引用链,如果某个对象到GC Roots间没有任何引用链相连,则证明此对象是不可能再被使用,可以回收

在Java技术体系中,可以作为GC Roots的对象包括:

  • 在虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象
  • Java虚拟机内部的引用,如基本类型对应的Class对象
  • 所有被同步锁持有的对象

垃圾回收机制

  • 内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

  • 内存溢出:指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。 内存泄露量大到一定程度会导致内存溢出。但是内存溢出不一定是内存泄露引起的。

  • 内存泄漏的分类(按发生方式来分类)

    • 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
    • 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
    • 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
    • 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏

四种引用类型

  • 强引用:形如Object obj = new Object() 这种引用关系就是强引用;无论什么时候,只要强引用关系存在,对象就永远不会被回收
  • 软引用:用来描述一些有用但非必要的对象,此类对象只有在进行一次垃圾收集仍然没有足够内存时,才会在第二次垃圾收集时被回收。JDK1.2之后提供了SoftReference类来实现软引用
  • 弱引用
    也是用来描述那些非必须对象,但它的强度比软引用更弱一些。被软引用关联的对象只能生存到下一次垃圾收集发生为止,当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。JDK1.2之后提供了WeakReference类来实现软引用
  • 虚引用
    最弱的一种引用关系,一个对象是否存在虚引用,丝毫不会对其生存时间造成任何影响,也无法通过虚引用来取得一个对象实例。设置虚引用关联的唯一目的就是让这个对象被回收时能收到一个系统通知。JDK1.2之后提供了PhantomReference类来实现软引用

回收方法区

方法区的垃圾收集主要回收两部分:废弃的常量和不再使用的类型。判定一个常量是否废弃相对简单,与对象类似,只要某个常量不再被引用,就会被清理。

而判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了,需要同时满足下面三个条件:

  • 该类的所有实例都已经被回收,即 Java堆中不存在该类及其任何派生子类的实例
  • 加载该类的类加载器已经被回收
  • 该类对应的 java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法

Java 虚拟机允许对满足上述三个条件的无用类进行回收,但并不是说必然被回收,仅仅是允许而已。关于是否要对类型进行回收,HotSpot 虚拟机提供了–Xnoclassgc参数进行控制

这篇关于二十四、java虚拟机垃圾处理机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!