JVM的垃圾回收机制小读

合集下载

jvm的gc原理

jvm的gc原理

jvm的gc原理JVM的GC原理一、概述JVM(Java虚拟机)是Java程序运行的环境,其中最重要的组成部分之一就是垃圾回收(Garbage Collection,简称GC)机制。

GC的作用是自动管理程序中的内存,及时释放不再使用的对象,以避免内存泄漏和内存溢出的问题。

本文将对JVM的GC原理进行详细介绍。

二、垃圾回收算法1. 标记-清除算法标记-清除算法是最基本的垃圾回收算法之一。

它的过程分为两个阶段:标记阶段和清除阶段。

在标记阶段,GC会从根节点(一般是程序中的静态变量和栈中的引用)开始,递归地遍历对象图,标记出所有被引用的对象。

在清除阶段,GC会遍历整个堆,清除所有未被标记的对象。

2. 复制算法复制算法是针对标记-清除算法的改进。

它将堆分为两个区域,每次只使用其中一个区域。

当一个区域的对象被标记后,将其复制到另一个区域中,然后清除原来的区域。

这样可以解决碎片问题,但是需要额外的空间来存储复制的对象。

3. 标记-整理算法标记-整理算法是对标记-清除算法的改进。

它的过程与标记-清除算法类似,但是在清除阶段,标记-整理算法会将存活的对象向一端移动,然后清除边界外的所有对象。

这样可以解决碎片问题,并且不需要额外的空间。

4. 分代算法分代算法是针对对象的生命周期不同而提出的。

一般来说,对象的生命周期可以分为年轻代和老年代。

年轻代中的对象生命周期较短,老年代中的对象生命周期较长。

分代算法将堆分为年轻代和老年代两个区域,分别采用不同的垃圾回收算法。

年轻代一般使用复制算法,老年代一般使用标记-清除算法或标记-整理算法。

三、GC的执行过程1. 初始标记初始标记阶段是GC的第一步,它的目的是标记出所有的根对象,并且停止所有的应用线程。

这个过程是短暂的,因为只需要标记出与根对象直接关联的对象。

2. 并发标记并发标记阶段是GC的核心步骤,它的目的是通过并发执行来标记出所有的存活对象。

在这个阶段,GC会遍历整个堆,标记出与根对象直接或间接关联的存活对象。

简单谈谈对GC垃圾回收的通俗理解

简单谈谈对GC垃圾回收的通俗理解

简单谈谈对GC垃圾回收的通俗理解简单谈谈对GC垃圾回收的通俗理解⽂章简介《简单谈谈对GC垃圾回收的理解》是我的第⼀篇博客,了解并学习了JVM的垃圾回收机制后,把⾃⼰的⼀些理解记录下来,通过输出博客的⽅式来沉淀,我觉得是⼀个不错的⽅式!垃圾回收是指什么所谓的垃圾,顾名思义,就是指的在程序运⾏的过程中,有类的诞⽣、初始化、销毁,在这⼀系列的过程中,我们的程序⾃然会产⽣⼀些已经消亡的,不需要的类、实例等等。

⽽这些对于程序不需要的东西或者阻碍程序正常运⾏的东西就是垃圾。

⽽垃圾回收指的就是将这些垃圾从我们程序运⾏的环境中清除出去,⾄于这些垃圾会去向哪⾥,⾃然是不需要我们去关⼼的,毕竟你也从未关⼼过垃圾收集车 将垃圾运往何处!为什么需要垃圾回收我们都知道,⼩区的垃圾回收车 每天都会将垃圾集中运⾛处理,还⼩区⼀个⼲净舒适的环境。

那么同样,程序的运⾏也需要⼀个畅通⽆阻的环境。

如果垃圾过多,可能导致程序运⾏时间变长,就像我们的电脑C盘空间不⾜的时候,电脑不仅运⾏缓慢,还会出现死机、蓝屏等恶况!程序中⽐较经典的因为垃圾过多导致的错误就有OOM(ng.OutOfMemoryError)。

OOM 内存不⾜官⽅语⾔是这样描述的:当Java虚拟机由于内存不⾜⽽⽆法分配对象,并且垃圾回收器⽆法再提供更多内存时,抛出该异常。

通俗来说,就是内存满了,爆了。

⽽我们知道,java中错误(Error)和异常(Exception)是不同的。

异常还可以被捕获、抛出来通过程序代码来处理,但是错误已经严重到不⾜以被应⽤处理,会导致程序直接崩溃停⽌!在真实项⽬中这样的情况肯定是不允许发⽣的。

那么我们可以分析⼀下导致内存不⾜的原因!⽆外乎有以下两点:分配到的内存太少。

程序使⽤的太多。

分配太少:我们知道,虚拟机可以使⽤的内存也是有个限度的,当被分配的内存⼤⼩完全不够⽀持我们程序正常运⾏就会OOM。

我们可以通过以下代码查看JVM初始化的总内存⼤⼩和JVM试图使⽤的最⼤内存。

javaGC垃圾回收机制G1、CMS

javaGC垃圾回收机制G1、CMS

javaGC垃圾回收机制G1、CMSCMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间。

对于要求服务器响应速度的应⽤上,这种垃圾回收器⾮常适合。

在启动JVM参数加上-XX:+UseConcMarkSweepGC ,这个参数表⽰对于⽼年代的回收采⽤CMS。

CMS采⽤的基础算法是:标记—清除。

使⽤场景:1、应⽤程序对停顿⽐较敏感,并且在应⽤程序运⾏的时候可以提供更⼤的内存和更多的CPU2、在JVM中,有相对较多存活时间较长的对象(⽼年代⽐较⼤)会更适合使⽤CMS。

为解决CMS算法产⽣空间碎⽚和其它⼀系列的问题缺陷,HotSpot提供了另外⼀种垃圾回收策略,G1(Garbage First)算法,通过参数-XX:+UseG1GC来启⽤,该算法在JDK 7u4版本被正式推出,G1垃圾收集算法主要应⽤在多CPU⼤内存的服务中,在满⾜⾼吞吐量的同时,竟可能的满⾜垃圾回收时的暂停时间,下⾯是官⽅介绍:The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories.It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbagecollector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:Can operate concurrently with applications threads like the CMS collector.Compact free space without lengthy GC induced pause times.Need more predictable GC pause durations.Do not want to sacrifice a lot of throughput performance.Do not require a much larger Java heap.G1采⽤了另外⼀种完全不同的⽅式组织堆内存,堆内存被划分为多个⼤⼩相等的内存块(Region),每个Region是逻辑连续的⼀段内存,G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。

