JVM理解(三)

上一节说到方法区和堆是有大小的,内容太多不够的处理,也就是今天学习的内容——垃圾回收

在学习垃圾回收之前,先学习JVM内存模型。

JVM内存模型

JVM内存模型又称内存区域、运行时数据区域。就是我们上一节所说的Runtime Data Area,最主要的内存区域就是方法区堆内存。

先来分析一下new ThreadDemo()这个对象

  1. 首先,所有刚创建出来的对象一般都在Eden区。先在Young区的Eden区中分配ThreadDemo对象。
  2. 如果经过了一次Young GC,ThreadDemo对象依然没有被回收掉,此时,ThreadDemo对象进入Survivor区中S0或S1其中一块。(假如进入S0)
  3. 再次进行Young GC,ThreadDemo对象依然没有被回收掉,ThreadDemo对象进入S1。
  4. 再次进行Young GC,ThreadDemo对象依然没有被回收掉,ThreadDemo对象进入S0。
  5. 每次进行GC 对象没有被回收掉,年龄age+1。
  6. 如果ThreadDemo对象一直没有被回收掉,并且age>15,就会进去Old区

方法区回收比较少,主要是堆内存的回收

Full GC= Metaspace GC + Old GC + Young GC

Young GC后依然有空间碎片的问题,如果想要分配一个大一点的对象,发现没有连续空间,把Eden区中存活的对象复制到survivor(S0/S1)再把Eden区清空


特殊情况

  1. 对象很大,超过1/2Eden区大小,对象直接在Old区分配;Eden区空间不够ThreadDemo对象分配内存,会触发一次Young GC。
  2. S0区域不够
    1. 触发Young GC(Minor GC)
    2. 向Old区借一点空间给存活的对象使用(担保机制)
  3. Old区不够
    1. 触发Old GC(Major GC)
    2. 还是不够,抛出OOM(OutOfMemoryError)

什么时候进行垃圾回收

  • Eden区或者S区不够,触发Young GC
  • Old区不够,触发Old GC
  • Metaspace不够,触发Metaspace GC
  • System.gc() 通知建议JVM垃圾回收
  • Full GC触发时机
    • Major GC触发Minor GC

垃圾收集器优化

优化思路

  1. 回收次数尽可能的少
  2. 垃圾回收的时候,停顿时间要短(垃圾回收线程暂停业务代码线程的时间)
  3. 吞吐量要高(业务代码执行时间/(业务代码执行时间+垃圾回收时间))

垃圾收集器

  1. Serial Collector
    1. 单线程收集,适合于单核CPU场景,适用于内存小的场景。例如100MB
    2. 使用:-XX:+UseSerialGC
    3. 会暂停业务代码的线程(stop the world)
    4. 新生代的serial:复制算法;老年代的serial:标记-整理算法
  2. Parallel Collector
    1. 更加关注吞吐量,多线程进行垃圾收集,也会stw
    2. 使用:-XX:+UseParallelGC
    3. 新生代:复制算法;老年代:标记-整理算法
  3. CMS、G1、ZGC
    1. 三者都是关注停顿时间,停顿时间越来越短(并没有完全暂停用户代码的线程)

垃圾回收算法

  • 复制算法

    Eden区-->Survivor区,解决了我们前面说到的YoungGC后空间碎片问题

     新生代区域适合使用复制算法:因为新生代对象生命周期比较短,大部分对象会被回收掉。所以我们可以把少部分对象复制到保留的空间,然后清除已使用空间。

  • 标记-清除算法
    • 扫描整个内存区域,并且标记清除之后,会存在空间碎片问题。
  • 标记-整理算法
    • 扫描整个内存区域,整理比较耗时,但会解决空间碎片问题。

        

 老年代区域使用标记-整理 | 标记-清除算法,因为老年代渔区对象生命周期长,如果用复制算法比较耗时,不如先做一个标记到后面在选择删除或者整理。

了解完垃圾回收算法之后,那么什么样的对象可以成为垃圾对象呢?

