Java面试题之Java虚拟机垃圾回收

  JVM的垃圾回收机制,在内存充足的情况下,除非你显式的调用System.gc(),否则不会进行垃圾回收;在内存充足的情况下垃圾回收会自动运行。

一、引用计数算法

1.定义:引用计数算法会给对象添加一个引用计数器,每当有一个地方引用他的时候,计数器就加1;当引用失效的时候计数器值就减1。当计数器为0的时候,对象就可以被收回。

2.缺点:存在循环引用的情况,导致两个循环引用对象的内存得不到释放。目前没有一个JVM垃圾回收实现是使用这个算法的。

3.现状:主流的Java虚拟机没有使用引用计数算法来管理内存,因为它很难解决循环引用的问题。

二、可达性分析算法

1.思路:通过一系列"GC Roots"对象作为起点,从这些节点开始向下进行搜索,搜索所走过的路径被称为"引用链"。当一个对象到GC Roots没有任何引用链相连,也就是从GC Roots到这个对象不可达,则证明此对象是不可用的。如图中Object5、Object6、Object7虽然互相关联,但是他们到GC Roots是不可达的,所以他们被判定为可回收的对象。

把一些对象当做root对象,JVM认为root对象是不可回收的,并且root对象引用的对象也是不可回收的。在Java语言中,可作为GC ROOT的对象包含以下几种:

(1)虚拟机栈(栈帧中本地变量表)中引用的队形啊

(2)方法区中静态属性引用的对象

(3)方法区中常量引用的对象

(4)本地方法栈中Native方法引用的对象。

2.即使在可达性分析法中不可达的对象,也不是非死不可的,要真正宣告对象的死亡,只要经历两次标记过程:

(1)如果对象在进行可达性分析之后,发现没有与GC Roots相连的引用链,那么它会被第一次引用。

(2)判断该对象是否有必要执行finallize(),如果对象内有覆盖finallize(),或者finallize()方法已经被覆盖过了,虚拟机将这种情况视为没有必要执行。

  1. 如果一个对象的finallize()方法执行缓慢,甚至发生了死循环,那么导致FQueue队列中的其他对象永远等待下去,甚至导致整个回收系统崩溃,因为在FQueue中的对象无法进行垃圾的回收。
  2. 如果一个对象被判定为有必要执行finalize()方法,那么这个对象将被放置在一个F-Queue的队列中,并在稍后由虚拟机建立的。低优先级的Finalizer线程去执行。这里的执行是指虚拟机会触发这个方法,但是不承诺等待该方法执行完毕,这样做的原因是:finalize()方法是对象最后一次逃脱死亡命运的机会,如果对象在finalize()方法中成功拯救自己,和引用链上的任何一个对象关联起来,比如把自己(this)赋值给某个类变量或者成员变量,那么在第二次标记的时候会被移除即将回收的集合。
  3. 如果对象没有成功逃脱,那么基本上会被真的回收了(第二次标记)。

任何一个对象的finallize方法只会被系统自动调用一次,如果对象面临下一次回收,他的finalize()方法不会再被执行。尽量避免finalize方法,因为它只是为了是C/C++程序员更容易接受java所做出的的一个妥协,他的运行代价高昂,不确定性高,无法表达各个对象的调用顺序。 ---未完待续

原文地址:https://www.cnblogs.com/bigdata-stone/p/12041882.html

时间: 2024-08-22 17:42:32

Java面试题之Java虚拟机垃圾回收的相关文章

JAVA虚拟机垃圾回收算法原理

