2019独角兽企业重金招聘Python工程师标准>>>

前面说到Java虚拟机的内存分配有两种,静态(栈)分配和动态(堆)分配,所以对于内存回收策略,也有两种:静态内存回收,动态内存回收

##静态内存回收 如下面这段代码

public void staticData(int arg){long a=1;Object obj=new Object();
}

其中参数arg,a是基本数据类型,obj是一个引用。javac在编译时就已经确定了这些变量的静态存储空间,其中arg会分配4个字节,long会分配8个字节,引用obj占用4个字节,所以这个方法占用的静态内存空间是4+8+4=16字节。这些内存会在栈上分配,方法执行完后就被回收。而方法结束后,obj虽然被回收了,但obj所指向的对象是存放在堆中的,它是可以被共享的,所以不一定会随着方法执行结束而消失。只有等到这个对象不再被使用后才会被回收,这类对象的回收是动态的。

##动态内存回收

动态内存回收有垃圾回收器自动完成,其需要解决的问题有三个:

  • 如何确定一个对象是否不再被使用

  • 确定后又在什么时候回收呢

  • 怎么回收这些对象

###可达性分析算法

在主流的商用程序语言(Java,C#,Lisp)的主流实现中,都是称通过可达性分析来判断对象是否存活。这个算法的基本思路是通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象不可用。

在Java语言中,可作为GC Roots的对象包括以下几种:

  • 虚拟机栈(栈帧中局部变量表)中引用的对象

  • 方法区中类静态属性引用的对象

  • 方法区中常量引用的对象

  • 本地方法栈中JNI(即一般说的native方法)引用的对象

关于Java中的引用

###垃圾收集算法 垃圾收集算法的实现有很多种,包括标记-清除算法复制算法标记-整理算法分代收集算法等。对于现在大多数商业虚拟机来说,主要还是用的是分代收集算法。其原理就是将Java堆内存根据对象的存活时间分为多个区(新生代和老年代),每个区使用不同的收集算法(上述)。对于新生代,对象存活存活量少,可以用复制算法;而对于老年代,大多对象都能长期存活,就可以使用标记-清除标记-整理算法来回收。这样减少了每次垃圾收集时所要扫描的对象的数量,从而提高了垃圾回收效率

###垃圾收集器 垃圾收集器是垃圾收集算法的具体实现,对于HotSpot虚拟机,包含的垃圾收集器如下图所示:

上图中展示了7种作用于不同区的收集器,如果两个收集器之间存在连线,说明他们可以搭配使用。

主要分为四类:Serial Collector,Parallel Collector,CMS Collector,G1

####Serial Collector(串行回收器)

JVM在client模式下默认的GC模式,包括Serial和Serial Old,可以通过JVM配置参数-XX:+UseSerialGC来指定GC使用该收集算法。由于是单线程GC工作,所以无论Minor GC还是Full GC,都会造成应用程序的全部停止。在Full GC中,会对整个Old区进行压缩。

在创建新对象时,如果新对象的大小超过Eden区的总大小,或者超过了PretenureSizeThreshold配置参数配置的大小,就只能在Old区分配。

当Eden空间不足时,首先检查每次Minor GC时复制到Old区的平均对象大小是否大于Old的剩余空间,如果大于,则直接触发Full GC,否则,再看HandlePromotionFailure(-XX:-HandlePromotionFailure)的值,如果为true,则触发Minor GC,否则,触发Minor GC后再触发Full GC。也就是说,如果每次需要复制的对象的大小超过了Old的剩余空间大小,就说明当前Old区的剩余空间大小已经不能满足Minor GC时从Eden,Survivor区复制过来的对象的存放空间了,所以只能触发Full GC。

我们知道,在Minor GC中,除了回收Eden去的非活动对象外,还会把一些“老对象”复制到Old区,而“老对象”的定义可以通过配置参数MaxTenuringThreshold来设置,如设置 -XX:MaxTenuringThreshold=10,则如果一个对象已经经历了10次Minor GC后仍然存活在Young区,则下次Minor GC时,直接将这个对象复制到Old区。还有一种情况是,如果Minor GC时,Survivor区存放不下这些将要存放到Survivor区的对象时,也会将这些对象复制到Old区;如果Old区空间不足,则触发Full GC,Full GC会清除堆中的所有垃圾对象

####Parallel Collector(并行回收器)

使用多线程的方式,利用多CUP来提高GC的效率,主要以到达一定的吞吐量为目标;Server模式下默认GC模式。Parallel Collector根据Minor GC,Full GC的不同分为三种,分别是ParNewParallelScavengeParallelOld

#####ParNew 可以通过-XX:+UseParNewGC参数来指定,它的对象分配和回收策略与Serial Collector类似,只是回收的线程是多线程并行回收的。在Parallel Collector中还有一个UseAdaptiveSizePolicy配置,这个参数用来动态控制Eden,Survivor From ,Survivor To的TenuringThreshold大小的,以便控制那些对象经过多少次回收后可以直接放入Old区

#####ParallelScavenge 在Server模式下默认的GC模式,可以通过 -XX:UseParallelGC参数来强制指定,并行回收的线程数可以通过 -XX:ParallelGCThreads来指定,这个值有一个计算公式,如果CPU核数小于8,线程数可以和核数一样;否则,值可以设置为 3+(cpu_core5)/8。通过-Xmn来设置Young区的大小,通过SurvivorRatio参数控制Eden,Survivor From,Survivor To的大小比例,如 -XX:SurvivorRatio=8 则表示Eden:Survivor From:Survivor To=8:1:1,其默认值也是8。

当在Eden区中申请内存空间时,如果Eden区剩余空间不够,则看当前申请的空间是否大于等于Eden总空间的一半,如果大于,则直接在Old中分配,如果小于,则触发Minor GC,触发前首先检查每次Minor GC时复制到Old区的平均大小是否大于Old的剩余空间,如果大于,则再触发Full GC。此次触发GC后仍然会按照这个规则重新检查一次,如果仍然满足,Full GC会再一次触发。

当Old区不足时,会触发Full GC,如果配置了ScavengeBeforeFullGC,则在Full GC之前,会先触发Minor GC

#####ParallelOld 可以通过-XX:+UseParallelOldGC来设置,并行回收的线程数可以通过-XX:ParallelGCThreads来指定,这个值有一个计算公式,如果CPU核数小于8,线程数可以和核数一样;否则,值可以设置为 3+(cpu_core5)/8。它与ParallelGC不同之处在于,前者Full GC会清除整个堆的垃圾对象,而后者只清楚部分,并对部分空间压缩。GC时同样也会造成应用程序的全部停止。

####CMS Collector(并发收集器) 可以通过-XX:+UseConcMarkSweepGC来指定,并发的线程数默认为4,也可以通过ParallelCMSThreads来指定。

CMS GC和上面讨论的GC不太一样。它既不是Minor GC,也不是Full GC,而是基于二者之间的一种GC,它的触发规则是检查Old区或者Perm的使用率,当比例达到一定值时触发CMS GC,回收Old区内存空间。这个比例可以通过CMSInitiatingOccupancyFraction参数来指定,默认为92%。这个默认值是通过((100-MinHeapFreeRatio)+(double)(CMSTriggerRatioMinHeapFreeRatio)/100.0)/100.0计算出来的,其中MinHeapFreeRatio=40,CMSTriggerRatio=80。如果Perm区也使用CMS GC,可以通过-XX:+CMSClassUnloadingEnabled设置,默认值也是92%,也是通过公式((100-MinHeapFreeRatio)+(double)(CMSTriggerPermRatioMinHeapFreeRatio)/100.0)/100.0,其中MinHeapFreeRatio=40,CMSTriggerPermRatio=80

触发CMS GC时回收的只是Old区和Perm区的垃圾对象,和Minor GC,Full GC基本没有关系。在这种模式下,Minor GC的触发规则和回收规则与Serial Collector基本一致,不同之处在于此GC回收为多线程。而触发Full GC有两种情况,一种是Eden区分配失败,Minor GC后分配到Survivor区时Survivor不够,Old区也不够。另一种情况是当CMS GC正在进行时,向Old区申请内存失败。

在hotspot1.6中如果使用了这种GC方式,在程序中显示的调用System.gc(),且设置了ExplicitGCInvokesConcurrent参数,那么在使用NIO时可能会引发内存泄漏。

CMS GC何时执行JVM还会有一些时机选择,如当前CPU是否繁忙。因此它有一个计算规则,并根据这个规则来动态调整。这也给JVM带来了一些开销,如果要禁止这个动态调整,禁止CMS GC自动触发,则可以配置参数 -XX:+UseCMSInitiatingOccuoancyOnly来实现

####G1 参考这里

转载于:https://my.oschina.net/aptx4869/blog/480199

JVM系列五:垃圾回收器相关推荐

  1. JVM系列之垃圾回收器(下篇)——Shenandoah垃圾回收器

    1. 前言 虽然目前大部分系统使用的是 JDK8,使用的垃圾回收器也大概率为 G1 或者更古老的垃圾回收器,但是截止到目前为止,JDK 已经更新到 JDK14 了,垃圾回收器也几乎在每一次迭代中被更新 ...

  2. JVM常见的垃圾回收器

    一.常见垃圾收集器 现在常见的垃圾收集器有如下几种: 新生代收集器: Serial ParNew Parallel Scavenge 老年代收集器: Serial Old CMS Parallel O ...

  3. Jvm 系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  4. jvm系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  5. JVM笔记:垃圾回收器总结

    垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商.不同版本的JVM来实现. 由于JDK的版本处于高速迭代过程中,因此Java发展至今已经衍生了众多的GC版本.从不同角度分析垃圾收集器,可以将GC ...

  6. 【JVM · GC】垃圾回收器

    1. GC分类与性能指标 1.1 垃圾回收期器概述 垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商.不同版本的JVM来实现. 由于 JDK 版本处于高速迭代过程中,因此Java 发展至今已经衍 ...

  7. JVM中的垃圾回收器详解

    垃圾回收器的种类和使用 1.概述 1.1垃圾回收器和垃圾回收算法的关系 1.2垃圾回收器的分类 1.3 如何使用参数查看当前使用的垃圾回收器 2 串行收集(Serial) 2.1 概念 3 并行收集( ...

  8. JVM学习笔记——垃圾回收器

    经典收集器与垃圾分代之间的关系 新生代收集器:Serial.ParNew.Parallel Scavenge 老年代收集器:Serial Old.Parallel Old.CMS 整堆收集器:G1 如 ...

  9. system.gc会立即执行垃圾回收吗_JVM垃圾回收系列之 垃圾回收器

    java垃圾收集器的分类以及特点如下所示: 1.串行垃圾回收器.这是一个单线程的收集器,就是说在gc回收的时候,无论是年轻代还是老年代,都是一个线程去执行,并且在执行期间,挂起用户线程,直到收集工作完 ...

最新文章

  1. 操作系统之CPU调度
  2. scipy 笔记:solve_triangular
  3. textarea 聚焦后边框_textarea焦点的用法实现获取焦点清空失去焦点提示效果
  4. Java基础结构语句和IDEA使用和数组
  5. 关于解决并发问题,99%的程序员都会忽略的一个重要方案!
  6. Registering Protocol Handlers for Your Web Applications
  7. Python基础:文件的操作
  8. GoldVideo-基于Web Assembly的H265播放器实现
  9. pdm怎么导入oracle,PowerDesigner导入导出PDM和rtf文件
  10. python:epub文件批量转TXT
  11. Tryhackme-Windows Exploitation Basics
  12. 豪斯曼检验matlab,豪斯曼检验、空间面板模型选择等问题
  13. Arturia Sound Explorers Collection Belledonne现已上市
  14. cesium实现相机绕地旋转效果
  15. 十几减9的口算题_一年级数学口算题:十几减9(可下载)
  16. 基于深度学习的显著性检测用于遥感影像地物提取(U-2-NET)
  17. sql server 2008创建修改sa用户密码
  18. 工具类JdbcUtils
  19. 推荐十个精彩的Ubuntu鼠标主题
  20. html5实现立体照片墙效果,利用css制作3D照片墙效果

热门文章

  1. python安装mysqldb模块_Python的MySQLdb模块安装
  2. 温度转换的python程序_python学习阶段性小结
  3. python局部变量函数_python函数局部变量用法实例分析
  4. 在mathtype中怎么打出花体字母
  5. Farthest Point Sampling on 2d image
  6. 在MNIST图像上训练卷积神经网络
  7. [图像处理]指定任意灰度变换
  8. iPhone4S安装Linux系统,别失望太早 iPhone 4S其实就是iPhone 5
  9. mybatis oracle生成注释,MyBatis Generator生成Oracle数据库对应实体类时无法获取注释问题...
  10. 冲击年薪50万的AI学习指南,限时免费~