什么是垃圾回收
- java程序运行期间生成新对象,加载类文件都需要占用内存,不同对象从被创建,使用,存储到最后使用完毕被销毁都有一个完整的生命周期,java程序开发人员实际上只需要负责对象的创建使用,对象的销毁回收由虚拟机自动完成,对象的回收过程就是垃圾回收
怎么来做垃圾回收
- jvm运行期间使用的内存包括堆内存,创建线程使用的vm栈内存,存储方法,类,常量池使用的永久代内存,堆外内存(direct buffer),开发人员使用的是heap(堆内存),也是重点需要管理的区域
- 由于不同对想的生命周期长短不同,因此需要将整块堆内存分成不同的区域,E,S1,S2,O,Eden区存放生命周期最短的对象,S区中等长度,Old区存长生命周期对象,因此对不同的区域启用不同的回收算法。
- 对象在堆的各个区域移动过程如下:E区满了进行一轮回收,剩下的晋升到空的S区,同时将非空的S区进行回收,剩下的也全部拷贝到空S区,将达到存活时间的对象晋升进入O区。
- 为什么会有两个S区,主要是为了处理回收碎片,E区满了回收之后所有对象拷贝进入S区,S区也会被回收,因此S区面临三种选择:1)整理并压缩碎片,空出整块的内存区域,2)将E区晋升上来的对象适配到S区中的碎片空间中;3)设置两块S区,将E区和非空S区的存活对象全部合并拷贝进入空S区;最终SUN选择第三种方法,从直觉上考虑直接合并拷贝应该是效率最高的,相当于用空间换时间
垃圾回收参数
其中 -Xmx 控制了 E S1 S2 O 这四个区的总大小,-XX:PermSize 和 -XX:MaxPermSize控制了PermGen的大小,两块的大小独立设置,因此总的堆内存大小 E+S1+S2+O+P= -Xmx + -XX:MaxPermSize
-Xms 初始堆大小,MinHeapFreeRatio参数可以调整空闲堆内存小于40%时候JVM会扩充堆内存到最大设置值
-Xmx 最大堆大小,MaxHeapFreeRatio参数可以控制空闲堆内存大于70%时候JVM减少堆知道最小值
-Xmn 新生代大小(E + S1 +S2),SUN推荐的大小是整个堆大小的3/8,增大这个值会减小O区的大小
-XX:PermSize 初始永久带大小
-XX:MaxPermSize 最大永久带大小,这个值设置推荐是系统P区基本稳定下来的量的1.5倍左右
-XX:SurviorRatio E区和S区的比例,默认是8,
-Xss: 每个线程的堆栈大小,jdk1.5之前是256,之后是1M。在物理内存不变的情况下减小这个值能生成更多的线程。一个进程内的线程最大数经验值推荐在3000-5000左右,调用栈不深的应用128K差不多够用了,大一点的差不多256K,具体的值还需要严格的测试。
常见的垃圾回收器
Serial回收器:jvm历史最悠久的回收器,jdk在client模式下默认的回收器,特点是启动回收的时候需要停止一切用户线程,对于小内存的应用回收效率高,不适合对响应时间要求高,大内存的应用;
Parallel回收器:并行回收相当于Serial串行回收器的多线程版,回收的时候还是需要stop the word,只是启用多线程回收让停顿时间缩短,满足对用户响应时间比较看重的应用,比如WEB应用。
CMS回收:也叫并发回收,针对Old区的回收分成6个阶段:
初始标记(CMS initial mark)
并发标记(CMS concurrent mark)
并发预清理(CMS-concurrent-preclean)
重新标记(CMS remark)
并发清除(CMS concurrent sweep)
并发重置(CMS-concurrent-reset)
初始标记和重新标记需要S-T-W,其他步骤都是和用户线程一起运行,初始标记只是把从GC Root能直接关联到的对象快速标记出来,重新标记标记是对在初始标记之后新产生的可回收对象补充做一轮标记,并发标记是GC Root Tracing,花的时间比较长。
CMS的young区默认使用ParNew的并发回收算法,也不会S-T-W,CMS优点众多,把JVM停顿的时间竟可能缩短,也有几个缺点:1)在回收的过程中用户线程继续运行的方式可能会发生回收还没做完但是没足够空间满足应用对内存的申请或者没有足够空间放下新晋升到Old区的对象,导致 发生 conncurrent mode failed,触发一次串行的FGC,大内存的FGC停顿时间会相当长,比较要命,因此要妥善设置CMS触发阀值,和Old区的大小,提前预留足够的Old区空间;2)同用户线程一块运行会额外占用一些CPU资源;3)产生内存碎片,启用碎片压缩的情况下在FGC事后会进行碎片整理
DirectBuffer的垃圾回收
- 堆外内存的好处是减少数据拷贝次数,减少对heap堆垃圾回收的影响
- java中的类DirectBuffer只是个堆外内存的引用,存储了实际内存引用地址和大小,封装了申请和回收的操作,内存的申请和回收实际上是调用native方法类似 malloc和calloc的方法;
- DirectBuffer本身的对象大小很小,但是关联的堆外内存可能非常大,因此使用它的风险在于如果没好好回收DirectBuffer,明明堆内还很空,但是整个系统内存可能已经被耗尽了,因此JVM使用XX:MaxDirectMemorySize来约束申请的堆外内存量,防止由于使用不当,一个java进程搞挂整台机器
- DirectBuffer的回收机制也很特殊,因为DirectBuffer这个java对象和关联的堆外内存实际上是处于两块不同区域,它通过关联一个PhantomReference,当DirectBuffer对象没有外部强引用之后其本身会被塞进一个ReferenceQueue,这个特殊实现的Queue里头有个后台线程一直扫描队列,把队列中的对象所关联的堆外内存释放掉,这种机制的好处是JVM对于内存的管理统一了,堆外这种异类就用异步的方式来特殊实现来回收释放;
- 堆外内存在申请的时候如果不够就会调用System.gc触发FGC,并且为了及时回收堆外内存也会经常手工调用System.gc,因此设置这个参数也很重要-XX:+ExplicitGCInvokesConcurrent,把System.gc转换成一次CMS的执行,提高效率
垃圾回收日志格式
基本上都是这种格式:回收前区域占用的大小->回收后区域占用的大小(区域设置的大小),占用的时间,
具体的网上找下文档
垃圾回收调优处理过程--观察
- 收集当前java进程的内存相关启动参数,观察系统日志有没有OOM异常,观察GC日志,关注FGC以及concurrent mode failed 或者 promotion failed异常,以及GC监测工具观察系统内存使用状况;
- minor gc执行频率,如果执行非常频繁就要关注内存大小是否够用,程序代码写的质量是否不高;
- FGC执行频率,每次FGC回收效果如何,这个现象要考察内存大小是否够用,如果每次FGC效果差需要重点怀疑内存泄露;
- minor gc 和 survior回收效果如何,每次会有多少对象晋升到老年代,如果回收效果差,要考察系统使用内存情况(heap dump)或者Young区大小是否够用,系统是频繁产生大对象;
- CMS频率是否执行过高,对于这一条可以检查下触发CMS的所有条件,包括:1)old区占用量是否导到达触发CMS阀值;2)是否开启了JVM根据成本计算自主决定CMS是否启用;3)永久带回收是否打开,并且永久带占用是否达到回收阀值;4)是否设置了ExplicitGCInvokesConcurrent,由外部system.gc触发
垃圾回收调优处理过程--设定调优目标
根据第一步观察到的状况来设定调优目标:
- OOM--调大内存占用,MAT分析内存详情,排除内存泄露
- 降低minor gc 频率活minor gc执行时间
- 降低 fgc 频率或 fgc 执行时间
调整的效果可以通过 jstat 的 gcutil来观察调优目标是否达到
垃圾回收调优处理过程--常用策略的选择
- 降低FGC频率的办法:1)加大内存以及Old区;2)观察每次survior回收后是否大量晋升到Old,可以尝试调大S区,或者调大S区存活次数;3)调优程序,控制缓存等长生命周期对象的使用量
- 降低minor gc频率的办法:1)加大Eden区;2)用CMS并发回收器;3)增加并行收集的线程数;4)升级CPU;
- 降低minor gc回收时间或old 回收时间:1)减小区域占用内存大小;2)对于CMS,调小CMS触发阀值;3)换更多更牛逼的CPU;4)优化代码
JDK 7,JDK8中的新特性:G1垃圾回收器
G1 GC是jdk 7 对JVM GC算法做了一次重大升级,当初计划用来替换CMS。JDK 8中进一步对G1做了优化,去掉了永久带。G1的目标是减少因为GC带了的系统停顿。
G1将Java堆内存空间划分成一块块等大的区域(region),每个区域都是一段连续的内存空间,E,S,O区将不再固定,而是可以利用任意的空白区块。小区快带来的好处是后台回收线程在扫描可回收对象时候可以优先清理那些包含更多可回收对象的区块,用相同的停顿时间回收更多的垃圾,总体提高回收效率,缩短总体停顿时间。和CMS比有下面一些优势:
- G1通过将内存空间分成区域(Region)的方式避免内存碎片问题
- Eden, Survivor, Old区不再固定、在内存使用效率上来说更灵活
- 可以预设停顿时间控制GC停顿对系统响应的影响程度
- G1在回收内存后会马上同时做合并空闲内存的工作、而CMS默认是在STW(stop the world)的时候做
- G1会在Young GC中使用、而CMS只能在O区使用
相关推荐
JVM的基础知识涵盖了其内存模型、垃圾回收机制、线程模型等多个方面,下面将详细总结这些基础知识。 ### JVM内存模型 JVM内存模型主要可以分为线程共享区域和线程私有区域。 **线程共享区域** 1. 堆(Heap):...
第四节:垃圾回收算法 1.1标记清除算法 1.2复制算法 1.3 标记整理(标记压缩)算法 第五节:垃圾回收器 1.1Serial/Serial Old收集器 1.2 ParNew收集器 1.3Parallel Scavenge收集器 1.4Parallel Old收集器 1.5CMS...
### JVM工作原理及垃圾回收机制详解 #### 一、JVM概述及原理 **1.1 JVM概述** Java Virtual Machine (JVM),即Java虚拟机,是一种虚构的计算机,在实际的计算机硬件上仿真模拟出的一套完整的计算机系统,用于执行...
本文根据《深入理解Java虚拟机》书籍内容及作者理解,总结了JVM相关的知识点,分享如下: 一、JVM内存区域 JVM在运行时,将内存空间分为若干个区域,主要包括方法区、堆内存、虚拟机栈、本地方法栈、程序计数器五...
JVM 内存分配与垃圾回收详解 Java 虚拟机(JVM)是 Java 语言的 runtime 环境,它提供了一个平台独立的方式来执行 Java 字节码。...了解 JVM 内存分配与垃圾回收是 Java 开发者必须掌握的基础知识之一。
Java虚拟机(JVM)内存管理和垃圾回收是Java编程中至...总结来说,理解JVM的内存管理与垃圾回收机制对于优化Java应用性能至关重要,开发者需要根据应用特点选择合适的垃圾回收策略和参数设置,以实现高效且稳定的运行。
总结来说,理解和掌握JVM内存区域的划分以及如何避免内存溢出是Java开发中至关重要的知识点,这有助于优化程序性能和解决运行时的内存问题。通过深入学习JVM的内存管理机制,开发者可以更好地控制和调优Java应用程序...
【JVM垃圾收集器概述】 Java虚拟机(JVM)的垃圾收集器是自动管理内存的重要组成部分,负责识别不再使用的对象并释放它们所占用的内存,以防止内存泄漏。垃圾收集器的选择和配置对应用程序的性能有着显著影响,特别...
(原创)JVM超详细知识点汇总,汇总了JVM内存模型,字节码,垃圾回收器,类加载器,JVM调优等众多非常详细的知识点。能够助你能深入完全的掌握JVM。
总结来说,JVM性能调优中的垃圾回收(GC)和内存管理是确保Java应用高效运行的关键。了解Java对象引用类型、垃圾回收算法以及分代处理垃圾的概念是进行JVM性能调优的基础。这些知识点对于准备Java面试的开发者来说,...
对象首先在Eden区创建,经过垃圾回收后存活的对象会转移到Survivor区,再经过多次GC后进入老年代。 2. **栈内存**:每个线程都有一个独立的栈,用于存储方法调用时的局部变量、操作数栈、动态链接、方法出口等信息。...
总结来说,JVM垃圾收集器通过可达性分析确定可回收对象,选择合适的时机进行回收,并利用不同的算法和收集器策略优化回收过程,以实现高效的内存管理。了解这些知识有助于理解和优化Java应用程序的性能。
本文档总结了JVM调优的基础知识和一些核心概念,旨在帮助开发者更好地掌握Java程序的性能优化。 首先,文档提到了Java中的数据类型分为基本类型和引用类型。基本类型的变量存储的是原始数据值,而引用类型的变量...
以下是对JVM核心知识点的详细梳理和面试题的总结: 1. **内存结构** - **堆(Heap)**:所有线程共享的内存区域,用于存储对象实例。堆分为新生代和老年代。 - **新生代** 包括Eden区、Survivor区(from和to)。...
文章目录如何判断一个对象是垃圾垃圾回收算法分代收集算法垃圾收集器相关知识总结 如何判断一个对象是垃圾 我们都知道了当堆中的区域没有足够内存去存放对象时就会触发垃圾回收,那么如何来判断一个对象是不是垃圾呢...
Java虚拟机(JVM)内存管理是Java编程中不可或缺的一部分,尤其在面试中常常成为考察的重点。以下是对JVM内存结构、垃圾回收机制及其相关面试...在面试中,这些知识点可以帮助你深入讨论JVM内存管理和垃圾回收的细节。
总之,Java与JVM的知识涉及广泛,从类加载机制到JVM内存模型,再到性能优化和故障排查,都是Java开发者必须掌握的核心技能。通过深入学习和实践,我们可以更好地驾驭Java应用程序,提高其稳定性和性能。
本篇文章将对JVM的基础知识进行总结,并探讨如何通过调整JVM参数来提升性能。 首先,我们需要了解JVM的主要组成部分:类装载器、运行时数据区、执行引擎、本地方法接口和本地方法库。其中,类装载器负责加载、验证...
4. **主人定期捕鱼-JVM垃圾回收** 垃圾回收是JVM自动清理不再使用的对象的过程,分为Minor GC(针对年轻代)和Major / Full GC(针对老年代或整个堆)。不同的垃圾回收器(如Serial、Parallel、CMS、G1等)有不同...
在本文中,我们将深入探讨 JVM 的底层原理,涵盖内存管理、类加载机制、垃圾回收、执行引擎等多个方面,帮助你全面理解这一关键组件。 一、JVM 内存结构 JVM 内存主要分为以下几个区域: 1. **程序计数器...