java自动垃圾回收机制

java自动垃圾回收机制

java⾃动垃圾回收机制前⾔:相⽐C++,java做的⼀⼤改进是将复杂的内存管理抽离出来交给jvm去处理,让码农不再时刻盯着内存泄漏的问题,可以更专注于业务逻辑的开发。

java的GC机制是和其内存模型相关联的,⽽GC的核⼼内存区域是内存中的堆区。

java堆区按对象的存活时间被分为了年轻代(eden区+s0区+s1区)和⽼年代(tentired区),java堆的按代区分其实是为了其垃圾回收的分代收集机制打开了⽅便之门。

java的GC收集器会在不同的分代上使⽤不同的垃圾收集策略。

GC其实主要需要解决两个问题:哪些是垃圾?如何清理垃圾?在解决这两个问题上涉及到下⾯的⽅法论:1.垃圾对象判定⽅法引⽤计数法:在C++的智能指针中使⽤了这种⽅式去做内存的⾃动回收。

即在对象⽣成时维护⼀个对该对象引⽤次数的计数器,对象初次⽣成时计数器值为1,每增加⼀个到该对象的引⽤,计数器加1,每减少⼀个引⽤(如引⽤变量赋值null,或引⽤变量离开作⽤域),计数器减1,计数器为零时,对象内存会被⾃动回收。

该⽅法的问题是存在内存泄漏的隐患,如对象相互引⽤、循环引⽤等情况相互引⽤:public class ReferenceCountingGc {Object instance = null;public static void main(String[] args) {ReferenceCountingGc objA = new ReferenceCountingGc();ReferenceCountingGc objB = new ReferenceCountingGc();objA.instance = objB;objB.instance = objA;objA = null;objB = null;}} 例⼦中两个new出来的对象ReferenceCountingGc由于通过内部的变量instance引⽤着对⽅,两个对象的引⽤计数都为1。

面试谈jvm原理

面试谈jvm原理

面试谈jvm原理Java虚拟机(JVM)是Java语言运行的基础。

JVM具有封装性、跨平台性、高度优化和可扩展性等特点,是Java应用程序的核心。

在Java的诞生初期,由于硬件环境和操作系统制约,JVM起到了垫底的作用。

而今天,JVM已经成为Java 运行效率和安全性的保障。

下面是一些我认为JVM原理面试时可能会涉及的重点:1. JVM的内存模型:JVM将内存分为堆内存和栈内存,堆内存用于存储对象实例和数组,而栈内存则用于存储方法的执行状态。

同时,JVM还有方法区和永久代的概念。

这些内存区域的大小和分配情况会影响JVM的性能和稳定性。

2. 垃圾回收机制:JVM的内存管理包括垃圾回收机制和内存分配机制。

垃圾回收机制是JVM实现自动内存管理的核心,JVM会周期性地扫描堆内存中没有被引用的对象,并自动回收它们所占用的内存。

垃圾回收机制常用的算法包括标记清除、复制和标记整理等。

3. 类加载机制:Java程序在运行时,需要将类文件中的二进制数据加载到JVM 中,才能执行相应的操作。

类加载机制将类文件加载到JVM中,并将它们解析为Java类。

类加载机制包括三个阶段:加载、链接和初始化。

4. JIT编译器:JIT(Just In Time)编译器是JVM在运行时动态优化的关键组件。

JIT编译器可以在程序运行时,根据代码的执行情况,生成本地机器代码,以提高程序的效率。

5. JVM调优:JVM的性能和稳定性很大程度上取决于JVM参数的设置和调整。

面试时,可能会涉及到如何根据系统的特点和需求,设置JVM参数以达到最佳性能和稳定性的问题。

总之,有关JVM原理的面试问题,往往涉及到JVM的内存模型、垃圾回收机制、类加载机制、JIT编译器和JVM调优等方面。

需要候选人对这些方面有比较深入的了解。

垃圾回收机制

垃圾回收机制

垃圾回收机制垃圾回收是计算机科学中一种重要的机制,用于回收和释放程序中不再使用的内存空间,以提高系统的效率和性能。

1. 什么是垃圾回收机制?垃圾回收是一种自动化的内存管理技术,用于检测和回收程序中不再可用的内存对象。

它可以分析程序的运行时行为,识别不再被引用的对象,并将其释放以供其他程序使用。

2. 垃圾回收的优点- 减少内存泄漏:垃圾回收可以识别并回收不再使用的内存对象,从而减少内存泄漏的风险。

- 提高性能:回收不再使用的内存可以释放系统资源,提高程序的运行效率和响应速度。

- 简化编程:垃圾回收可以减少程序员手动管理内存的工作量,使编程更加简单和可靠。

3. 垃圾回收的实现方式垃圾回收机制可以通过以下几种方式来实现:- 引用计数:每个对象都维护一个引用计数器,当引用计数为零时,认为对象不再需要,可以进行回收。

- 标记-清除:通过标记所有可达对象,然后清除不可达对象来进行回收。

- 复制式垃圾回收:将内存分为两个区域,一部分为活跃对象,另一部分为闲置对象。

当活跃对象占满时,将活跃对象复制到闲置对象区域,然后清除活跃对象的内存。

- 分代式垃圾回收:根据对象的存活时间将内存分为多个代,然后对不同代进行不同的垃圾回收策略。

4. 垃圾回收的挑战垃圾回收虽然带来了许多优点,但也面临一些挑战:- 停顿时间:垃圾回收会导致程序的停顿,影响系统的实时性能。

- 资源消耗:垃圾回收需要消耗系统的资源,包括CPU和内存。

- 确定回收时机:确定内存对象是否不再使用是一个复杂的问题,需要进行准确的分析和判断。