什么样的对象可以称为垃圾对象

 我们通过判断ThreadDemo对象是否有用,怎么判断呢?

  1. 可达性分析(从GC Root出发)
    1. GC Root是什么样的对象或者变量才可以呢??
      1. 局部变量表中的局部变量
      2. 生态城成员变量
      3. 方法区中的常量
      4. Thread进程
      5. ClassLoader加载的一些对象或者变量
  2. 引用计数
    1. 看是否有引用指向它
      1. 但是也会有问题——循环引用


JVM参数

  1. -X

    Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

    1. -Xint 解释执行
    2. -Xcomp 编译执行
    3. -Xmixed 解释+编译
  2. -XX

    1. -XX:name = value
      1. -XX: InitialHeapSize = 100M  堆内存大小  -Xms 100M
      2. -XX: MaxHeapSize = 100M    堆内存最大的大小  -Xmx 100M
      3. -XX:ThreadStackSize = 100   Java虚拟机栈的深度  -Xss 100
    2. -XX:+    -XX:-
      1. -XX:+/-UseG1GC  开启/关闭
  3. 其他参数

    1. -version
    2. -cp
    3. -help

设置JVM参数

  1. 开发工具

    1. 修改默认参数:

      window-->preferences-->java-->Installed JREs-->Edit-->Default VM arguments
    2.  修改运行时参数

      Run As -->Run Configurations-->Arguments-->VM arguments
    3. 修改eclipse配置文件 eclipse.ini。

  2. 启动jar包时

    java -jar xxx.jar -XX:+UseG1GC
  3. 中间件

    有些中间件是以JVM来运行的,可以再bin/启动中间件 设置。
  4. 实时修改某些jvm参数的值

    1. 也不是所有的值都是可以实时修改的噢 利用-XX:+PrintFlagsFinal 打印jvm参数,{manageable}才是可以实时修改的。
    2. jinfo -flag -XX:name = value pid 修改指定进程(pid)的指定参数的值。

常见的JDK命令

  1. 查看进程 jps -l
  2. jinfo 查看虚拟机配置参数信息,也可以用来调整参数
    1. jinfo pid
    2. jinfo -flag name pid
    3. jinfo -flag name=value pid
    4. jinfo -flag +/- name pid
  3. jstack 查看指定进程中线程的情况
  4. jstat
    1. jstat -class pid 查看某个java进程中类装载的信息
    2. jstat -gc pid 查看JVM中堆的垃圾收集情况统计(以下是各参数及含义)
      1. S0U(S0的大小)  S1C(S1的大小)  EC(Eden区大小)
      2. S0U(S0使用大小)  S1U(S1使用大小)  EU(Eden区使用大小)
      3. OC(Old区的大小) OU(Old区使用大小) MC(方法区的大小)MU(方法区使用大小)
      4. CCSC(压缩类空间大小) CCSU(压缩类空间使用大小)
      5. YGC(Young GC回收次数)YGCT(Young GC回收消耗时间)
      6. FGC(Old GC回收次数) FGCT(Old GC回收消耗时间)
      7. GCT(垃圾回收消耗总时间)
  5. jmap
    1. jamp -heap pid 查看堆内存详情的快照信息
    2. jmap -dump :[live] format=b, file=    生成Java虚拟机的堆快转储快照dump文件,live参数可选,如果指定,则只转储堆中的活动对象,如果没有指定,转储堆中所有对象jmap -dump:live,format=b,file=d:\hprof pid
    3. 通过java jvisual VM 打开,自动分析快照文件

常见的JVM分析工具

JDK自带的

  • jvisualvm
    • 在jdk\bin\jvisualvm.exe
  • jconsole

第三方工具

  • arthas.jar

堆dump文件分析工具

  • MAT
  • heaphero
  • perfma

GC日志查看相关的

生成GC日志命令

  • -XX:+PrintGC                 输出GC日志
  • -XX:+PrintGCDetails      输出GC的详细日志
  • -XX:+PrintGCTimeStamps        输出GC的时间戳
  • -Xloggc:gc.log        日志文件的输出路径

分析日志文件的工具

  • viewergc.jar
  • gceasy.io
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值