JVM实战(25)——元数据区优化

这篇具有很好参考价值的文章主要介绍了JVM实战(25)——元数据区优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析

阶段4、深入jdk其余源码解析

阶段5、深入jvm源码解析

一、案例背景

本章介绍的案例比较特殊,是由于人为设置JVM参数错误,而导致的JVM性能问题。

首先,生产环境有一个新上线的系统,频繁触发Full GC告警。通过GC日志,我们发现日志中有大量以下字样:
【Full GC(Metadata GC Threshold) xxxxx,xxxxx】

从这里就知道,频繁的Full GC是因为Metadata区域(JDK1.8+)被占满。

1.1 存在问题

Metadata区域,也就是元数据区,一般存放着类信息,为什么会被频繁占满,进而触发Full GC呢?我们通过工具分析元数据区的内存占用情况,发现元数据区域的内存使用波动曲线类似于下面这样:

JVM实战(25)——元数据区优化,jvm专题,jvm

也就是说,元数据区的内存占用不断增加,当达到一个顶点后(快占满)就会触发Full GC,Full GC会对元数据区域进行垃圾回收,所以接下来元数据区的内存占用就又变小了。

二、元数据区占满

2.1 优化前

通过上述的案例背景介绍,已经可以很明显的看出,系统的问题就是 不断有新的类被加载到元数据区,导致不断地触发Full GC :

JVM实战(25)——元数据区优化,jvm专题,jvm

那到底是什么类在不断地被加载呢?

我们可以通过在JVM启动参数中加上以下配置,然后观察GC日志:
-XX:TraceClassLoading -XX:TraceClassUnloading

这两个参数,用来追踪类加载和类卸载的情况,GC日志中会打印出JVM加载了哪些类、卸载了哪些类:
【Loaded sun.reflect.GeneratedSerializationConstructorAccessor from _JVM_Defined_Class】

可以看到,JVM在运行期间不断地加载了大量的“GeneratedSerializationConstructorAccessor”类到元数据区,这些类是在程序中使用Java的反射时加载的,比如像下面这样:

    Method method = XXX.class.getDeclaredMethod(xxx, xxx);
    method.invoke(target, params);

在执行这类反射代码时,JVM会动态生成一些类放入元数据区:

JVM实战(25)——元数据区优化,jvm专题,jvm

那 JVM又为什么会不停的创建这些类对象呢?

首先,我们要明白Class对象都是SoftRefence(软引用),软引用在正常情况下不会被回收。JVM在GC时判断是否回收软引用对象时,采用了一个公式:
$$
clock-timestamp ≤ freespace * SoftRefLRUPolicyMSPerMB
$$
这个公式的意思是说:clock-timestamp表示对象最近一次被访问距当前的时间差,freespace表示JVM中的空闲内存大小,SoftRefLRUPolicyMSPerMB表示每1MB空间可以允许SoftReference对象存活多久。

举个例子,假如JVM中的空闲内存大小为3000MB,SoftRefLRUPolicyMSPerMB设置为1000ms,那么Class对象就可以存活:3000*1000=3000秒,也就是50分钟。

SoftRefLRUPolicyMSPerMB可以通过JVM启动参数配置,在上述案例中,这个值被配置成了0,于是freespace * SoftRefLRUPolicyMSPerMB=0。这就导致程序通过反射创建出Class对象后,立马被回收了,接着JVM在反射代码的执行过程中,继续创建这种反射代理类,在JVM的机制下,这种类对象会越来越多,直到将元数据区占满。

JVM实战(25)——元数据区优化,jvm专题,jvm

这里其实大家会有个疑问,为什么软引用的class对象被回收后,就会导致JVM不断的创建更多的新class对象。其实这是JDK内部的一个缺陷,需要分析JDK源码,不再赘述。

2.2 优化后

了解了问题的所在,我们就开始针对这个案例进行优化,其实非常简单,之所以出现元数据区的频繁GC就是因为JVM参数设置不合理,只要把-XX:SoftRefLRUPolicyMSPerMB=0这个参数的值设置大一点就可以了,比如1000、2000、5000。