除了释放不再被引用的对象外,垃圾收集器还要处理堆碎块.新的对象分配了空间,不再被引用的对象被释放,所以堆内存的空闲位置介于活动的对象之间.请求分配新对象时可能不得不增大堆空间的大小,虽然可以使用的总空闲空间是足够的.这是因为,堆中没有连续的空闲空间放得下新的对象. 垃圾收集器算法 任何垃圾回收算法都必须做两件事,首先,它必须检测出垃圾对象.其次,它必须回收垃圾对象所使用的堆空间并还给程序.从根对象开始,任何可以被触及的对象都被认为是“活动的”对象(如果正在运行的程序可以访问到根对象和某个对象之间

Java虚拟机垃圾回收机制

在Java虚拟机中,对象和数组的内存都是在堆中分配的,垃圾收集器主要回收的内存就是再堆内存中.如果在Java程序运行过程中,动态创建的对象或者数组没有及时得到回收,持续积累,最终堆内存就会被占满,导致OOM. JVM提供了一种垃圾回收机制,简称GC机制.通过GC机制,能够在运行过程中将堆中的垃圾对象不断回收,从而保证程序的正常运行. 垃圾对象的判定 我们都知道,所谓“垃圾”对象,就是指我们在程序的运行过程中不再有用的对象,即不再存活的对象.那么怎么来判断堆中的对象是“垃圾”.不再存活的对象呢?

Java虚拟机--垃圾回收机制

Java与C++相比,具有动态分配内存和垃圾回收机制的技术优势,使得我们不用把精力集中在内存的管理上,那我们为什么还要去了解GC和内存分配呢?原因很简单:当需要排查各种内存溢出.内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些"自动化"的技术实施必要的监控和调节. 1.为什么进行垃圾回收  随着程序的运行,系统内存中存在的对象实例.各种变量越来越多,如果不进行垃圾回收,会影响到程序的性能,当占用内存过多时,还会产生OOM等系统异常. 2.哪些内存需要回收 关于

老生常谈Java虚拟机垃圾回收机制(必看篇)

二.垃圾收集 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 判断一个对象是否可被回收 1. 引用计数算法 给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1.引用计数为 0 的对象可被回收. 两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收. 正因为循环引用的存在,因此 Java 虚拟机不使用引用计数

29、Java虚拟机垃圾回收调优

一.背景 如果在持久化RDD的时候,持久化了大量的数据,那么Java虚拟机的垃圾回收就可能成为一个性能瓶颈.因为Java虚拟机会定期进行垃圾回收,此时就会追踪所有的java对象, 并且在垃圾回收时,找到那些已经不在使用的对象,然后清理旧的对象,来给新的对象腾出内存空间. 垃圾回收的性能开销,是跟内存中的对象的数量,成正比的.所以,对于垃圾回收的性能问题,首先要做的就是,使用更高效的数据结构,比如array和string:其次就是在持久化rdd时, 使用序列化的持久化级别,而且用Kryo序列化类库

【译】Java SE 14 Hotspot 虚拟机垃圾回收调优指南

原文链接:HotSpot Virtual Machine Garbage Collection Tuning Guide,基于Java SE 14. 本文主要包括以下内容: 优化目标与策略(Ergonomics) 垃圾收集器实现(Garbage Collector Implementation) 影响垃圾收集性能的因素 总堆(Total Heap) 年轻代 可用的收集器(Available Collectors) 串行收集器(Serial Collector) 并行收集器(Parallel Co

java虚拟机垃圾回收被误解的7件事

对Java垃圾回收最大的误解是什么?它实际又是什么样的呢? 当 我还是小孩的时候,父母常说如果你不好好学习,就只能去扫大街了.但他们不知道的是,清理垃圾实际上是很棒的一件事.可能这也是即使在Java的世界中, 同样有很多开发者对GC算法产生误解的原因--包括它们怎样工作.GC是如何影响程序运行和你能对它做些什么.因此我们找到了Java性能调优专家Haim Yadid,并把名为Java performance tuning guide的文章发表在Takipi的博客上. 最新博文:关于垃圾回收被误解

Java中的内存分配与垃圾回收

一.内存分配 Java程序运行时的内存分配,按照JVM规范,包括以下几个区域:程序计数器.虚拟机栈.本地方法栈.方法区.堆.其中,前三个是线程私有的,与线程生命周期相同,线程退出内存自动回收:后两者是所有线程共享内存的,只在垃圾回收机制被触发时,被动回收. * 程序计数器,内存区域极小,是当前线程的字节码执行行号指示器: * 虚拟机栈.本地方法栈,即平时所说的“栈”,是虚拟机用来执行方法(包括Java.非Java方法)时,使用的临时内存空间,用来存储当前方法.局部变量等,全部基本类型变量,以及类

Java进阶之内存管理与垃圾回收

Java是在JVM所虚拟出的内存环境中运行的.内存分为栈(stack)和堆(heap)两部分.我们将分别考察这两个区域. 栈 在Java中,JVM中的栈记录了线程的方法调用.每个线程拥有一个栈.在某个线程的运行过程中,如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即帧(frame).在frame中,保存有该方法调用的参数.局部变量和返回地址. 调用栈 Java的参数和局部变量只能是基本类型的变量(比如int),或者对象的引用(reference).因此,在栈中,只保存有基本类型的变