5. 垃圾回收的最佳实践为了充分利用垃圾回收机制,以下是一些最佳实践:- 避免创建不必要的对象:尽量避免频繁创建和销毁对象,以减少垃圾的产生。

- 及时释放资源:在不再需要使用内存对象时,及时进行释放,以加快垃圾回收的速度。

- 使用合适的数据结构:选择合适的数据结构可以减少垃圾回收的复杂性和开销。

结论垃圾回收机制是一种重要的内存管理技术,可以提高系统的性能和可靠性。

垃圾回收机制的原理

垃圾回收机制的原理

垃圾回收机制的原理随着计算机领域的不断发展,我们的应用程序正在变得越来越庞大和复杂。

而这些应用程序一旦开始运行,就会占用大量的系统内存。

为了确保计算机系统的稳定运行,我们需要一种垃圾回收机制来确保内存资源的有效管理。

本文将介绍垃圾回收机制的原理以及其在计算机系统中的应用。

1. 垃圾回收机制垃圾回收机制是一种自动内存管理机制,它会扫描内存中不再使用的对象并将其标记为“无用垃圾”。

这些“无用垃圾”对象然后被系统回收,以释放它们占用的内存资源。

在某些编程语言中,如Java和Python,垃圾回收机制是自动完成的,开发人员不需要手动清理内存。

在其他编程语言中,如C和C ++,开发人员需要手动释放不再使用的内存资源。

2. 垃圾回收算法垃圾回收算法是垃圾回收机制的核心。

垃圾回收算法通常使用两种基本方法: 引用计数和标记-清除。

2.1 引用计数引用计数算法是最简单的垃圾回收算法之一。

在这个算法中,编程语言会保持即将使用的每个对象的引用数量。

当引用数量降至零时,对象将被标记为垃圾并由垃圾回收机制自动回收。

尽管这种算法可能比较简单,但它容易陷入循环引用的问题,即两个或多个对象引用对方,而不消失引用。

因此,循环引用的对象不会被回收,这可能会导致内存泄漏。

2.2 标记-清除标记-清除算法是一种更复杂的垃圾回收算法,它由两个步骤组成。

首先,算法扫描内存中的所有对象,标记所有活动对象。

这些活动对象在程序中仍有引用。

然后,算法会清空未标记的对象,释放它们占用的内存资源。

这种算法能够解决引用计数的问题,但在大型内存中,扫描整个内存可能比较缓慢,影响系统的性能。

3. 垃圾回收机制的应用场景在大型应用程序中,使用垃圾回收机制来确保有效的内存管理非常重要。

垃圾回收机制能够避免内存泄漏等问题,保证系统的稳定运行。

垃圾回收机制的典型应用场景包括桌面应用程序和网络应用程序,如网站和服务器。

4. 总结垃圾回收机制是一种自动化的内存管理机制,它可以扫描内存中无用的对象,并释放它们占用的内存资源。

JVM垃圾回收之三色标记

JVM垃圾回收之三色标记

JVM垃圾回收之三⾊标记三⾊标记法是⼀种垃圾回收法,它可以让JVM不发⽣或仅短时间发⽣STW(Stop The World),从⽽达到清除JVM内存垃圾的⽬的。

JVM中的CMS、G1垃圾回收器所使⽤垃圾回收算法即为三⾊标记法。

三⾊标记算法思想三⾊标记法将对象的颜⾊分为了⿊、灰、⽩,三种颜⾊。

⽩⾊:该对象没有被标记过。

(对象垃圾)灰⾊:该对象已经被标记过了,但该对象下的属性没有全被标记完。

(GC需要从此对象中去寻找垃圾)⿊⾊:该对象已经被标记过了,且该对象下的属性也全部都被标记过了。

(程序所需要的对象)算法流程从我们main⽅法的根对象(JVM中称为GC Root)开始沿着他们的对象向下查找,⽤⿊灰⽩的规则,标记出所有跟GC Root相连接的对象,扫描⼀遍结束后,⼀般需要进⾏⼀次短暂的STW(Stop The World),再次进⾏扫描,此时因为⿊⾊对象的属性都也已经被标记过了,所以只需找出灰⾊对象并顺着继续往下标记(且因为⼤部分的标记⼯作已经在第⼀次并发的时候发⽣了,所以灰⾊对象数量会很少,标记时间也会短很多), 此时程序继续执⾏,GC线程扫描所有的内存,找出扫描之后依旧被标记为⽩⾊的对象(垃圾),清除。

具体流程:⾸先创建三个集合:⽩、灰、⿊。

将所有对象放⼊⽩⾊集合中。

然后从根节点开始遍历所有对象(注意这⾥并不递归遍历),把遍历到的对象从⽩⾊集合放⼊灰⾊集合。

之后遍历灰⾊集合,将灰⾊对象引⽤的对象从⽩⾊集合放⼊灰⾊集合,之后将此灰⾊对象放⼊⿊⾊集合重复 4 直到灰⾊中⽆任何对象通过write-barrier检测对象有变化,重复以上操作收集所有⽩⾊对象(垃圾)三⾊标记存在问题浮动垃圾:并发标记的过程中,若⼀个已经被标记成⿊⾊或者灰⾊的对象,突然变成了垃圾,由于不会再对⿊⾊标记过的对象重新扫描,所以不会被发现,那么这个对象不是⽩⾊的但是不会被清除,重新标记也不能从GC Root中去找到,所以成为了浮动垃圾,浮动垃圾对系统的影响不⼤,留给下⼀次GC进⾏处理即可。

垃圾回收机制

垃圾回收机制

垃圾回收机制垃圾回收器GC(Garbage Collection):JAVA/.NET中的垃圾回收器。

Java是由C++发展来的。

它摈弃了C++中⼀些繁琐容易出错的东西。

其中有⼀条就是这个GC。

⽽C#⼜借鉴了JAVA。

垃圾回收的原因从计算机组成的⾓度来讲,所有的程序都是要驻留在内存中运⾏的。

⽽内存是⼀个限制因素(⼤⼩)。

除此之外,托管堆也有⼤⼩限制。

因为地址空间和存储的限制因素,托管堆要通过垃圾回收机制,来维持它的正常运作,保证对象的分配,尽可能不造成“内存溢出”。

