JVM中判断无效对象算法

文章介绍了JVM内存的组成部分,包括线程私有的虚拟机栈、本地方法栈和程序计数器,以及线程共享的方法区和堆。重点讨论了垃圾回收的重要性,提到了引用计数和根搜索两种算法,并指出GC在进行根搜索时需要暂停所有线程(StopTheWorld)以确保准确性。
摘要由CSDN通过智能技术生成

JVM 内存大致分为 线程私有区域线程共享区域

虚拟机栈、本地方法栈和程序计数器,这三个区域是线程私有的。

虚拟机栈用于描述Java方法执行的过程。每一个方法在执行的过程中会创建一个栈帧。栈帧中包括局部变量、操作数栈、动态链接和方法出口等信息。当方法执行完成后,对应的栈帧就会弹栈。虚拟机栈的内存分配是确定的,所以不需要特别关注虚拟机栈及其他线程私有区域的内存使用情况。

方法区和堆是线程共享区域。方法区和堆主要存放对象、数组等不确定数量的数据。在方法执行的过程中创建的对象数量是不确定的。所以需要合理的内存管理机制来管理这两个区域。方法区和堆内存是垃圾回收器进行垃圾回收的主要区域。

内存中的垃圾

在程序运行过程中,会创建对象,但是当方法执行完成或对象不再使用时,它们被定义为"垃圾"。此时,需要通过垃圾回收器来清理这些内存区域。为了将"垃圾"量化成计算机语言,我们需要设计一套算法供垃圾回收器使用。垃圾回收的动作是由垃圾回收器自动运行和判定的。

判断一个对象是否为垃圾

常见的算法有两种:引用计数算法和根搜索算法。

引用计数算法(Reference Counting Collector)

在该算法中,每个对象都会有一个引用计数器。当对象被引用时,计数器会增加;当引用失效时,计数器会减少。当计数器为零时,意味着对象不再被引用,可以进行回收。

这种算法简单且高效,判定过程相对容易。然而,它存在一个致命的缺点,即无法处理循环引用的情况。当两个对象相互引用时,它们的计数器永远不会变为零,导致内存泄漏。因此,引用计数算法在早期的 JVM 中使用较多,但现在已经较少使用。

根搜索算法(Tracing Collector)

根搜索算法的核心思想,就是从某一些指定的对象出发,寻找与该根对象具有引用关系的对象,然后再从这些对象开始继续寻找,形成一个个的引用链。不在引用链上的对象被标记为引用不可达对象。

那么哪些对象可以叫做根对象呢?

  • 虚拟机栈中引用的对象
  • 方法区中常量引用的对象
  • 方法区中静态属性引用的对象
  • 本地方法栈中JNI(Native方法)引用的对象
  • 活跃线程

上述算法只是一个算法的中心思想,实际执行过程要比这个复杂的。另外,GC判断对象是否可达看的还是强引用。

  1. 进行根搜索的时候,是需要暂停所有线程的,即执行一次 STW(Stop The World),最主要的目的是防止上述的对象图在算法运行的过程中有变化从而影响算法的准确性。

  2. 线程暂停的时间长短,取决于对象的多少,和堆内存的大小无关。

  3. 宣告一个对象的“死亡”其实不仅仅通过上述的算法计算,而是需要经历两次的标记,本文暂不进行赘述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值