`
1028826685
  • 浏览: 936875 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类

hotspot的垃圾回收策略,设置和调优

    博客分类:
  • J2EE
 
阅读更多

我们都知道JVM内存由几个部分组成 Java栈、程序计数器(ProgramCounter)寄存器、本地方法栈、堆、方法区、运行常量池。

JVM垃圾回收仅仅针对公共内存区域即:方法区进行。

本文主要讨论两点,一是垃圾回收策略,二是调优的方法。

一、垃圾回收机制

1.1 分代管理

方法区按照对象出现的不同时间进行分代:

u  堆中会频繁地创建对象,基于一种分代的思想,按照对象存活时间将划分为新生代旧生代两部分,我们不能一次垃圾回收新生代存活的对象就放入旧生代,而是要经过几次GC后还存活的对象,我们才放入旧生代,所以我们又把新生代再次划分为Eden区和两个Survivor区,让对象创建在Eden区,然后在两个Survivor之间反复复制,最后仍然存活的对象才复制到旧生代中。

u  方法区存放的是常量、加载的字节码文件信息等,信息相对稳定。因为不会频繁地创建对象,所以不需要分代,直接GC即可。

由此我们JVM垃圾回收要扫描的范围是:

注:图片来自网络

新生代:

1.所有新对象创建发生在Eden区,Eden区满后触发新生代上的minor GC,将Eden区和非空闲Survivor区存活对象复制到另一个空闲的Survivor区中。

2.永远保证一个Survivor是空的,新生代minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。

旧生代:

1.Eden区满后触发minor GC将存活对象复制到Survivor区,Survivor区满后触发minor GC将存活对象复制到旧生代。

2.经过新生代的两个Survivor之间多次复制,仍然存活下来的对象就是年龄相对比较老的,就可以放入到旧生代了,随着时间推移,如果旧生代也满了,将触发Full GC,针对整个堆(有新生代、旧生代和持久代)进行垃圾回收。

持久代:

持久代如果满,将触发Full GC

1.2 垃圾回收

要执行gc关键在于两点,一是检测垃圾对象,二是释放垃圾对象所占用的空间。

1.2.1 检测垃圾对象

检测出垃圾对象一般有两种算法

1、 引用计数法

2、 可达性分析

引用计数法因为无法检测对象之间相互循环引用的问题,基本没有被采用。现在主流的语言的垃圾收集中检测垃圾对象主要还是“可达性分析”方法,下面也主要介绍JVM可达性分析方法检测垃圾对象。

“可达性分析”算法描述?

通过一系列的名为“GC Root”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连时,则该对象不可达,该对象是不可使用的,垃圾收集器将回收其所占的内存。所以JVM判断对象需要存活的原则是:能够被一个根对象到达的对象。

什么是能够到达呢?

就是对象A中引用了对象B,那么就称A到B可达

GCRoot对象集合?

a.Java虚拟机栈(栈帧中的本地变量表)中的引用的对象。

b.方法区中的类静态属性引用的对象。

c.方法区中的常量引用的对象。

d.本地方法栈中JNI本地方法的引用对象。

1.2.2 释放空间

1、垃圾回收算法

前面已经介绍了如何检测出垃圾对象,在检测出垃圾对象之后,需要按照特定的垃圾回收算法进行内存回收,常见的垃圾回收算法有:

u  复制(Copying)

u  标记-清除(Mark-Sweep)

u  标记-整理(Mark-Compact)

u  分代(Generational Collection),借助前面三种算法实现

这里就不一一详述,感兴趣可以自行百度。

2、垃圾收集器实现

上面算法都是理论性的东西,Java虚拟机规范没有规定垃圾收集器具体如何实现,因此不同厂商、不同版本虚拟机提供的垃圾收集器可能有所差异。下面列举HotSpot(Sun JDK和Open JDK自带)虚拟机提供的六种垃圾收集器实现:

收集器名称

应用目标

采用算法

引入版本

运行方式

Serial

新生代

复制算法

Jdk1.3.1前

串行,单线程

ParNew

新生代

复制算法

 

并行,多线程

Parallel Scavenge

新生代

复制算法

Jdk1.4

并行,多线程

Serial Old

旧生代

标记-整理

 

串行,单线程

Parallel Old

旧生代

标记-整理

Jdk1.6

并行,多线程

CMS

旧生代

标记-清除

Jdk1.5

并发,多线程

并行(Parallel):多条垃圾收集线程并行工作,而用户线程仍处于等待状态。

并发(Concurrent):垃圾收集线程与用户线程一段时间内同时工作(不是并行,而是交替执行)。

总结:

1、两个串行收集器、三个并行收集器、一个并发收集器。

2、ParNew收集器是Serial的多线程版本。

3、Serial Old收集器是Serial收集器的旧生代版本。

4、Parallel Scavenge收集器以吞吐量为目标,适合在后台运算而不需要太多交互的任务。

5、Parallel Old收集器是Parallel Scavenge的旧生代版本。

6、Parallel Scavenge收集器和Parallel Old收集器是名副其实的“吞吐量优先”组合。

7、除CMS外,其他收集器工作时都需要暂停其他所有线程,CMS是第一款真正意义上的并发(Concurrent)收集器,第一次实现了让垃圾收 集器线程与 用户线程同时工作,是一款以最短停顿时间为目标的收集器,适合交互性较多的场景,这也是与Parallel Scavenge/Parallel Old吞吐量优先组合的区别。

8、新生代因为回收留下的对象少,所以采用标记-复制法。

9、旧生代因为回收留下的对象多,所以采用标记-清除/标记-整理算法。

3、选择所需垃圾收集器

虚拟机提供了参数,以便用户根据自己的需求设置所需的垃圾收集器:

JVM运行参数

新生代

旧生代

-XX:+UseSerialGC(Client模式默认值)

Serial

Serial Old

-XX:+UseParNewGC

ParNew

Serial Old

-XX:+UseConcMarkSweepGC

ParNew

CMS(Serial Old备用)

-XX:+UseParallelGC(Server模式默认值)

Parallel Scavenge

Serial Old

-XX:+UseParallelOldGC

Parallel Scavenge

Parallel Old

二、性能调优

2.1 性能调优的目的

减少minor gc的频率、以及full gc的次数。

2.2 性能调优的手段

1.使用JDK提供的内存查看工具,如JConsoleJava VisualVM

2.控制堆内存各个部分所占的比例

3.采用合适的垃圾收集器

手段1:内存查看工具和GC日志分析

n  -verbose.gc:显示GC的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。

n  -xx:+printGCdetails:详细了解GC中的变化。

n  -XX:+PrintGCTimeStamps:了解这些垃圾收集发生的时间,自JVM启动以后以秒计量。

n  -xx:+PrintHeapAtGC:了解堆的更详细的信息。

手段2:针对新生代和旧生代的比例

如果新生代太小,会导致频繁GC,而且大对象对直接进入旧生代引发full gc

如果新生代太大,会诱发旧生代full gc,而且新生代的gc耗时会延长

建议新生代占整个堆1/3合适,相关JVM参数如下:

n  -Xms:初始堆大小

n  -Xmx:最大堆大小

n  - Xmn:新生代大小

n  -XX:PermSize=n:持久代最大值

n  -XX:MaxPermSize=n:持久代最大值

n  -XX:NewRatio=n:设置新生代和旧生代的比值。如:为3,表示新生代与旧生代比值为1:3,新生代占整个新生代旧生代和的1/4。

手段3:针对Eden和Survivor的比例

如果Eden太小,会导致频繁GC

如果Eden太大,会导致大对象直接进入旧生代,降低对象在新生代存活时间。

n  -XX:SurvivorRatio=n:新生代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

n  -XX:PretenureSizeThreshold:直接进入旧生代中的对象大小,设置此值后,大于这个参数的对象将直接在旧生代中进行内存分配。

n  -XX:MaxTenuringThreshold:对象转移到旧生代中的年龄,每个对象经历过一次新生代GC(Minor GC)后,年龄就加1,到超过设置的值后,对象转移到旧生代。

手段4:采用正确的垃圾收集器

通过JVM参数设置所使用的垃圾收集器参考前面的介绍,这里关注其他一些设置。

并行收集器设置

n  -XX:ParallelGCThreads=n:设置并行收集器收集时并行收集线程数。

n  -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间,仅对ParallelScavenge生效。

n  -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比,仅对Parallel Scavenge生效。

并发收集器设置

n  -XX:CMSInitiatingOccupancyFraction:默认设置下,CMS收集器在旧生代使用了68%的空间后就会被激活。此参数就是 设置旧生代空间被使用多少后触发垃圾收集。注意要是CMS运行期间预留的内存无法满足程序需要,就会出现concurrent mode failure,这时候就会启用Serial Old收集器作为备用进行旧生代的垃圾收集。

n  -XX:+UseCMSCompactAtFullCollection:空间碎片过多是标记-清除算法的弊端,此参数设置在FULL GC后再进行一个碎片整理过程

n  -XX:CMSFullGCsBeforeCompaction:设置在若干次垃圾收集之后再启动一次内存碎片整理

三、实际项目配置

 

1、修改 tomcat\bin\Catalina.bat 文件
windows环境下:

 

在166行左右
rem Execute Java with the applicable properties ”以下每行
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%

在 %DEBUG_OPTS% 后面添加-Xms256m -Xmx512m

linux环境下:

打开在Tomcat的安装目录的bin文件的catalina.sh文件,进入编辑状态.
在注释后面加上如下脚本:
JAVA_OPTS='-Xms512m -Xmx1024m'
JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=64M -XX:MaxPermSize=256m"

其中 JAVA_OPTS='-Xms512m -Xmx1024m' 是设置Tomcat使用的内存的大小.

-XX:PermSize=64M -XX:MaxPermSize=256m 指定类空间(用于加载类)的内存大小 

 

保存后,重新以命令行的方式运行 tomcat ,即可,然后通过最后面介绍的如何观察tomcat现有内存情况的方法进行查看是否已经变更成功。

分享到:
评论

相关推荐

    JVM的垃圾回收机制详解和调优

    Java虚拟机(JVM)的垃圾回收(Garbage Collection,简称GC)机制是其自动内存管理的关键组成部分。Java语言并没有强制要求JVM必须包含GC,但现代JVM实现如HotSpot都内置了GC,以自动回收不再使用的对象所占用的内存...

    Java垃圾回收机制详解和调优

    Java垃圾回收机制是Java虚拟机(JVM)中至关重要的组成部分,它的主要任务是自动管理内存,回收不再使用的对象以避免内存泄漏...在实际应用中,应根据系统负载、内存使用情况以及性能指标持续监控和调整垃圾回收策略。

    Java的垃圾回收机制详解和调优大全

    垃圾回收的调优涉及到多个方面,包括选择合适的GC策略、调整堆大小、控制新生代和老年代的比例、设置GC日志以便分析等。调优的目标是在保持应用响应时间和稳定性的同时,最大化系统资源利用率。这需要开发者深入理解...

    【译】Java 14 Hotspot 虚拟机垃圾回收调优指南(csdn)————程序.pdf

    Java 14 Hotspot 虚拟机的垃圾回收调优是提升应用程序性能的关键环节。本指南主要涵盖了垃圾收集器的优化目标、策略以及各种实现,旨在帮助开发者更好地理解如何调整 JVM 参数以满足特定的需求。 优化目标与策略...

    Java_GC垃圾回收调优指南

    不同的垃圾回收策略适用于不同场景下的应用程序,因此了解这些策略的特点对于优化应用程序至关重要。 #### 一般调优准则 1. **熟悉默认设置**:Sun HotSpot JVM 集成了智能调优功能,称为“Ergonomics”。对于至少...

    垃圾回收器是什么1

    垃圾回收器是编程语言中的一个重要概念,特别是在Java和Oracle的Hotspot及OpenJDK等...不同的JVM实现,如Hotspot和OpenJDK,以及不同的编程语言,可能有不同的垃圾回收策略和实现,需要根据具体场景进行选择和调整。

    JAVA垃圾回收面试个人总结.doc

    垃圾回收的优化通常涉及到调整堆大小、设置新生代和老年代的比例、选择合适的垃圾收集器组合(如Serial、ParNew、Parallel Scavenge、CMS、G1等)以及使用并发模式、并行度、暂停时间目标等参数。理解这些概念和原理...

    性能工程师指南:玩转OpenJDK HotSpot垃圾收集器

    ### 性能工程师指南:玩转OpenJDK HotSpot垃圾收集器 #### 一、性能工程概述 在软件开发过程中,性能工程是一个重要的环节,它不仅涵盖了对软件性能的需求定义与测试计划制定,还包括了软件的开发、实施及后续的...

    垃圾回收算法与实现,Turling

    《垃圾回收算法与实现》是IT领域中关于内存管理和优化的重要话题,主要关注的是如何自动地识别并释放不再使用的内存,以确保程序的稳定运行。在这个主题中,Turing垃圾回收算法是一个重要的研究方向,它在Java等语言...

    12 垃圾回收相关概念.md,学习代码

    1. **对象引用计数**:这是最简单的垃圾回收策略,为每个对象维护一个引用计数。当引用计数为零时,表明该对象没有被任何其他对象引用,可以被视为垃圾进行回收。然而,这种方法无法处理循环引用问题。 2. **可达性...

    [百度网盘] HotSpot实战[完整版][带书签].pdf

    - **垃圾回收调优**:通过合理的参数配置,如设置新生代和老年代的比例、选择合适的垃圾回收器等方法来优化垃圾回收过程。 #### 3. **内存分配与管理** - **对象的创建与分配**:HotSpot支持多种对象分配策略,如...

    HotSpot实战

    这些垃圾回收器针对不同的应用场景进行了优化,用户可以根据自己的需求选择合适的垃圾回收策略。 3. **内存管理**:HotSpot 支持多代内存管理模型,将堆内存分为年轻代和老年代。年轻代主要用于存储新创建的对象,...

    垃圾回收相关总结

    总结,垃圾回收是JVM性能调优的关键环节。理解不同收集器的工作机制、默认设置以及如何根据应用场景选择合适的组合,能有效地优化系统的性能,减少因垃圾回收带来的暂停时间,从而提升整体系统效率。同时,通过细致...

    性能工程师指南:玩转OpenJDK HotSpot垃圾收集器(83页).pdf

    总的来说,这本书是性能工程师和Java开发者深入理解OpenJDK HotSpot垃圾收集器,提升应用性能的重要参考资料。通过学习、分析和调优,读者将能够更好地控制和优化Java应用的内存管理,从而提高整体系统性能。

    JVM垃圾回收及监控优化1

    为了监控和优化JVM的垃圾回收,开发者可以使用如VisualVM、JConsole、JMX等工具,通过观察内存分配、垃圾回收日志、GC停顿时间等指标来调整JVM参数,比如设置最大堆大小、年轻代和老年代的比例、GC算法选择、晋升...

    jvm性能调优

    - **调整策略**: 根据诊断结果调整垃圾回收策略和相关参数。 以上是对“jvm性能调优”的详细介绍,涵盖了JVM的基础知识、性能调优的流程及具体指标、监视和分析工具的使用、GC调优的一般原则等内容。这些知识点...

    05.垃圾回收算法1

    垃圾回收算法的选择和优化是JVM性能调优的关键部分,不同的算法有各自的优缺点,需要根据实际应用的需求和性能指标进行权衡。理解这些算法可以帮助开发者更好地理解Java内存管理,从而编写出更高效、更稳定的代码。

    JVM调优文档,自己总结汇总关于GC和性能的文章

    1. **引用计数**:早期的一种垃圾回收策略,通过维护每个对象的引用计数来确定该对象是否可以被回收。当对象的引用计数降为0时,表明没有引用指向该对象,因此可以被回收。 2. **对象引用遍历**:现代JVM通常采用...

    垃圾回收.pdf

    Java虚拟机(JVM)的垃圾回收(Garbage Collection, GC)机制是Java编程中的一个重要组成部分,它负责自动管理内存,释放不再使用的对象所占用的空间,以防止内存泄漏。本文将深入探讨JVM的GC机制,包括其概述、工作...

Global site tag (gtag.js) - Google Analytics