JVM 垃圾回收

JVM常见概念性问题

1、什么对象会被认为是垃圾对象?

一般一个对象不再被引用,就代表该对象可以被回收,标记垃圾对象的方式引用计数算法、可达性分析算法。

引用计数算法:这种算法是通过一个对象的引用计数器来判断该对象是否被引用了。每当对象被引用,引用计数器就会加 1;每当引用失效,计数器就会减 1。当对象的引用计数器的值为 0 时,就说明该对象不再被引用,可以被回收了。这里强调一点,虽然引用计数算法的实现简单,判断效率也很高,但它存在着对象之间相互循环引用的问题

可达性分析算法:GC Roots 是该算法的基础,GC Roots 是所有对象的根对象,在 JVM 加载时,会创建一些普通对象引用正常对象。这些对象作为正常对象的起始点,在垃圾回收时,会从这些 GC Roots 开始向下搜索,当一个对象到 GC Roots 没有任何引用链相连时,就证明此对象是不可用的。目前 HotSpot 虚拟机采用的就是这种算法。

可作为GC Root对象:

        a、Java虚拟机栈中的引用的对象

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

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

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

2、什么时候会触发对象回收?

        垃圾回收线程在 JVM 中是自动执行的,Java 程序无法强制执行。我们唯一能做的就是通过调用 System.gc 方法来"建议"执行垃圾收集器,但是否可执行,什么时候执行?仍然不可预期

3、垃圾回收发生在什么地方?

        在JVM 的内存区域中,程序计数器、虚拟机栈、本地方法栈都是线程私有的,随着线程的创建而创建,销毁而销毁;每个栈帧中分配多少内存基本是在类结构确定下来的时候就已知的,因此这三个区域的内存分配和回收都具有确定性。垃圾回收的重点区域是堆和方法区中的内存

4、怎么进行垃圾回收的?

        Java 提供了一个系统级的线程来跟踪每一块分配出去的内存空间,当 JVM 处于空闲循环时,垃圾收集器线程会自动检查每一块分配出去的内存空间,然后自动回收每一块空闲的内存块。

5、垃圾回收算法

a、复制算法

        IBM公司曾经对朝生夕死的对象进行量化的研究,发现新生代中 98%的对象都熬不过第一轮的垃圾回收收集,因此新生代的内存没必要按照1:1来划。而是把新生代划分为一块较大的Eden空间和两块较小的Survivor空间,且内存比例为 8:1:1

思想:先标记存活对象,再复制存活对象到其他空间,然后进行空间清理

1、调用 new 指令时,会在 Eden 区中分配一块存储对象的内存地址(同步操作,TLAB(Thread Local Allocation Buffer)对应虚拟机参数 -XX:+UseTLAB,默认开启)
2、当eden区占满时,会触发Minor GC,进行垃圾回收,Survivor 区中的 to 指向的 Survivior 区永远是空的

GC过程:

  • eden、from区通过可达性分析算法,标记存活对象并将存活对象复制到to区域
  • 如果一个对象被复制的次数为15(对应虚拟机参数 -XX:+MaxTenuringThreshold)那么该对象将被晋升 (promote)至老年代,另外如果单个Survivor 区已经被占用了50%时那么较高复制次数的对象也会被晋升至老年代
  • 复制完成后,对eden、from区进行垃圾回收,并进行from、to区域交换,保证下次gc时,to一直为空

缺点:

  • Copying算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么Copying算法的效率将会大大降低
  • 内存使用率会降低,空间浪费

6、基于垃圾回收算法的垃圾回收器

        GC 吞吐量 = GC耗时 / (应用程序耗时 +GC 耗时),GC 的吞吐量一般不能低于 95%

        停顿时间:指垃圾收集器正在运行时,应用程序的暂停时间

        垃圾回收频率:指多久发生一次指垃圾回收,通常垃圾回收的频率越低越好,增大堆内存空间可以有效降低垃圾回收发生的频率,但同时也意味着堆积的回收对象越多,最终也会增加回收时的停顿时间

        垃圾收集器的种类很多,可以分成响应速度快、吞吐量高两种类型。通常情况下 CMS 和 G1 回收器的响应速度快,Parallel Scavenge 回收器的吞吐量高。

 在 JDK1.8 环境下,默认使用的是 Parallel Scavenge(年轻代)+Serial Old(老年代)垃圾收集器(标记清除算法)

