JVM与GC垃圾回收(各种垃圾收集器,Jvm相关工具)

1.JVM内存区域:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
虚拟机栈,本地方法栈,程序计数器线程隔离,方法区,本地内存,直接内存,堆线程共享。

①.虚拟机栈:描述方法执行时的内存模型,
在这里插入图片描述

主要保存执行方法时的局部变量表、操作数栈、动态连接和方法返回地址等信息,方法执行时入栈,方法执行完出栈,出栈就相当于清空了数据,入栈出栈的时机很明确,不需要进行 GC。

②.本地方法栈:与虚拟机栈类似,本地方法栈针对于本地方法(该方法并非 Java 实现的,可能由 C 或 Python等其他语言实现的, Java 通过 JNI 来调用本地方法),不需要进行 GC。

③程序计数器:线程独有,保存当前线程执行字节码文件的行号(指令地址),不需要进行 GC。

④本地内存:包含直接内存,元空间,元空间包含方法区(方法区功能,主要存储类的信息,常量,静态变量,即时编译器编译后代码等),不需要进行 GC。

⑤堆:主要存储对象实例和数组,需要进行 GC。

2.识别是否为垃圾的方法

①.引用计数法:在对象被引用一次时在其对象头上加一次引用次数,如果引用次数为0将被回收。
问题:存在循环引用(两个对象相互引用对方,引用次数都不为0)

②.可达性算法:可达性算法的原理是以一系列叫做 GC Root 的对象为起点出发,引出它的下一个节点,直到遍历完所有节点(这样通过 GC Root 串成的一条线就叫引用链),直到所有的结点都遍历完毕,如果相关对象不在任意一个以 GC Roos为起点的引用链中,则这些对象会被判断为「垃圾」,会被 GC 回收。
GC Roots:
• 虚拟机栈(栈帧中的本地变量表)中引用的对象
• 方法区中类静态属性引用的对象

   •      方法区中常量引用的对象
   •     本地方法栈中 JNI(即一般说的 Native 方法)引用的对象

3.垃圾回收的方法

①.标记清除法:标记可回收对象,将其回收,因为可回收对象内存不连续,会造成内存碎片。
在这里插入图片描述

②。标记整理法:标记清除可回收内存,并将不可回收内存整理紧邻排列。需要频繁移动内存,效率低。
在这里插入图片描述
③.复制法:将堆内存分为两个部分A,B,A分配内存,B不分配内存,将A中不可回收资源复制到B中以连续内存存储。并将A全部清除。
会浪费一半内存。
在这里插入图片描述
④.分代收集算法(结合上述所有算法优点)
在这里插入图片描述