提高这个数值,就是让反射过程中JVM自动创建的软引用的一些class对象不要被随便回收,那元数据区中的内存占用也就基本稳定了。

三、总结

本章,我们通过示例分析了元数据区被占满导致的频繁Full GC问题,通过参数-XX:SoftRefLRUPolicyMSPerMB可以配置软引用对象的平均存活时间,从而避免了元数据区频繁被占满。文章来源地址https://www.toymoban.com/news/detail-815373.html

到了这里,关于JVM实战(25)——元数据区优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈

    JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、运行时数据区 二、Java虚拟机栈 1.栈帧的组成 2.局部变量表 3.操作数栈 4.帧数据 总结 JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具

    2024年01月20日
    浏览(42)
  • JVM实战(19)——JVM调优工具概述

    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 学习必须往深处挖,挖的越深,基础越扎实! 阶段1、深入多线程 阶段2、深入多线程设计模式 阶段3、深入juc源码解析

    2024年01月18日
    浏览(51)
  • (一)JVM实战——jvm的组成部分详解

    本节内容是关于java虚拟机JVM组成部分的介绍,通过其组成架构图了解JVM的主要组成部分。 ClassFile: 字节码文件 - javac: javac前端编译器将源代码编译成符合jvm规范的.class文件,即字节码文件 - class文件的结构组成: 魔术、Class文件版本、常量池、访问标志、类索引、父类索引

    2024年04月25日
    浏览(46)
  • 面试宝典之JVM优化

    加载、验证、准备、解析、初始化。然后是使用和卸载了 新生代内存不够用时候发生 MGC 也叫 YGC,JVM 内存不够的时候发生 FGC 标记-清除: 这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些要被回收的对象,然后统一回收。这种方法很简单,但是会有

    2024年01月20日
    浏览(48)
  • JVM03-优化垃圾回收

           JVM的内存区域中,程序计数器、虚拟机栈和本地方法栈这3个区域是线程私有的,随着线程的创建而创建,销毁而销毁;栈中的栈帧随着方法的进入和退出进行入栈和出栈操作,每个栈帧中分配多少内存基本是在类结构确定下来的时候就已知的,因此这三个区域的内存

    2024年02月12日
    浏览(37)
  • JVM的FastThrow优化机制

            前一阵子,在公司排查线上问题发现:出问题的方法报空指针异常,但是没有异常堆栈信息和Message。我一开始以为是代码中做了处理,但是经过翻阅代码发现不是。最后一番查找资料,这种现象是JVM的一种优化机制,叫做FastThrow机制。          JVM会对一些特定

    2024年02月02日
    浏览(33)
  • JVM-性能优化工具 MAT

    MAT( Memory Analyzer Tool )工具是一款功能强大的 ]ava 堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于 Eclipse 开发的,不仅可以单独使用,还可以作为插件的形式嵌入在 Eclipse 中使用。是一款免费的性能分析工具,使用起来非常方便。 https://www.eclipse.

    2024年02月11日
    浏览(40)
  • Jvm之JIT优化详细解释

    我们知道,将高级语言转换成计算机可识别的机器语言有两种方式,即编译和解释。尽管在Java中,代码需要编译成字节码才能执行,但字节码本身并不能直接在机器上执行。 因此,JVM内置了解释器(interpreter),在运行时对字节码进行解释,将其翻译成机器码,然后执行。 解释

    2024年02月10日
    浏览(41)
  • jvm对象创建和内存分配优化

    1、类加载检测 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。 new指令对应语言层面讲是,new、对

    2024年02月13日
    浏览(56)
  • JVM实战(20)——jstat实战(1)

    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 学习必须往深处挖,挖的越深,基础越扎实! 阶段1、深入多线程 阶段2、深入多线程设计模式 阶段3、深入juc源码解析

    2024年01月19日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包