垃圾回收器官网地址:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/index.html

垃圾回收器对比

G1 将整块内存区域分配成若干同等大小 reg,新生代和老年代均由不同数量的reg组成

垃圾回收算法:标记整理,可规避cms内存碎片化问题,大大降低了fullGC的频率,虽然常态性能略输于cms但却没有cms特殊情况下的极端性能问题,总体更稳定。G1中各代的内存区域里reg间不一定是连续的,所以对于cpu缓存加载机制并不是特别友好,而且大对象占据超过一个reg时还会带来内存浪费的问题。

使用场景:可配分内存空间比较大(8g+),保证每个reg分配的尽量大,以减少内存浪费

优势:G1主要采用的是将堆内存分为多个相同大小的region,利用 Region Set进行对象引用收集,维护了一个优先列表,当进行垃圾回收时,根据停断时间,选择最优的region进行垃圾回收,

        1、并行与并发:G1能够更充分利用多CPU、多核环境运行

        2、分代收集:G1虽然也用了分代概念,但相比其他收集器需要配合不同收集协同工作,但G1收集器能够独立管理整个堆

        3、空间管理:与CMS的标记一清理算法不同,G1从整体上基于标记一整理算法,将整个Java堆划分为多个大小相等的独立区域(Region),这种算法能够在运行过程中不产生内存碎片

        4、可预测的停顿:降低停顿时间是G1和CMS共同目标,但是G1追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒。

7、什么情况会发生stw ?

        只要发生GC就会触发 stop the world,区别只是时间的长短。而stw时间主要受垃圾回收器影响 比如:Serial、PartNew、Parallel Scavenge 收集器无论是串行还是并行,都会挂起用户线程,而CMS和G1在并发标记时,是不会挂起用户线程,但其他时候一样会挂起用户线程,stop the world的时间相对来说小很多了。

        full gc将会对年轻代、老年代以及元空间、堆外内存进行垃圾回收。

        触发Full GC的原因:

                a、当年轻代晋升到老年代的对象大小比目前老年代剩余的空间大小还要大时,此时会触发Full GC;

                b、当老年代的空间使用率超过某阈值时,此时会触发Full GC;

                c、当元空间不足时(JDK1.7永久代不足),也会触发Full GC;

                d、当调用System.gc()也会安排一次Full GC;

8、查看和分析GC

a、JVM配置GC的常用的参数

-XX:+PrintGC                         输出 GC 日志
-XX:+PrintGCDetails              输出 GC 的详细日志
-XX:+PrintGCTimeStamps     输出 GC 的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps     输出 GC 的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC             在进行 GC 的前后打印出堆的信息
-Xloggc:../logs/gc.log             日志文件的输出路径

查看命令:

jinfo -flags 进程ID

JVM 实战问题

1、如果微服务的需求是处理大量的文本,如每次请求会传入一个10KB左右的文本,在高并发的情况下,该如何来优化程序尽量避免由于垃圾回收导致的进程卡死问题?

a、可以将eden区设置大些,让垃圾回收尽可能的发生在eden区(尽量避免GC)

b、批量调用(减少系统的调用次数)、增大接收套接字的buffer缓冲区,降低用户态和内核态的内存拷贝频次

c、考虑池化;如协程复用申请的内存区域,go的buffer pool通过buffer reset在处理完业务时候自动释放复用申请的内存

d、程序中尽可能的减少对象创建(如果性能不是优化到极致,不建议接口之间入参对象一传到底,架设防腐层、业务解耦对系统扩展很重要)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值