⼤⽩话原理:我们定义变量会申请内存空间来存放变量的值,⽽内存的容量是有限的,当⼀个变量值没有⽤了(称为垃圾),就应该将其占⽤的内存给回收掉。

变量名是访问到变量的唯⼀⽅式,所以当⼀个变量值没有任何关联的变量名时,我们就⽆法访问到该变量了,该变量就是⼀个垃圾,会被程序的垃圾回收机制⾃动回收。

垃圾(Garbage)就是程序需要回收的对象,如果⼀个对象不在被直接或间接地引⽤,那么这个对象就成为了「垃圾」,它占⽤的内存需要及时地释放,否则就会引起「内存泄露」。

有些语⾔需要程序员来⼿动释放内存(回收垃圾),有些语⾔有垃圾回收机制(GC)。

本⽂就来讨论GC实现的三种基本⽅式。

其实这三种⽅式也可以⼤体归为两类:跟踪回收,引⽤计数。

美国IBM的沃森研究中⼼David F.Bacon等⼈发布的「垃圾回收统⼀理论」⼀⽂阐述了⼀个理论:任何垃圾回收的思路,⽆⾮以上两种的组合,其中⼀种的改善和进步,必然伴随着另⼀种的改善和进步。

垃圾回收的基本原理算法思路都是⼀致的:把所有对象组成⼀个集合,或可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到,这个对象就被回收了垃圾回收算法跟踪回收跟踪回收的⽅式独⽴于程序,定期运⾏来检查垃圾,需要较长时间的中断。

标记—清除算法(Mark-Sweep)标记—清除算法是最基础的收集算法,它分为“标记”(mark)和“清除”(sweep)两个阶段:⾸先标记出所需回收的对象,在标记完成后统⼀回收掉所有被标记的对象,它的标记过程其实就是前⾯的可达性分析算法中判定垃圾对象的标记过程。

jvm老年代回收机制

jvm老年代回收机制

jvm老年代回收机制JVM的老年代回收机制涉及到处理那些在新生代中经历了一定数量的垃圾回收周期后仍然存活的对象。

这些对象被认为是长期存活的,因此会从新生代晋升到老年代。

老年代的回收策略有以下特点:1. Major GC: 老年代的垃圾收集被称为Major GC或Full GC,因为它通常会涉及到整个Java堆或者是整个老年代的垃圾收集过程。

Major GC相比Minor GC(针对新生代)会有更大的性能开销。

2. 混合GC(Mixed GC): 这是指同时对整个新生代以及部分老年代进行的垃圾收集。

当越来越多的对象晋升到老年代时,虚拟机可能会触发Mixed GC来避免内存耗尽。

3. CMS GC: 并发标记清除(CMS, Concurrent Mark Sweep)是JVM 中用于老年代的一种垃圾收集算法。

它尝试最小化应用程序暂停时间。

CMS在进行垃圾回收的主要工作时,应用线程仍然可以运行。

4. G1 GC: Garbage-First是一种更先进的垃圾回收算法,它把堆分成多个大小相等的区域,并预测每个区域中的垃圾数量来决定回收的顺序。

这种算法适用于大内存的服务器应用。

5. Full GC: 除了Major GC外,还有一种称为Full GC的过程,它会清理整个堆空间——包括新生代、老年代、元数据区等所有区域。

Full GC通常在出现OutOfMemoryError之前发生,或者在调用System.gc()时被触发。

6. 老年代的内存管理: 由于老年代中对象的生命周期较长,其空间分配和管理更为复杂。

老年代的回收算法需要能够有效地处理大量长时间存在的对象。

这通常通过使用不同的标记、清除和压缩技术来实现。

7. 内存占比和晋升: JVM中有一个叫做“老年阈值”的概念,即对象在经历几次Minor GC后仍存活,就会从新生代晋升到老年代。

这个晋升策略与老年代的空间占用情况密切相关。

8. 卡表: 在实现老年代垃圾回收时,JVM还使用了卡表(Card Table)这一机制来减少检查老年代中对象所花费的时间。

Java垃圾回收机制

Java垃圾回收机制

垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。

垃圾收集的目的在于清除不再使用的对象。

GC通过确定对象是否被活动对象引用来确定是否收集该对象。

GC首先要判断该对象是否是时候可以收集。

两种常用的方法是引用计数和对象引用遍历。

引用计数收集器引用计数是垃圾收集器中的早期策略。

在这种方法中,堆中每个对象(不是引用)都有一个引用计数。

当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。

当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。

任何引用计数为0的对象可以被当作垃圾收集。

当一个对象被垃圾收集时,它引用的任何对象计数减1。

优点:引用计数收集器可以很快的执行,交织在程序运行中。

对程序不被长时间打断的实时环境比较有利。

缺点:无法检测出循环引用。

如父对象有一个对子对象的引用,子对象反过来引用父对象。

这样,他们的引用计数永远不可能为0.跟踪收集器早期的JVM使用引用计数,现在大多数JVM采用对象引用遍历。

对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。

如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。

在对象遍历阶段,GC必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

下一步,GC要删除不可到达的对象。

删除时,有些GC只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。

这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。

因此,许多GC可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

JVM内存垃圾回收方法

JVM内存垃圾回收方法

JVM内存垃圾回收⽅法概要:why:为什么回收,见whatwhat:垃圾回收哪些内存(不可达对象的确定)when:何时执⾏GC(安全点、安全区域)how:如何回收(原理——垃圾回收算法、实现——垃圾收集器)1、垃圾回收哪些内存JVM运⾏时数据区中,线程私有的程序计数器、虚拟机栈、本地⽅法栈随线程的创建和退出⽽⾃动产⽣和销毁,不需要垃圾回收;⽽对于⽅法区和堆区,由于是随虚拟机的启动和退出⽽创建和销毁,在这期间被各线程共享,若不回收垃圾以腾出空间则最终会耗尽这两部分空间。

因此,JVM垃圾回收的是共享区域的内存,主要是⽅法区和Java堆内存的回收。

1.1、⽅法区⽅法区的垃圾收集主要是回收废弃常量和⽆⽤的类(卸载类)。

