JVM调优总结(三)基本垃圾回收算法
- 格式:doc
- 大小:63.00 KB
- 文档页数:3
垃圾回收算法1.标记清除标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。
在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。
然后,在清除阶段,清除所有未被标记的对象。
适用场合:●存活对象较多的情况下比较高效●适用于年老代(即旧生代)缺点:●容易产生内存碎片,再来一个比较大的对象时(典型情况:该对象的大小大于空闲表中的每一块儿大小但是小于其中两块儿的和),会提前触发垃圾回收●扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)2.复制算法从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存(图中下边的那一块儿内存)上去,之后将原来的那一块儿内存(图中上边的那一块儿内存)全部回收掉现在的商业虚拟机都采用这种收集算法来回收新生代。
适用场合:●存活对象较少的情况下比较高效●扫描了整个空间一次(标记存活对象并复制移动)●适用于年轻代(即新生代):基本上98%的对象是”朝生夕死”的,存活下来的会很少缺点:●需要一块儿空的内存空间●需要复制移动对象3.标记整理复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。
这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。
如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。
标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。
首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。
之后,清理边界外所有的空间。
这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。
4.分代收集算法分代收集算法就是目前虚拟机使用的回收算法,它解决了标记整理不适用于老年代的问题,将内存分为各个年代。
一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(Permanet Generation)。
Jvm垃圾回收机制Jvm垃圾回收机制(根据java编程思想进⾏总结)⾸先打个⽐⽅C++⾥⾯的堆想象成⼀个院⼦,⾥⾯每个对象都负责管理⾃⼰的地盘,⼀段时间以后,对象可能被销毁,但地盘必须加以重⽤。
但在某些java虚拟机中堆的分配更像是传送带,没分配⼀个对象,他就往前移动⼀格。
但是java的堆并不是完全像传送带那样⼯作,那样会导致频繁的内存页⾯调度进⽽影响到性能。
其中的关键在与垃圾回收器的介⼊,当堆在⼯作的时候,将⼀⾯回收空间,⼀⾯使堆中对象紧凑的排列,这样“堆指针”就更容易移动到靠近传送带的开始处,也就尽量避免了页⾯的错误。
通过垃圾回收器对对象重新排列,实现了⼀种⾼速的,有⽆限空间的可供分配的堆模型。
⾸先了解下其他的垃圾回收机制:⼀、引⽤计数引⽤计数是⼀种简单但是很慢的垃圾回收技术。
每个对象都含有⼀个引⽤计数器,当有引⽤链接⾄对象时,引⽤计数加1。
当引⽤离开作⽤于或被设置为null时,引⽤计数减1.虽然管理引⽤技术的开销不⼤,但这项开销在整个程序的⽣命周期中将持续发⽣。
垃圾回收期会在含有全部对象的列表上遍历,当发现某个对象的引⽤计数为0时,就释放其占⽤的空间(但是引⽤计数模式经常会在记数值变为0时⽴即释放对象)。
这个⽅法存在⼀种缺陷,如果对象之间存在循环引⽤,可能会出现“对象应该被回收,但引⽤记数却不为0”的情况。
引⽤记数常⽤来说明垃圾收集的⼯作⽅式,单似乎未被⽤⽤于任何⼀种java虚拟机实现中。
⼆、停⽌-复制(stop-and-copy)将所有存活的对象复制到新堆,其他都是垃圾缺陷:1.两个堆2.稳定状态下,还是会发⽣复制。
解决办法:1.堆中分配⼏块较⼤的内存,复制发⽣在较⼤的内存块。
2.标记—清扫B.基于“对于任何活的对象,⼀定能最终追溯到其存活在堆栈或静态存储区之中的引⽤。
”java虚拟机将采⽤⼀种⾃适应的垃圾回收技术。
⾄于如何找到存活对象,取决于不同的java虚拟机实现。
⼀种做法名叫停⽌-复制(stop-and-copy),意味着先暂停程序的运⾏(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另⼀个堆,没有被复制的全部都是垃圾。
JVM垃圾回收机制原理及调优JVM(Java Virtual Machine)是Java程序的运行环境,可以将Java字节码转换为机器码并执行程序。
其中一个重要的机制就是垃圾回收(Garbage Collection,GC),它负责自动释放不再使用的内存资源,以提高内存的利用率。
JVM中的垃圾回收机制基于两个核心概念:引用和可达性。
引用是指在程序中使用一个对象的指针。
Java中有四种类型的引用:强引用、软引用、弱引用和虚引用。
强引用是最常见的引用类型,只有当没有任何强引用指向一个对象时,垃圾回收器才会回收该对象。
软引用和弱引用可以用来实现缓存功能,如果内存不足时,垃圾回收器会回收这些对象。
虚引用是最弱的引用类型,主要用于对象被回收前的通知。
可达性是指对象能否通过引用链被访问到。
在Java中,垃圾回收器通过从GC Roots(如活动线程、静态变量、方法区中的类静态常量等)出发,追踪所有的引用链,可以到达的对象被认为是可达的,而无法到达的对象则被判定为垃圾。
JVM的垃圾回收机制有多种算法,常见的有标记清除、复制、标记整理、分代回收等。
标记清除算法是最基本的垃圾回收算法,分为两个阶段。
首先,垃圾回收器从根对象出发,将所有的可达对象进行标记。
然后,在标记完成后,垃圾回收器对堆内存进行扫描,将所有未被标记的内存块视为垃圾,进行回收。
复制算法将内存分为两个区域,一半被称为"from"空间,另一半被称为"to"空间。
对象首先存储在from空间,当垃圾回收发生时,将有效的对象存储到to空间并压缩,然后清空from空间。
通过多次复制过程,可以避免内存碎片化问题。
标记整理算法是在标记清除算法基础上的改进,它会在标记阶段将所有的可达对象进行标记,并在垃圾回收阶段将标记的对象整理到内存的一侧,从而减少碎片化问题。
分代回收算法根据对象的生命周期将内存划分为不同的代。
一般将新创建的对象放在新生代,时间经受住垃圾回收的对象放在年老代。
JVM调优总结作者: 和你在一起程序员其实很痛苦的,每隔一段时间就会听到、看到很多很多新名词、新技术---囧.幸而有了互联网,有了开源、有了wiki、有了分享:)—人人为我,我为人人。
拓荒者走过的时候很痛苦,但是如果能给后来人留下点路标,是不是可以让他们少走一些弯路呢?踏着前辈的足迹我走到了这里,也应该为后来的人留下点东西。
走夜路其实不可怕,可怕的是一个人走夜路:) - 做最棒的软件开发交流社区A-PDF Number Pro DEMO: Purchase from to remove the watermark目 录1. java路上1.1 JVM调优总结-序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 1.2 JVM调优总结(一)-- 一些概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 1.3 JVM调优总结(二)-一些概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 1.4 JVM调优总结(三)-基本垃圾回收算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 1.5 JVM调优总结(四)-垃圾回收面临的问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12 1.6 JVM调优总结(五)-分代垃圾回收详述1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14 1.7 JVM调优总结(六)-分代垃圾回收详述2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18 1.8 JVM调优总结(七)-典型配置举例1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 1.9 JVM调优总结(八)-典型配置举例2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 1.10 JVM调优总结(九)-新一代的垃圾回收算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 1.11 JVM调优总结(十)-调优方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38 1.12 JVM调优总结(十一)-反思 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47 1.13 JVM调优总结(十二)-参考资料 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .501.1 JVM调优总结-序发表时间: 2009-11-17几年前写过一篇关于JVM调优的文章,前段时间拿出来看了看,又添加了一些东西。
JVM垃圾回收算法及G1回收机制JVM(Java Virtual Machine)是Java程序运行的环境,其中的垃圾回收算法是JVM内存管理的重要组成部分。
垃圾回收算法的作用是自动释放不再使用的内存空间,以提高程序的性能和效率。
其中,G1(Garbage-First)是一种现代化的垃圾回收器,相较于传统的垃圾回收算法具有更高的效率和更低的延迟。
垃圾回收算法的核心思想是通过扫描内存,找出不再被引用的对象,并将其释放。
常见的垃圾回收算法包括标记-清除算法、复制算法、标记-整理算法等。
标记-清除算法是最基础的垃圾回收算法之一、它通过标记所有被引用的对象,然后清除未被标记的对象。
这个算法的优点是可以处理任意的内存分配情况,但是会产生大量的碎片化空间。
复制算法是另一种常见的垃圾回收算法。
它将内存分为两个区域,每次只使用其中一个区域。
当一个区域满了之后,将还存活的对象复制到另一个区域,然后清除当前区域。
这个算法的优点是简单高效,但是会浪费一半的内存空间。
标记-整理算法是标记-清除算法的改进版。
它先标记所有被引用的对象,然后将存活的对象向一端移动,然后清除边界之外的对象。
这个算法的优点是可以减少碎片化空间,但是会有对象移动的开销。
G1是一种基于标记-整理算法的垃圾回收器,它在Java SE 6u14版本中引入。
G1回收机制主要有以下几个特点:首先,G1将堆内存划分为若干个大小相等的区域(Region),每个区域可以是Eden区、Survivor区或Old区。
这种划分方式可以有效地减少碎片化问题,并且可以根据实际情况动态调整区域的大小。
其次,G1采用了增量式的标记算法,在应用程序运行的同时进行垃圾回收操作。
这样可以减少单次垃圾回收的暂停时间,并且将垃圾回收的工作均匀地分布在多个时间片段中,避免长时间的停顿。
再次,G1使用了全局的标记-整理算法。
它通过标记所有被引用的对象,然后将存活的对象向一端移动,并清除边界之外的对象。
JVM的垃圾回收机制详解和调优1.JVM的GC概述gc即垃圾收集机制是指jv m用于释放那些不再使用的对象所占用的内存。
java语言并不要求jvm有gc,也没有规定gc如何工作。
不过常用的jv m都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。
在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。
有些垃圾收集专用于特殊的应用程序。
比如,实时应用程序主要是为了避免垃圾收集中断,而大多数OLTP应用程序则注重整体效率。
理解了应用程序的工作负荷和jv m支持的垃圾收集算法,便可以进行优化配置垃圾收集器。
垃圾收集的目的在于清除不再使用的对象。
gc通过确定对象是否被活动对象引用来确定是否收集该对象。
gc首先要判断该对象是否是时候可以收集。
两种常用的方法是引用计数和对象引用遍历。
1.1.引用计数引用计数存储对特定对象的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当增减引用数。
当某对象的引用数为0时,便可以进行垃圾收集。
1.2.对象引用遍历早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。
对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。
如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。
在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。
下一步,gc要删除不可到达的对象。
删除时,有些gc只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。
这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。
因此,许多g c可以重新组织内存中的对象,并进行压缩(com pact),形成可利用的空间。
为此,gc需要停止其他的活动活动。
这种方法意味着所有与应用程序相关的工作停止,只有gc运行。
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)前会被回收。
图解JVM垃圾内存回收算法图解JVM垃圾内存回收算法这篇⽂章主要介绍了图解JVM垃圾内存回收算法,由于年轻代堆空间的垃圾回收会很频繁,因此其垃圾回收算法会更加重视回收效率,下⾯博主和⼤家来⼀起学习⼀下吧前⾔⾸先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的⼈都知道以下两点:JVM是做什么的Java堆是什么因为我们即将要讲的就是发⽣在JVM的Java堆上的垃圾回收,为了突出核⼼,其他的⼀些与本篇不太相关的东西我就⼀笔略过了众所周知,Java堆上保存着对象的实例,⽽Java堆的⼤⼩是有限的,所以我们只能把⼀些已经⽤完的,⽆法再使⽤的垃圾对象从内存中释放掉,就像JVM帮助我们⼿动在代码中添加⼀条类似于C++的free语句的⾏为然⽽这些垃圾对象是怎么回收的,现在不知道没关系,我们马上就会讲到怎么判断对象为垃圾对象在了解具体的GC(垃圾回收)算法之前,我们先来了解⼀下JVM是怎么判断⼀个对象是垃圾对象的顾名思义,垃圾对象,就是没有价值的对象,⽤更严谨的语句来说,就是没有被访问的对象,也就是说没有被其他对象引⽤,这就牵引出我们的第⼀个判断⽅案:引⽤计数法引⽤计数法这种算法的原理是,每有⼀个其他对象产⽣对A对象的引⽤,则A对象的引⽤计数值就+1,反之,每有⼀个对象对A对象的引⽤失效的时候,A对象的引⽤计数值就-1,当A对象的引⽤计数值为0的时候,其就被标明为垃圾对象这种算法看起来很美好,了解C++的应该知道,C++的智能指针也有类似的引⽤计数,但是在这种看起来“简单”的⽅法,并不能⽤来判断⼀个对象为垃圾对象,我们来看以下场景:在这个场景中,A对象有B对象的引⽤,B对象也有A对象的引⽤,所以这两个对象的引⽤计数值均不为0,但是,A、B两个对象明明就没有任何外部的对象引⽤,就像⼤海上两个紧挨着的孤岛,即使他们彼此依靠着,但仍然是孤岛,其他⼈过不去,⽽且由于引⽤计数不为0,也⽆法判断为垃圾对象,如果JVM中存在着⼤量的这样的垃圾对象,最终就会频繁抛出OOM异常,导致系统频繁崩溃总⽽⾔之,如果有⼈问你为什么JVM不采⽤引⽤计数法来判断垃圾对象,只需要记住这⼀句话:引⽤计数法⽆法解决对象循环依赖的问题可达性分析法引⽤计数法已经很接近结果了,但是其问题是,为什么每有⼀个对象来引⽤就要给引⽤计数值+1,就好像有⼈来敲门就开⼀样,我们应该只给那些我们认识的、重要的⼈开门,也就是说,只有重要的对象来引⽤时,才给引⽤计数值+1但是这样还不⾏,因为重要的对象来引⽤只要有⼀个就够了,并不需要每有⼀个引⽤就+1,所以我们可以将引⽤计数法优化为以下形式:给对象设置⼀个标记,每有⼀个“重要的对象”来引⽤时,就将这个标记设为true,当没有任何“重要的对象”引⽤时,就将标记设为false,标记为false的对象为垃圾对象这就是可达性分析法的雏形,我们可以继续进⾏修正,我们并不需要主动标记对象,⽽只需要等待垃圾回收时找到这些“重要的对象”,然后从它们出发,把我们能找到的对象都标记为⾮垃圾对象,其余的⾃然就是垃圾对象我们将上⽂提到的“重要的对象”命名为GC Roots,这样就得到了最终的可达性分析算法的概念:创建垃圾回收时的根节点,称为GC Roots,从GC Roots出发,不能到达的对象就被标记为垃圾对象其中,可以作为GC Roots的区域有:虚拟机栈的栈帧中的局部变量表⽅法区的类属性和常量所引⽤的对象本地⽅法栈中引⽤的对象换句话说,GC Roots就是⽅法中的局部变量、类属性,以及常量垃圾回收算法终于到本⽂的重点了,我们刚刚分析了如何判断⼀个对象属于垃圾对象,接下来我们就要重点分析如何将这些垃圾对象回收掉标记-清除算法标记-清除很容易理解,该算法有两个过程,标记过程和清除过程,标记过程中通过上⽂提到的可达性分析法来标记出所有的⾮垃圾对象,然后再通过清除过程进⾏清理⽐⽅说,我们现在有下⾯的这样的⼀个Java堆,已经通过可达性分析法来标记出所有的垃圾对象(⽤橙⾊表明,蓝⾊的是普通对象):然后我们通过清除阶段进⾏清理,结果是下图:发现什么问题了吗,没错,清理完后的空间是不连续的,也就是说,整个算法最⼤的缺点就是:会出现⼤量的空间碎⽚,当需要分配⼤对象时,会触发FGC,⾮常消耗性能这⾥引出⼀个FGC的概念,为了避免主题跑偏,本⽂中暂时不进⾏深⼊,只需要知道垃圾回收分为YGC(年轻代垃圾回收)和FGC(完全垃圾回收),可以把YGC理解为扫扫地,倒倒垃圾,把FGC理解为给家⾥来个⼤扫除复制算法复制算法将Java堆划分为两块区域,每次只使⽤其中的⼀块区域,当垃圾回收发⽣时,将所有被标记的对象(GC Roots可达,为⾮垃圾对象)复制到另⼀块区域,然后进⾏清理,清理完成后交换两块区域的可⽤性这种⽅式因为每次只需要⼀整块⼀起删除即可,就不⽤⼀个个地删除了,同时还能保证另⼀块区域是连续的,也解决了空间碎⽚的问题整个流程我们再来看⼀遍1.⾸先我们有两块区域S1和S2,标记为灰⾊的区域为当前激活可⽤的区域:2.对Java堆上的对象进⾏标记,其中蓝⾊的为GC Roots可达的对象,其余的均为垃圾对象:3.接下来将所有可⽤的对象复制到另⼀块区域中:4.将原区域中所有内容删除,并将另⼀块区域激活这种⽅法的优缺点也很明显:优点:解决了空间不连续的问题缺点:空间利⽤率低(每次只使⽤⼀半)为了解决这⼀缺点,就引出了下⾯这个算法优化的复制算法⾄于为什么不另起⼀个名字,其实是因为这个算法也叫做复制算法,更确切的说,刚才介绍的只是优化算法的雏形,没有虚拟机会使⽤上⾯的那种复制算法,所以接下来要讲的,就是真正的复制算法这个算法的思路和刚才讲的⼀样,不过这个算法将内存分为3块区域:1块Eden区,和2块Survivor区,其中,Eden区要占到80%这两块Survivor区就可以理解为我们刚才提到的S1和S2两块区域,我们每次只使⽤整个Eden区和其中⼀块Survivor区,整个算法的流程可以简要概括为:1.当发⽣垃圾回收时,将Eden区+Survivor区中仍然存活的对象⼀次性复制到另⼀块Survivor区上2.清理掉Eden区和使⽤的Survivor区中的所有对象3.交换两块Survivor的激活状态光看⽂字描述⽐较抽象,我们来看图像的形式:1.我们有以下这样的⼀块Java堆,其中灰⾊的Survivor区为激活状态2.标记所有的GC Roots可达对象(蓝⾊标记)3.将标记对象全部复制到另⼀块Survivor区域中4.清理掉Eden区和激活的Survivor区中的所有对象,然后交换两块区域的激活状态以上就是整个复制算法的全过程了,有⼈可能会问了,为什么Survivor区这么⼩,就不怕放不下吗?其实平均来说,每次垃圾回收的时候基本都会回收98%左右的对象,也就是说,我们完全可以保证⼤部分情况下剩余的对象都⼩于10%,放在⼀块Survivor区中是没问题的。
JVM垃圾回收算法及分代垃圾收集器⼀、垃圾收集器的分类1、次收集器 Scavenge GC,指发⽣在新⽣代的GC,因为新⽣代的Java对象⼤多都是朝⽣⼣死,所以Scavenge GC⾮常频繁,⼀般回收速度也⽐较快。
当Eden空间不⾜以为对象分配内存时,会触发Scavenge GC。
⼀般情况下,当新对象⽣成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进⾏GC,清除⾮存活对象,并且把尚且存活的对象移动到Survivor区。
然后整理Survivor的两个区。
这种⽅式的GC是对年轻代的Eden区进⾏,不会影响到年⽼代。
因为⼤部分对象都是从Eden区开始的,同时Eden区不会分配的很⼤,所以Eden区的GC会频繁进⾏。
因⽽,⼀般在这⾥需要使⽤速度快、效率⾼的算法,使Eden去能尽快空闲出来。
当年轻代堆空间紧张时会被触发,相对于全收集⽽⾔,收集间隔较短。
2、全收集器 Full GC,指发⽣在⽼年代的GC,出现了Full GC⼀般会伴随着⾄少⼀次的Minor GC(⽼年代的对象⼤部分是Scavenge GC过程中从新⽣代进⼊⽼年代),⽐如:分配担保失败。
Full GC的速度⼀般会⽐Scavenge GC慢10倍以上。
当⽼年代内存不⾜或者显式调⽤System.gc()⽅法时,会触发Full GC。
当⽼年代或者持久代堆空间满了,会触发全收集操作。
可以使⽤System.gc()⽅法来显式的启动全收集,全收集⼀般根据堆⼤⼩的不同,需要的时间不尽相同,但⼀般会⽐较长。
3、垃圾回收器的常规匹配⼆、常见垃圾回收算法1、引⽤计数(Reference Counting) ⽐较古⽼的回收算法。
原理是此对象有⼀个引⽤,即增加⼀个计数,删除⼀个引⽤则减少⼀个计数。
垃圾回收时,只⽤收集计数为0的对象。
此算法最致命的是⽆法处理循环引⽤的问题。
2、复制(Copying) 此算法把内存空间划为两个相等的区域,每次只使⽤其中⼀个区域。
JVM调优总结范文JVM(Java Virtual Machine)是Java程序执行的运行环境,具有自动垃圾回收、即时编译和动态加载等特性。
在大型Java应用程序中,JVM的性能优化显得尤为重要,可以提高应用程序的性能和稳定性。
以下是一些JVM调优的总结。
1.内存参数调优通常情况下,JVM的默认内存配置是远远不够的。
我们可以通过调整-Xms(初始内存)和-Xmx(最大内存)来提高JVM的性能。
通常情况下,将-Xms和-Xmx设置为相同的值,避免频繁的内存调整。
2.垃圾回收调优垃圾回收是JVM的核心功能之一,它自动回收无用的对象,释放内存空间。
我们可以通过调整以下参数来优化垃圾回收性能:-XX:+UseConcMarkSweepGC:使用CMS垃圾回收器,减少垃圾回收停顿时间。
-XX:+UseParallelGC:使用并行垃圾回收器,提升垃圾收集的吞吐量。
-XX:+UseG1GC:使用G1垃圾回收器,适用于大内存和多核CPU的场景。
3.虚拟机参数调优虚拟机参数的调优可以提高JVM的性能和稳定性。
一些重要的参数包括:-XX:PermSize和-XX:MaxPermSize:仅限于JDK1.7之前的版本,用于调整永久代的大小。
在JDK1.8及以后的版本中,永久代已被元空间(Metaspace)取代。
-XX:MaxMetaspaceSize:调整元空间的大小。
-XX:NewRatio:调整新生代和老年代的比例,默认为2,表示新生代占整个堆的1/3-XX:SurvivorRatio:调整 Eden区和Survivor区的比例,默认为84.多线程调优多线程是现代应用程序的常见特征之一、在JVM中,我们可以通过调整线程池参数来优化多线程性能,如-Xss(每个线程的栈大小)、-Xhsepolicy(堆外空间分配策略)等。
5. Java代码调优优化Java代码可以提高应用程序的性能。
一些常见的Java代码调优技术包括:-减少对象的创建。
可以从不同的的角度去划分垃圾回收算法:
按照基本回收策略分
引用计数(Reference Counting):
比较古老的回收算法。
原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。
垃圾回收时,只用收集计数为0的对象。
此算法最致命的是无法处理循环引用的问题。
标记-清除(Mark-Sweep):
此算法执行分两阶段。
第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。
此算法需要暂停整个应用,同时,会产生内存碎片。
复制(Copying):
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。
垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。
次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。
当然,此算法的缺点也是很明显的,就是需要两倍内存空间。
标记-整理(Mark-Compact):
此算法结合了“标记-清除”和“复制”两个算法的优点。
也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。
此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。
按分区对待的方式分
增量收集(Incremental Collecting):实时垃圾回收算法,即:在应用进行的同时进行垃圾回收。
不知道什么原因JDK5.0中的收集器没有使用这种算法的。
分代收集(Generational Collecting):基于对对象生命周期分析后得出的垃圾回收算法。
把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。
现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。
按系统线程分
串行收集:串行收集使用单线程处理所有垃圾回收工作,因为无需多线程交互,实现容易,而且效率比较高。
但是,其局限性也比较明显,即无法使用多处理器的优势,所以此收集适合单处理器机器。
当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。
并行收集:并行收集使用多线程处理垃圾回收工作,因而速度快,效率高。
而且理论上CPU数目越多,越能体现出并行收集器的优势。
并发收集:相对于串行收集和并行收集而言,前面两个在进行垃圾回收工作时,需要暂停整个运行环境,而只有垃圾回收程序在运行,因此,系统在垃圾回收时会有明显的暂停,而且暂停时间会因为堆越大而越长。