我们都知道Java使用的是垃圾自动回收机制,开发者无需像C程序员一样时时刻刻关心何时做垃圾回收。但是作为一名Java程序员了解JVM的垃圾回收机制是一件非常必要的事情,对于分析系统发生OM的问题,内存泄漏等问题时会非常有帮助。
对于垃圾回收,我们比较关心的是以下几个问题:
1、回收些什么玩意?
2、什么时候回收?
3、怎样回收?
一、回收什么玩意?
Java是面向对象的语言,那么它的垃圾回收当然是回收那一个个被创建出来的对象实例。在了解垃圾回收机制之前建议先看看JVM的内存管理,否则有些地方看起来会比较费劲。在JVM规范中的内存管理定义了本地方法栈,虚拟机栈,程序计数器,方法区,java堆,直接内存这几个主要的内存分配模块,其中本地方法栈,虚拟栈,程序计数器随着线程而生,随线程而灭,这几个地方基本不需要过多的考虑GC,因为随着线程的结束,他们所占用的内存自然就释放了,所以GC对象的主要战场就是方法区里存放的类信息,常量,静态变量和java堆里的对象实例。
二、什么时候回收?
在java堆和方法区中存放的那些对象,JVM是怎么知道他们现在是没有用的垃圾了呢?这里就介绍两种判定方式,分别是引用计数算法和可达性分析算法
引用分析算法
给对象添加一个引用计数器,当有其它对象引用它的时候,引用值+1,当引用失效的时候,引用值-1,客观的说引用分析算法确实是一个简单有效的算法,在游戏脚本领域有广泛的使用,但是在Java虚拟机里却没有采用它,原因是它很难解决对象之间互相引用的情况。如下图:
在整个程序中只有它们自己互相引用,并没有其他的地方需要用到它两,从实际角度来说它们属于垃圾对象,但是通过引用计数算法得出的结果它们又不是垃圾,并不会被GC掉,如果这样的垃圾对象一直堆积最终会导致OOM,所以java虚拟机采用的是另外一种算法
可达性分析算法
从一系列的被称为“GC ROOT”对象出发,从这些节点开始向下搜索,搜索所走过的路经称为引用链,当一个对象到GC ROOT上没有任何的引用链时,就判断它为可被回收的垃圾对象。如下图所示:
Object4和Object5就是没有引用链的对象,也就意味着它们将被GC。可怜的小对象.
JDK把对象的引用进行了分类,分为强引用,软引用,弱引用,虚引用。下面分别来看看这些引用的区别
强引用:类似Object1 ob = new Object1(); 这样的引用关系就是强引用,将永远不会被GC
软引用:描述一些还有用,但是非必需的对象,这些对象在系统即将发生内存溢出异常之前会把他们加入秋后问斩的名单,如果把他们回收后还没有足够的内存,那么就会抛出OutofMemory的异常。
弱引用:描述一些非必需的对象,当垃圾收集工作器工作的时候,无论当前系统内存是否足够,他们都会被斩首,一群的可怜的娃
虚引用:最弱的一种引用关系,为一个对象设置虚引用的唯一目的就是在该对象被GC收到一个系统通知。一种累觉不爱的引用关系。
三、如何回收
通常一个对象要真正的被回收需要经过两次标记。如下图:
每一个对象都继承自Object,Object里有一个finalize()方法,当JVM发现某个对象不可达的时候就会把它标记为可被回收的对象,也就是第一次标记。然后对这些对象进行一次筛选,条件就是是否有必要执行它的finalize()方法。如果没有就直接被干掉,如果有就将他们放入一个叫F-Queue的队列,然后一个虚拟机自动创建一个低优先级的线程去执行他们的finalize()方法,稍后对F-Queue里的对象进行二次标记,把那些执行完还没有引用链的对象干掉。
这里值得注意的是虚拟机并不会等F-Queue里的对象全部执行完finalize(),因为如果某个对象的finalize方法里有死循环,则GC将一直处于等待状态,导致整个内存回收系统崩溃。其次是判断是否有必要执行finalize()的方法是看它是已经执行过一次,或者对象没有覆写finalize()方法的都被认为没必要的而被直接被干掉。
方法区的回收
有人认为方法区是永久代,是没有GC的,的确对方法区进行GC的性价比确实不高,但它还是有GC的。对堆中的新生代进行GC基本能挽回70~90%的内存空间,而对永久代的回收就达不到这么高的比例。
方法区中的回收对象主要有两类:废弃常量和无用类。判断方法区中的常量池中的常量是否为废弃常量只需要判断是否有引用即可,判断无用类则是根据以下三个方面:
a、java堆中没有该类的实例,也就是该类的实例全部被回收
b、加载该类的ClassLoader已经被回收
c、该类对应的java.lang.Class对象没有地方被引用,无法在任何地方通过反射访问
在大量使用反射,动态代理,CGLib等技术的地方都需要虚拟机具有加载类和卸载类的能力,以保证永久代不会内存溢出。
相关推荐
其中,垃圾回收机制(Garbage Collection, GC)是Java虚拟机(JVM)的一项重要特性,它能够自动检测并回收不再使用的对象占用的内存空间,从而有效避免了内存泄漏问题。本文将详细介绍Java中的垃圾回收机制及其工作原理...
Java虚拟机(JVM)是Java程序运行的核心组件,它为Java代码提供了跨平台的运行环境。深入理解JVM的工作原理对于优化Java程序性能、排查问题以及提升开发能力至关重要。以下将详细介绍JVM的主要组成部分、内存模型、...
通过学习这些知识点,并结合《实战Java虚拟机——JVM故障诊断与性能优化》的源码,开发者能够更深入地理解JVM的工作机制,从而更好地优化Java应用的性能,处理各种运行时问题。实践中,不断尝试、调整和学习,才能...
本文将介绍Java虚拟机的使用和优化,包括Java虚拟机的特性、垃圾回收机制、性能优化方法等。 Java虚拟机的特性 Java虚拟机是Java语言的核心组件之一,它负责将Java源代码编译成字节码,并在不同的平台上解释执行...
本文深入探讨了Java垃圾回收机制的特点及其在Java虚拟机(JVM)中的应用,并详细分析了几种典型的垃圾收集算法。此外,文章还介绍了如何通过命令行参数来调整垃圾回收的行为以及`finalize`方法的作用。通过理解这些...
Java性能调优,特别是关于垃圾回收机制的分析和指导,是优化Java应用程序的关键环节。Java的垃圾回收(Garbage Collection, GC)是自动管理内存的一种机制,它负责识别并清理那些不再使用的对象,以释放内存资源。...
在编程领域,特别是对于初学者来说,了解并掌握Java的垃圾回收机制是非常重要的。与C++等需要手动管理内存的语言不同,Java通过内置的垃圾回收器(Garbage Collector, GC)自动管理对象的生命周期,简化了内存管理的...
Java垃圾回收机制是Java虚拟机(JVM)中的一种机制,用于防止内存泄露和有效地使用空闲的内存。垃圾回收机制的主要目的是为了回收无用的对象占用的内存空间,使该空间可被程序再次使用。 垃圾回收机制的算法有多种...
在Java编程中,Java虚拟机是至关重要的组成部分,它负责执行编译后的Java字节码,并通过动态类加载、内存管理、垃圾回收等机制保证程序的高效运行。本书深入探讨了以下几个关键知识点: 1. **JVM架构**:JVM由类...
Java垃圾回收机制是Java虚拟机(JVM)中的一种自动管理内存的机制,它可以自动地将不再使用的对象从内存中回收,以释放更多的内存空间供其他对象使用。本文将详细介绍Java垃圾回收机制的工作原理、各个阶段的执行...
### JVM的垃圾回收机制 JVM的垃圾回收(Garbage Collection,GC)机制是其自动内存管理的关键部分。GC的主要任务是在程序运行过程中自动检测并释放不再使用的对象所占用的内存空间,避免了手动管理内存所带来的问题,...
4.垃圾回收:Java虚拟机的垃圾回收机制可以自动回收不再使用的对象,避免内存溢出。 Java虚拟机的优点包括: * 平台无关性:Java虚拟机使得Java语言编译器生成的目标代码可以在多种平台上运行。 * 可移植性:Java...
Java的垃圾回收机制(Garbage Collection,GC)是Java虚拟机(JVM)的一个重要组成部分,它负责自动管理内存的分配和释放,以减轻程序员在内存管理方面的负担,并防止内存泄漏和内存溢出等问题。本文将详细探讨GC的...
垃圾回收(Garbage Collection)是JVM中一个重要的自动化内存管理机制。它负责回收堆内存中不再使用的对象实例,从而防止内存泄漏。不同的JVM实现采用不同的垃圾回收算法,常见的算法有标记-清除、标记-整理、复制、...
Java虚拟机(JVM)的垃圾回收(Garbage Collection,简称GC)机制是Java编程中的一个重要组成部分,它自动管理程序的内存,确保无用的对象能够被有效地释放,从而避免内存泄漏。本文将深入探讨Java垃圾回收的基本...
在本文中,我们将深入探讨Java虚拟机的体系结构、垃圾回收机制、Java对象的生命周期和分代,以及相关的参数设置与调优。 Java虚拟机体系结构 Java虚拟机由三个主要组件组成:类加载器、运行时数据区和执行引擎。类...
### 垃圾回收机制详解 #### 一、引言 在现代软件开发中,内存管理一直是程序设计中的一项重要任务。特别是在高级编程语言中,如何有效地管理和释放内存资源成为了衡量一个程序性能的关键因素之一。Java作为一种...