回收废弃常量与下⾯将介绍的回收Java堆中的对象很相似,⽽判定“⽆⽤的类”需同时满⾜三个条件:1、该类所有实例已被回收,即Java堆中⽆该类的任何实例。

(下层)2、该类对应的ng.Class对象没有在任何地⽅被引⽤,⽆在任何地⽅通过反射访问该类的⽅法。

(下层)3、加载该类的ClassLoader已被回收。

(上层)java 8提供了-xx:MetaspaceSize来设置触发元空间垃圾回收的阈值。

1.2、堆Java堆⾥⾯存放着⼏乎所有的对象实例,垃圾收集器对堆进⾏回收前,⾸先要做的就是确定哪些对象可以作为垃圾回收。

JDK1.2后,Java对引⽤概念进⾏了扩充,将引⽤分为强引⽤(Strong Reference)、软引⽤(Soft Reference)、弱引⽤(Weak Reference)、虚引⽤(Phantom Reference)、终引⽤(Final Reference)。

关于Java Reference,可参阅。

总的来说,回收的堆对象有两类:1、有被引⽤的对象:即被软引⽤、弱引⽤、虚引⽤所引⽤的对象可能被JVM强制当成垃圾回收。

1、软引⽤:软引⽤对象在系统将要发⽣内存耗尽(OOM)前会被回收。

javajvm垃圾回收原理

javajvm垃圾回收原理

Java虚拟机(JVM)的垃圾回收原理是指在运行Java程序时,JVM自动管理内存的过程。

垃圾回收是指自动识别和释放不再使用的内存,以便重新分配给其他需要的对象。

JVM的垃圾回收原理主要包括以下几个步骤:
1. 标记:JVM首先标记所有活动对象,即那些仍然被引用的对象。

从根对象(如方法栈、静态变量等)开始,通过可达性分析算法,递归地遍历对象图,将所有可达的对象标记为活动对象。

2. 清除:在标记完成后,JVM会对堆内存中的所有对象进行遍历,将未被标记的对象判定为垃圾对象,并将其所占用的内存空间释放出来。

3. 压缩:在清除垃圾对象后,JVM会对堆内存进行压缩,将存活对象向一端移动,以便为新对象分配连续的内存空间,减少内存碎片化。

4. 分配:在压缩完成后,JVM会为新对象分配内存空间,并更新堆指针,以便下次分配内存时能够快速找到可用的内存空间。

JVM的垃圾回收机制采用了自适应的算法,根据当前的内存使用情况和程序的运行情况,动态调整垃圾回收的策略和参数,以提高垃圾回收的效率和性能。

需要注意的是,垃圾回收是一个相对耗时的操作,会占用一定的系统资源。

因此,在编写Java程序时,应尽量避免产生大量的垃圾对象,合理管理内存的使用,以提高程序的性能和效率。

jvm垃圾回收(区域、时间、算法)

jvm垃圾回收(区域、时间、算法)