根据对象生存周期将堆内存分为新生代和老年代,两者所占内存比例为1:2。新生代(Eden 区, from Survivor 区(简称S0),to Survivor 区(简称 S1),三者的比例为 8: 1 : 1,这样就可以根据新老生代的特点选择最合适的垃圾回收算法,我们把新生代发生的 GC 称为 Young GC(也叫 Minor GC),老年代发生的 GC 称为 Old GC(也称为 Full GC)。

1、对象在新生代的分配与回收
98%的对象生存周期都很短,他们都被分配在新生代的Eden区。
当Eden区内存满的时候将触发Minor GC,回收Eden区近98%的对象,剩余很少的对象将移动到S0区,下一次Eden区内存满时再触发Minor GC 将Eden区和S0区存活对象移动到S1区,并清理Eden区和S0区可回收对象。若再触发下一次 Minor GC,则重复上一步,只不过此时变成了 从 Eden,S1 区将存活对象复制到 S0 区,每次垃圾回收, S0, S1 角色互换。也就是说在 Eden 区的垃圾回收我们采用的是复制算法,因为在 Eden 区分配的对象大部分在 Minor GC 后都消亡了,只剩下极少部分存活对象(这也是为啥 Eden:S0:S1 默认为 8:1:1 的原因),S0,S1 区域也比较小,所以最大限度地降低了复制算法造成的对象频繁拷贝带来的开销。
对象大小一般为所有属性类型大小之和。
是否为大对象根据配置决定

2,晋升老年代
①每次Minor GC后存活的对象年龄+1,当年龄达到设定阈值时将会晋升老年代。②当对象较大时,因为复制会比较慢,且占用空间,所有直接分配在老年代③还有一种情况也会让对象晋升到老年代,即在 S0(或S1) 区相同年龄的对象大小之和大于 S0(或S1)空间一半以上时,则年龄大于等于该年龄的对象也会晋升到老年代。

3、空间分配担保
在发生 MinorGC 之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,如果大于,那么Minor GC 可以确保是安全的,如果不大于,那么虚拟机会查看 HandlePromotionFailure 设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,如果大于则进行 Minor GC,否则可能进行一次 Full GC。

4、Stop The World
老年区满了会触发Full GC ,Full GC会清除堆里面全部可回收(不可用)对象(包含新生代和老年代)会造成STW,造成很大的开销。在发生STW时除了垃圾回收线程,其余全部线程将会被挂起,此时的server将会拒绝服务。

(Minor GC 也会造成 STW,但只会触发轻微的 STW,因为 Eden 区的对象大部分都被回收了,只有极少数存活对象会通过复制算法转移到 S0 或 S1 区,所以相对还好)

把新生代设置成 Eden, S0,S1区或者给对象设置年龄阈值或者默认把新生代与老年代的空间大小设置成 1:2 都是为了尽可能地避免对象过早地进入老年代,尽可能晚地触发 Full GC。

5,Safe Point
由于 Full GC(或Minor GC) 会影响性能,所以我们要在一个合适的时间点发起 GC,这个时间点被称为 Safe Point。

Safe Point触发的特点位置
循环的末尾
方法返回前
调用方法的 call 之后
抛出异常的位置

因为老年代对象多,占用空间大,复制算法开销很大,所以老年代采用标记整理法。

4.垃圾收集器(垃圾回收方法的实现)

在新生代工作的垃圾回收器:Serial, ParNew, ParallelScavenge
在老年代工作的垃圾回收器:CMS,Serial Old, Parallel Old
同时在新老生代工作的垃圾回收器:G1

在生产环境中我们要根据不同的场景来选择垃圾收集器组合,
一 :如果是运行在桌面环境处于 Client 模式的,则用 Serial + Serial Old (最古老的垃圾收集器,新生代和老年代在gc时都会stw,使用一个gc线程进行垃圾收集,新生代使用复制法,老年代使用标记整理法)收集器绰绰有余,
二:Parallel + Paralell Old (Serial + Serial Old的并行版本)关注高吞吐量,有自适应调节策略(根据当前运行情况自适应设置停顿时间和最大吞吐量)
三 :如果需要响应时间快,用户体验好的,则用 ParNew + CMS(ParNew 是新生代 Serial 的并行版本,即stw时开启多个gc线程进行垃圾回收,CMS以最短停顿时间为目的,在老年代使用,主要有四步:1. 初始标记(短暂stw,标记gc roots直达的对象)2. 并发标记(开启多个线程与用户线程并行执行,根据gc roots标记全部对象)3. 重新标记(短暂stw,标记因并发标记时用户线程导致的标记变化)4.并发清除(和用户线程并发使用标记清除法清除标记的对象) ) 的搭配模式,标记清除会产生内存碎片,随着时间增加必然会占满老年代内存,最后会触发担保机制(使用Serial Old触发一次full gc)
四:G1 在物理内存上不在区分新生代与老年代,而是将堆内存分为一个个的Region区域,逻辑上任然有分代的概念(任然是eden区耗尽触发Minnor gc 将幸存对象移至surviver区,surviver区不够eden区晋升为old区)。垃圾收集和CMS大概相同,只是整体使用标记整理法,局部复制法,避免了内存碎片。
可以设置停顿时间:

在这里插入图片描述

查看linux系统下gc情况

1.tomcat启动:进入tomcat bin目录下vim catalina.sh

配置jvm相关参数:
JAVA_OPTS="-server -Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m -XX:MaxPermSize=256m -XX:SurvivorRatio=4
-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log
-Djava.awt.headless=true
-XX:+PrintGCTimeStamps -XX:+PrintGCDetails
-Dsun.rmi.dgc.server.gcInterval=600000 -Dsun.rmi.dgc.client.gcInterval=600000
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15"

-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log 为gc.log路径,将其copy到windows系统,

运行gchisto(java -jar path/Gchisto.jar),将gc.log导入gchisto查看gc情况。

使用

2.springboot项目:①ps -ef | grep 进程name 得到进程id ②jstat -gc 进程id 5000 (每5s查看一次gc情况)
参考:https://www.cnblogs.com/qmfsun/p/5601734.html,https://blog.csdn.net/yishuifengxiao/article/details/82120582

3.jvm调优:JVM调优核心为调整年轻代、年老大的内存空间大小及使用GC发生器的类型等。
https://blog.csdn.net/Javazhoumou/article/details/99298624

4.使用java visual vm jdk自带工具查看jvm信息
http://www.51testing.com/html/38/n-3724238.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值