jvm垃圾回收(区域、时间、算法)1、进⾏垃圾回收的区域(1)堆(2)⽅法区栈是线程的私有数据,所以不进⾏垃圾回收2、垃圾回收的时间对这个对象不再引⽤的时候public class ReferenceCountingGC {private static final int MB=1024*1024;public Object instance=null;private byte[] size=new byte[2*MB];public static void main(String[] args) {ReferenceCountingGC referenceCountingGC1=new ReferenceCountingGC();ReferenceCountingGC referenceCountingGC2=new ReferenceCountingGC();//循环引⽤referenceCountingGC1.instance=referenceCountingGC2;referenceCountingGC2.instance=referenceCountingGC1;referenceCountingGC1=null;referenceCountingGC2=null;System.gc();;}}[Full GC (System.gc())[Tenured: 0K->640K(86016K), 0.0045506 secs] 6862K->640K(124736K),[Metaspace: 3223K->3223K(1056768K)], 0.0046551 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]Heapdef new generation total 38784K, used 345K [0x0000000082200000, 0x0000000084c10000, 0x00000000ac150000)eden space 34496K, 1% used [0x0000000082200000, 0x0000000082256548, 0x00000000843b0000)from space 4288K, 0% used [0x00000000843b0000, 0x00000000843b0000, 0x00000000847e0000)to space 4288K, 0% used [0x00000000847e0000, 0x00000000847e0000, 0x0000000084c10000)tenured generation total 86016K, used 640K [0x00000000ac150000, 0x00000000b1550000, 0x0000000100000000)the space 86016K, 0% used [0x00000000ac150000, 0x00000000ac1f0040, 0x00000000ac1f0200, 0x00000000b1550000)Metaspace used 3230K, capacity 4496K, committed 4864K, reserved 1056768Kclass space used 350K, capacity 388K, committed 512K, reserved 1048576K(1)引⽤计数给对象添加⼀个引⽤计数器,每当这个对象进⾏⼀次引⽤,计数器就加1;每当引⽤失效的时候,计数器就减1。

Java垃圾回收机制研究

Java垃圾回收机制研究

Java垃圾回收机制研究作者:杨毅来源:《计算机光盘软件与应用》2013年第22期摘要:Java垃圾回收机制是Java最重要的几个功能之一,这个机制可以确保Java能有效、安全的对内存进行管理,同时也降低了编程难度,提高了编程效率。

关键词:Java 垃圾回收;Java虚拟机中图分类号:TP312.2Java垃圾指的是在堆内存中不再使用的Java对象,这些对象占据了一定的内存空间,如果这些空间不被释放,就会造成因垃圾过多而内存耗尽,造成系统崩溃。

Java中的垃圾不需要显示释放,而是通过垃圾回收器自动回收空间。

1 Java的垃圾回收机制Java语言来源于C++语言,在C++程序中,每定义了一个变量,就需要在内存中开辟一个空间来存储这个变量。

当程序不再使用这个变量的时候,就需要释放这个内存空间资源,好让别的变量来用它。

而释放无用变量内存空间的事情要由程序员自己来解决,这样显然是非常繁琐的。

当程序比较大,变量多的时候往往程序员就忘记释放内存或者在不该释放的时候释放内存了,从而引发了内存的溢出或者泄露。

相对C++语言来说,Java去除了其难以理解和掌握的特性,引入了垃圾回收机制,使C++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。

垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。

2 符合回收机制的条件垃圾回收器通常是作为一个单独的线程来运行,以不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能显式的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

Java的垃圾回收条件主要有以下四种:(1)空引用。

当对象没有引用指向时,这个对象就符合垃圾回收的条件,如下代码中p1就符合被回收的条件。

Java代码:Person p1= new Person("A");p1=null;(2)重新为引用变量赋值。

垃圾回收器的工作原理

垃圾回收器的工作原理

垃圾回收器的工作原理
垃圾回收器的工作原理是通过自动检测和清除程序中不再使用的内存对象来实现内存管理。

它的主要工作包括以下几个步骤:
1. 标记:垃圾回收器首先会从根对象(如全局变量、活动栈等)开始,遍历程序对象的引用链,将可达的对象标记为“存活”。

2. 清除:清除阶段会遍历整个堆内存,将未被标记为“存活”的对象当作垃圾,将其所占用的内存空间释放出来。

3. 压缩:清除阶段可能会留下大量不连续的内存空间碎片。

为了解决这个问题,垃圾回收器会进行内存压缩操作,将存活对象紧凑地排列在一起,使得内存空间得到整理。

4. 再分配:经过压缩后,垃圾回收器会记录下可用的内存空间,并将这些空间划分为一系列更小的块,以备后续的对象分配使用。

垃圾回收器的工作原理基于以下几个基本假设:
1. 引用可达性:只有可达的对象才被认为是“存活”的,垃圾回收器通过根对象遍历引用链,确定哪些对象是可达的。

2. 内存分配速度小于回收速度:保证在未来的内存分配中,总是能够有足够的内存空间供分配对象使用。

3. 垃圾对象不再被引用:垃圾回收器需要保证在清除阶段,所有未被标记的对象都不再被引用,以免误删存活对象。

垃圾回收器可以通过不同的算法实现,例如标记-清除、标记-
整理、复制、分代等。

每种算法都有其特定的优缺点和适用场景,但它们的基本原理都是相似的。

Java的垃圾回收机制:强制回收System.gc()Runtime.getTime().gc()

Java的垃圾回收机制:强制回收System.gc()Runtime.getTime().gc()

Java的垃圾回收机制:强制回收System.gc()Runtime.getTime().gc()垃圾回收当引⽤类型的实体,如对象、数组等不再被任何变量引⽤的时候。

这块占⽤的内存就成为了垃圾。

JVM会根据⾃⼰的策略决定是回收内存注意:1. 垃圾回收只回收内存中的对象,⽆法回收物理资源(数据库连接,⽹络IO等)2. 程序⽆法精确的控制台垃圾回收的运⾏,垃圾回收汇总任何时候进⾏,系统⾃动。

3. 在垃圾回收机制回收任何对象之前总会调⽤他的finalize()⽅法。

对象在内存中的三种状态:1. 可达状态:对象有变量再引⽤。

2. 可恢复状态:如果⼀个对象没有任何变量引⽤它,但是调⽤了finalize()后⼜有新的变量引⽤了对象,中间的状态为“可恢复状态”。

3. 不可达状态:对象没有变量引⽤,并且重新调⽤了finalize()⽅法后,还没有变成可达状态,就变为不可达状态,系统开始回收资源。

强制垃圾回收System.gc() Runtime.getRuntime.gc()package com.zmd.study.rubbish;import ;/*** @ClassName RubbishTest* @projectName: object1* @author: Zhangmingda* @description:测试⼲预垃圾回收* date: 2021/4/6.*/public class RubbishTest {private String name;//构造⽅法public RubbishTest(String name) { = name;}//重写finalize增加输出便于观察是否⾃动回收了对象@Overrideprotected void finalize() throws Throwable {System.out.println(name + "要被回收了");super.finalize();}//测试创建多个对象,看垃圾有没有⾃动回收public static void main(String[] args) {for(int i=0;i<1000; i++) {new RubbishTest("name" + i);System.out.println("循环打印" + "name" + i);//强制垃圾回收,当没有变量引⽤上⾯new出来的对象,就会调⽤finalize()⽅法回收内存System.gc();//Runtime.getRuntime().gc();} } }。

GC垃圾回收机制

GC垃圾回收机制

GC垃圾回收机制1.1GC概述垃圾回收是⼀种⾃动的存储管理机制。

当⼀些被占⽤的内存不再需要时,就应该予以释放,以让出空间,这种存储资源管理,称为垃圾回收(Garbage Collection)。

垃圾回收器可以让程序员减轻许多负担,也减少程序员犯错的机会。

1.2GC执⾏时机GC触发的条件有两种:(1)程序调⽤System.gc时可以触发;(2)系统⾃⾝来决定GC触发的时机。

了解Minor GC触发条件:当Eden区满时,触发Minor GC。

Full GC触发条件:调⽤System.gc时,系统建议执⾏Full GC,但是不必然执⾏⽼年代空间不⾜⽅法区空间不⾜通过Minor GC后进⼊⽼年代的平均⼤⼩⼤于⽼年代的可⽤内存1.3GC内容⾃动垃圾回收机制就是寻找Java堆中的对象,并对对象进⾏分类判别,寻找出正在使⽤的对象和已经不会使⽤的对象,然后把那些不会使⽤的对象从堆上清除。

如何区别这两类对象呢?这就有了两种⽅式:引⽤计数法引⽤计数算法是垃圾收集器中的早期策略。

在这种⽅法中,堆中的每个对象实例都有⼀个引⽤计数。

当⼀个对象被创建时,且将该对象实例分配给⼀个引⽤变量,该对象实例的引⽤计数设置为 1。

当任何其它变量被赋值为这个对象的引⽤时,对象实例的引⽤计数加 1(a = b,则b引⽤的对象实例的计数器加1),但当⼀个对象实例的某个引⽤超过了⽣命周期或者被设置为⼀个新值时,对象实例的引⽤计数减 1。

特别地,当⼀个对象实例被垃圾收集时,它引⽤的任何对象实例的引⽤计数器均减 1。

任何引⽤计数为0的对象实例可以被当作垃圾收集。

引⽤计数收集器可以很快的执⾏,并且交织在程序运⾏中,对程序需要不被长时间打断的实时环境⽐较有利,但其很难解决对象之间相互循环引⽤的问题。

可达性分析可达性分析算法是从离散数学中的图论引⼊的,程序把所有的引⽤关系看作⼀张图,通过⼀系列的名为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所⾛过的路径称为引⽤链(Reference Chain)。

Java垃圾回收策略

Java垃圾回收策略

Java垃圾回收策略随着软件开发的不断发展,内存管理一直被认为是一个重要的议题。

在传统的编程语言中,程序员需要手动管理内存,这给开发者带来了很大的负担。

为了解决这个问题,Java引入了垃圾回收机制,使得程序员不需要关心内存的分配和释放,大大简化了程序的开发。

Java的垃圾回收机制是基于自动垃圾回收器(Garbage Collector, GC)实现的。

自动垃圾回收器会周期性地检查程序中的对象,标记出不再被使用的对象,并释放它们占用的内存空间。

这样,开发人员就不需要手动释放内存,大大降低了内存管理的复杂度。

在Java中,垃圾回收策略主要分为四种类型:标记-清除、复制、标记-整理和分代回收。

不同的策略适用于不同的场景,下面将逐一介绍这四种策略。

1. 标记-清除(Mark-Sweep)标记-清除是最基本的垃圾回收算法之一。

它通过标记不再使用的对象,并在标记完成后,清除这些对象所占用的内存空间。

标记-清除算法的缺点是会产生内存碎片,这可能会导致内存分配时出现不连续的空间,影响程序的性能。

2. 复制(Copying)复制算法是将内存分为两个相等的部分,每次只使用其中一部分。

当一部分的内存空间用完后,将还存活的对象复制到另一部分,然后清除已使用的那部分。

复制算法的优点是不会产生内存碎片,但是也会导致内存利用率降低。

3. 标记-整理(Mark-Compact)标记-整理算法在标记-清除算法的基础上做了改进。

它通过标记不再使用的对象,并将存活的对象向一端移动,然后清理整理出连续的内存空间。

标记-整理算法解决了标记-清除算法的内存碎片问题,但仍然可能导致内存利用率较低。

4. 分代回收(Generational)分代回收算法是基于一种观察:大部分对象在创建后很快就变得不可达。

基于这个观察,分代回收算法将内存分为多个代(Generation),并根据对象的年龄将其放置在不同的代中。

这样,在垃圾回收时,只需要对某一代的对象进行回收,提高了回收效率。

GC介绍之引用计数法

GC介绍之引用计数法

GC介绍之引⽤计数法⼀:JVM垃圾回收机制为什么栈不会有垃圾回收机制:栈内存中⽅法运⾏完毕后会有弹栈的操作,不会产⽣垃圾;堆内存中却没有这种操作,当堆内存中很多⽆⽤的成员变量、对象等等积压到⼀定程度时,就会发⽣堆内存溢出的⼀个错误OutOfMemoryError (Java heap space)堆内存溢出,虽然说堆内存的⼤⼩是可以调节的,但是它还是解决不了根本问题。

那么为了避免这种情况的发⽣,出现了垃圾回收机制,也就是我们所说的GC。

⼆:垃圾回收的伊甸区3.伊甸区(Eden)新对象被创建时,通常便会被分配到伊甸区。

由于通常都会有多个线程在同时分配⼤量的对象,因为伊甸区⼜被进⼀步划分成⼀个或多个线程本地分配缓冲(Thread Local Allocation Buffer,简称TLAB)。

有了这些缓冲区使得JVM中⼤多数对象的分配都可以在各个线程⾃⼰对应的TLAB 中完成,从⽽避免了线程间昂贵的同步开销。

TLAB中⽆法完成分配(通常是由于没有⾜够的空间),便会到伊甸区的共享空间中进⾏分配。

如果这⾥还是没有⾜够的空间,则会触发⼀次新⽣代垃圾回收的过程来释放空间。

如果垃圾回收后伊甸区还是没有⾜够的空间,那么这个对象便会到⽼⽣代中去分配。

三:堆内存的结构堆内存逻辑上是分为三个部分:新⽣代、养⽼代、永久代(jdk1.7以后我们称永久代为元空间)。

但是实际上负责存储的只有:新⽣代、养⽼代。

四:垃圾回收机制回收机制介绍(⼀种轻GC是在伊甸区和幸存区,⼀种重GC是在养⽼区)注意:没有元空间的垃圾回收机制对象在伊甸区(Eden)被new出来,当伊甸区满了以后还需要创建对象,这时候JVM会对伊甸区进⾏垃圾回收(YGC也叫轻GC),将伊甸区中的没有被其他对象所引⽤的对象进⾏销毁(finalize()⽅法⽤于销毁对象的)。

然后将伊甸区中存活的对象移动到幸存0区,并且该对象年龄为1,当伊甸区再满了之后会对伊甸区和幸存0区的对象进⾏GC,然后会将伊甸区和幸存0区存活的对象移动到幸存1区,如果当前存活的对象GC前是幸存区的,那么他们的年龄+1,就这样GC⼀次交换⼀次年龄增长⼀次,如果有对象经过了15次GC依然存活(15岁),会被转移到养⽼区(Old),当养⽼区满了之后也会进⾏垃圾回收(Full GC也叫重GC),对养⽼区进⾏垃圾清理,当最后没有可清理的垃圾时且新⽣代、养⽼代都满了之后,会报⼀个异常:OutOfMemoryError (Java heap space)异常原因:代码中创建了⼤量的对象,且长时间不能被回收,导致创建新对象出现堆内存溢出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JVM的垃圾回收机制小读技术2010-05-09 19:41:04 阅读20 评论2 字号:大中小订阅今天下午突然遇到了一个内存漏洞的问题,所以上网查了查,结果看到了一篇文章,说的是jvm的垃圾回收机制,下面粘过来,看了好久才看完的,说的思路有点含糊,还给带了点代码,这样还不错……对JVM的内存管理机制有加深了一层理解哈…………下面是那篇文章,喜欢的可以看看…………O(∩_∩)O…………Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。

Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。

引言Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。

Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。

一般来说,堆的是由垃圾回收来负责的,尽管JVM规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在实现的时候都有一个由垃圾回收所管理的堆。

垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。

垃圾收集的意义在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。

JVM的一个系统级线程会自动释放该内存块。

垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。

当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。

事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。

由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。

碎片是分配给对象的内存块之间的空闲内存洞。

碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。

垃圾收集能自动释放内存空间,减轻编程的负担。

这使Java 虚拟机具有一些优点。

首先,它能使编程效率提高。

在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。

在用Java 语言编程的时候,靠垃圾收集机制可大大缩短时间。

其次是它保护程序的完整性,垃圾收集是Java语言安全性策略的一个重要部份。

垃圾收集的一个潜在的缺点是它的开销影响程序性能。

Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。

这一个过程需要花费处理器的时间。

其次垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%收集到所有的废弃内存。

当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。

垃圾收集的算法分析Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就量正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。

垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。

而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。

下面介绍几个常用的算法。

1、引用计数法(Reference Counting Collector)引用计数法是唯一没有使用根集的垃圾回收的法,该算法使用引用计数器来区分存活对象和不再使用的对象。

一般来说,堆中的每个对象对应一个引用计数器。

当每一次创建一个对象并赋给一个变量时,引用计数器置为1。

当对象被赋给任意变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须实时运行的程序。

但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量,计数器加1,而每次现有对象出了作用域生,计数器减1。

2、tracing算法(Tracing Collector)tracing算法是为了解决引用计数法的问题而提出,它使用了根集的概念。

基于tracing算法的垃圾收集器从根集开始扫描,识别出哪些对象可达,哪些对象不可达,并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。

在扫描识别过程中,基于tracing算法的垃圾收集也称为标记和清除(mark-and-sweep)垃圾收集器.3、compacting算法(Compacting Collector)为了解决堆碎片问题,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的过程中,算法将所有的对象移到堆的一端,堆的另一端就变成了一个相邻的空闲内存区,收集器会对它移动的所有对象的所有引用进行更新,使得这些引用在新的位置能识别原来的对象。

在基于Compacting算法的收集器的实现中,一般增加句柄和句柄表。

4、copying算法(Coping Collector)该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。

它开始时把堆分成一个对象面和多个空闲面,程序从对象面为对象分配空间,当对象满了,基于coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。

一种典型的基于coping算法的垃圾回收是stop-and-copy算法,它将堆分成对象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行。

5、generation算法(Generational Collector)stop-and-copy垃圾收集器的一个缺陷是收集器必须复制所有的活动对象,这增加了程序等待时间,这是coping算法低效的原因。

在程序设计中有这样的规律:多数对象存在的时间比较短,少数的存在时间比较长。

因此,generation算法将堆分成两个或多个,每个子堆作为对象的一代(generation)。

由于多数对象存在的时间比较短,随着程序丢弃不使用的对象,垃圾收集器将从最年轻的子堆中收集这些对象。

在分代式的垃圾收集器运行后,上次运行存活下来的对象移到下一最高代的子堆中,由于老一代的子堆不会经常被回收,因而节省了时间。

6、adaptive算法(Adaptive Collector)在特定的情况下,一些垃圾收集算法会优于其它算法。

基于Adaptive算法的垃圾收集器就是监控当前堆的使用情况,并将选择适当算法的垃圾收集器。

透视Java垃圾回收1、命令行参数透视垃圾收集器的运行2、使用System.gc()可以不管JVM使用的是哪一种垃圾回收的算法,都可以请求Java的垃圾回收。

在命令行中有一个参数-verbosegc可以查看Java使用的堆内存的情况,它的格式如下:java -verbosegc classfile可以看个例子:class TestGC{public static void main(String[] args){new TestGC();System.gc();System.runFinalization();}}在这个例子中,一个新的对象被创建,由于它没有使用,所以该对象迅速地变为可达,程序编译后,执行命令:java -verbosegc TestGC 后结果为:[Full GC 168K->97K(1984K),0.0253873 secs]机器的环境为,Windows 2000 + JDK1.3.1,箭头前后的数据168K和97K分别表示垃圾收集GC前后所有存活对象使用的内存容量,说明有168K-97K=71K的对象容量被回收,括号内的数据1984K为堆内存的总容量,收集所需要的时间是0.0253873秒(这个时间在每次执行的时候会有所不同)。

3、finalize方法透视垃圾收集器的运行在JVM垃圾收集器收集一个对象之前,一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,Java提供了缺省机制来终止化该对象心释放资源,这个方法就是finalize()。

它的原型为:protected void finalize() throws Throwable在finalize()方法返回之后,对象消失,垃圾收集开始执行。

原型中的throws Throwable表示它可以抛出任何类型的异常。

之所以要使用finalize(),是由于有时需要采取与Java的普通方法不同的一种方法,通过分配内存来做一些具有C风格的事情。

这主要可以通过"固有方法"来进行,它是从Java里调用非Java方法的一种方式。

C和C++是目前唯一获得固有方法支持的语言。

但由于它们能调用通过其他语言编写的子程序,所以能够有效地调用任何东西。

在非Java代码内部,也许能调用C的malloc()系列函数,用它分配存储空间。

而且除非调用了free(),否则存储空间不会得到释放,从而造成内存"漏洞"的出现。

当然,free()是一个C和C++函数,所以我们需要在finalize()内部的一个固有方法中调用它。

也就是说我们不能过多地使用finalize(),它并不是进行普通清除工作的理想场所。

在普通的清除工作中,为清除一个对象,那个对象的用户必须在希望进行清除的地点调用一个清除方法。

这与C++"破坏器"的概念稍有抵触。

在C++中,所有对象都会破坏(清除)。

或者换句话说,所有对象都"应该"破坏。

若将C++对象创建成一个本地对象,比如在堆栈中创建(在Java中是不可能的),那么清除或破坏工作就会在"结束花括号"所代表的、创建这个对象的作用域的末尾进行。

若对象是用new创建的(类似于Java),那么当程序员调用C++的delete命令时(Java没有这个命令),就会调用相应的破坏器。

若程序员忘记了,那么永远不会调用破坏器,我们最终得到的将是一个内存"漏洞",另外还包括对象的其他部分永远不会得到清除。

相关文档
最新文档