本文主要研究下JvmGcMetrics的managementExtensionsPresent

JvmGcMetrics

micrometer-core-1.0.3-sources.jar!/io/micrometer/core/instrument/binder/jvm/JvmGcMetrics.java

@NonNullApi
@NonNullFields
public class JvmGcMetrics implements MeterBinder {private static final Logger logger = LoggerFactory.getLogger(JvmGcMetrics.class);private boolean managementExtensionsPresent = isManagementExtensionsPresent();@Overridepublic void bindTo(MeterRegistry registry) {AtomicLong maxDataSize = new AtomicLong(0L);Gauge.builder("jvm.gc.max.data.size", maxDataSize, AtomicLong::get).tags(tags).description("Max size of old generation memory pool").baseUnit("bytes").register(registry);AtomicLong liveDataSize = new AtomicLong(0L);Gauge.builder("jvm.gc.live.data.size", liveDataSize, AtomicLong::get).tags(tags).description("Size of old generation memory pool after a full GC").baseUnit("bytes").register(registry);Counter promotedBytes = Counter.builder("jvm.gc.memory.promoted").tags(tags).baseUnit("bytes").description("Count of positive increases in the size of the old generation memory pool before GC to after GC").register(registry);Counter allocatedBytes = Counter.builder("jvm.gc.memory.allocated").tags(tags).baseUnit("bytes").description("Incremented for an increase in the size of the young generation memory pool after one GC to before the next").register(registry);if (this.managementExtensionsPresent) {// start watching for GC notificationsfinal AtomicLong youngGenSizeAfter = new AtomicLong(0L);for (GarbageCollectorMXBean mbean : ManagementFactory.getGarbageCollectorMXBeans()) {if (mbean instanceof NotificationEmitter) {((NotificationEmitter) mbean).addNotificationListener((notification, ref) -> {final String type = notification.getType();if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {CompositeData cd = (CompositeData) notification.getUserData();GarbageCollectionNotificationInfo notificationInfo = GarbageCollectionNotificationInfo.from(cd);if (isConcurrentPhase(notificationInfo.getGcCause())) {Timer.builder("jvm.gc.concurrent.phase.time").tags(tags).tags("action", notificationInfo.getGcAction(), "cause", notificationInfo.getGcCause()).description("Time spent in concurrent phase").register(registry).record(notificationInfo.getGcInfo().getDuration(), TimeUnit.MILLISECONDS);} else {Timer.builder("jvm.gc.pause").tags(tags).tags("action", notificationInfo.getGcAction(),"cause", notificationInfo.getGcCause()).description("Time spent in GC pause").register(registry).record(notificationInfo.getGcInfo().getDuration(), TimeUnit.MILLISECONDS);}GcInfo gcInfo = notificationInfo.getGcInfo();// Update promotion and allocation countersfinal Map<String, MemoryUsage> before = gcInfo.getMemoryUsageBeforeGc();final Map<String, MemoryUsage> after = gcInfo.getMemoryUsageAfterGc();if (oldGenPoolName != null) {final long oldBefore = before.get(oldGenPoolName).getUsed();final long oldAfter = after.get(oldGenPoolName).getUsed();final long delta = oldAfter - oldBefore;if (delta > 0L) {promotedBytes.increment(delta);}// Some GC implementations such as G1 can reduce the old gen size as part of a minor GC. To track the// live data size we record the value if we see a reduction in the old gen heap size or// after a major GC.if (oldAfter < oldBefore || GcGenerationAge.fromName(notificationInfo.getGcName()) == GcGenerationAge.OLD) {liveDataSize.set(oldAfter);final long oldMaxAfter = after.get(oldGenPoolName).getMax();maxDataSize.set(oldMaxAfter);}}if (youngGenPoolName != null) {final long youngBefore = before.get(youngGenPoolName).getUsed();final long youngAfter = after.get(youngGenPoolName).getUsed();final long delta = youngBefore - youngGenSizeAfter.get();youngGenSizeAfter.set(youngAfter);if (delta > 0L) {allocatedBytes.increment(delta);}}}}, null, null);}}}}//......
}
复制代码

可以看到这里会先判断managementExtensionsPresent,如果有才会注册jvm.gc.concurrent.phase.time以及jvm.gc.pause的timer指标

isManagementExtensionsPresent

    private static boolean isManagementExtensionsPresent() {try {Class.forName("com.sun.management.GarbageCollectionNotificationInfo", false,JvmGcMetrics.class.getClassLoader());return true;} catch (Throwable e) {// We are operating in a JVM without access to this level of detaillogger.warn("GC notifications will not be available because " +"com.sun.management.GarbageCollectionNotificationInfo is not present");return false;}}
复制代码

这里的话是采用类加载来判断的,如果能找到com.sun.management.GarbageCollectionNotificationInfo则为true

  • 加载失败
/ # jshell
Apr 12, 2018 4:39:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 10
|  For an introduction type: /help introjshell> Class.forName("com.sun.management.GarbageCollectionNotificationInfo", false, Object.class.getClassLoader())
|  java.lang.ClassNotFoundException thrown: com/sun/management/GarbageCollectionNotificationInfo
|        at Class.forName0 (Native Method)
|        at Class.forName (Class.java:374)
|        at (#1:1)jshell> /exit
|  Goodbye
复制代码
  • 加载成功
/ # jshell
Apr 12, 2018 4:05:30 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 10
|  For an introduction type: /help introjshell> Class.forName("com.sun.management.GarbageCollectionNotificationInfo", false, Object.class.getClassLoader())
$1 ==> class com.sun.management.GarbageCollectionNotificationInfo
jshell> /exit
|  Goodbye
复制代码

GarbageCollectionNotificationInfo

/Library/Java/JavaVirtualMachines/jdk-10.jdk/Contents/Home/lib/src.zip!/jdk.management/com/sun/management/GarbageCollectionNotificationInfo.java

package com.sun.management;import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataView;
import javax.management.openmbean.CompositeType;
import com.sun.management.internal.GarbageCollectionNotifInfoCompositeData;public class GarbageCollectionNotificationInfo implements  CompositeDataView {//......
}
复制代码

从类路径看,是在jdk.management的模块里头,所在包为com.sun.management。如果要是的metrics能有jvm.gc.concurrent.phase.time以及jvm.gc.pause的timer指标的话,则要求jdk里头有com.sun.management.GarbageCollectionNotificationInfo,默认是有的,如果你的jdk进行了jlink的话,则需要加上java.management以及jdk.management

java.management与jdk.management

management相关的jmod

➜  jmods ls | grep management
java.management.jmod
java.management.rmi.jmod
jdk.internal.vm.compiler.management.jmod
jdk.management.agent.jmod
jdk.management.jmod
复制代码

java.management

jmod describe java.management.jmod
java.management@10
exports java.lang.management
exports javax.management
exports javax.management.loading
exports javax.management.modelmbean
exports javax.management.monitor
exports javax.management.openmbean
exports javax.management.relation
exports javax.management.remote
exports javax.management.timer
requires java.base mandated
uses javax.management.remote.JMXConnectorProvider
uses javax.management.remote.JMXConnectorServerProvider
uses sun.management.spi.PlatformMBeanProvider
provides javax.security.auth.spi.LoginModule with com.sun.jmx.remote.security.fileloginmodule
qualified exports com.sun.jmx.remote.internal to java.management.rmi jdk.management.agent
qualified exports com.sun.jmx.remote.security to java.management.rmi jdk.management.agent
qualified exports com.sun.jmx.remote.util to java.management.rmi
qualified exports sun.management to jdk.jconsole jdk.management jdk.management.agent
qualified exports sun.management.counter to jdk.management.agent
qualified exports sun.management.counter.perf to jdk.management.agent
qualified exports sun.management.spi to jdk.internal.vm.compiler.management jdk.management
contains com.sun.jmx.defaults
contains com.sun.jmx.interceptor
contains com.sun.jmx.mbeanserver
platform macos-amd64
复制代码

可以看到java.management模块qualified exports sun.management to jdk.jconsole jdk.management jdk.management.agent,注意这里是sun.management

这个mod提供了jmx相关类库,不加的话,依赖jxm的功能会报错,比如

java.lang.IllegalStateException: Logback configuration error detected:
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:23 - no applicable action for [jmxConfigurator], current ElementPath  is [[configuration][jmxConfigurator]]at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:166)at org.springframework.boot.logging.logback.LogbackLoggingSystem.reinitialize(LogbackLoggingSystem.java:212)at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:75)at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:114)at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:264)at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:237)at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:200)at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:173)at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:74)at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:358)at org.springframework.boot.SpringApplication.run(SpringApplication.java:317)at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:137)
复制代码

jdk.management

jmod describe jdk.management.jmod
jdk.management@10
exports com.sun.management
requires java.base mandated
requires java.management transitive
provides sun.management.spi.PlatformMBeanProvider with com.sun.management.internal.platformmbeanproviderimpl
contains com.sun.management.internal
platform macos-amd64
复制代码

可以看到jdk.management导出了com.sun.management,注意这里是com.sun.management

小结

要想在metrics里头有jvm.gc.concurrent.phase.time以及jvm.gc.pause的timer指标,则需要添加jdk.management模块,GarbageCollectionNotificationInfo是在com.sun.management包里头,而不是sun.management包。JvmGcMetrics用到了jmx,因此也需要加上java.lang.management模块。

doc

  • 聊聊springboot1.x及2.x的JvmGcMetrics的区别

聊聊JvmGcMetrics的managementExtensionsPresent相关推荐

  1. 面向对象设计原则_聊聊面向对象的6大设计原则

    程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...

  2. python邮件发送哪个好_最全总结!聊聊 Python 发送邮件的几种方式

    1. 前言 邮件,作为最正式规范的沟通方式,在日常办公过程中经常被用到 我们都知道 Python内置了对 SMTP 的支持,可以发送纯文本.富文本.HTML 等格式的邮件 本文将聊聊利用 Python ...

  3. 今天聊聊分布式锁 No.86

    好了切入正题,一直在工作中会聊到很多锁的问题,今天跟大家一起闲聊一下,究竟什么是锁,为什么需要锁,以及分布式的情况下,怎么设计和实现锁. 什么是锁? 明·魏禧<大铁椎传>上是这样解释的: ...

  4. 聊聊找工作中的项目经验问题(推荐系统和智能问答)

    在求职过程中有这么一句话叫做"金九银十",也就是说,很多时候,求职的黄金时期就是在九月份和十月份,这两个月份中企业需求是最多的,求职的成功率也是最高的.但是随着AI方面的人才越来越 ...

  5. 聊聊Service Mesh:linkerd

    [编者的话]随着企业逐渐将传统的单体应用向微服务或云原生应用的转变,虽然微服务或者云原生应用能给企业带来更多的好处,但也会带来一些具有挑战的问题,如怎么管理从单体应用转向微服务所带来的服务间通讯的复杂 ...

  6. 庖丁解牛迭代器,聊聊那些藏在幕后的秘密

    0x00 前言 \\ 在我之前的一篇博客<细说C#:不是"栈类型"的值类型,从生命周期聊存储位置>的最后,我以总结和后记的方式涉及到一部分迭代器的知识.但是觉得还是不够 ...

  7. 聊聊Unsafe的一些使用技巧

    记得初学 Java 那会,刚学完语法基础,就接触到了反射这个 Java 提供的特性,尽管在现在看来,这是非常基础的知识点,但那时候无疑是兴奋的,瞬间觉得自己脱离了"Java 初学者" ...

  8. 聊聊 TCP 长连接和心跳那些事

    1 前言 可能很多 Java 程序员对 TCP 的理解只有一个三次握手,四次挥手的认识,我觉得这样的原因主要在于 TCP 协议本身稍微有点抽象(相比较于应用层的 HTTP 协议):其次,非框架开发者不 ...

  9. 聊聊算法在面试中的地位

    前段时间,有一位好友找到我,向我打听阿里社招笔试是否看重算法题的考察,我给予了肯定的答复.他表现的有些沮丧,表示自己工程底子很扎实,框架源码也研究地很透彻,唯独算法能力不行,leetcode 上的简单 ...

最新文章

  1. 4.Ling初体验 匿名类型在查询表达式中的使用
  2. 读取复杂结构的yml配置项
  3. 服务 TCP 断线错误分析
  4. oracle里的查询转换
  5. WEB Service 下实现大数据量的传输
  6. 计算机主机接线视频教程,电脑主板跳线怎么接?电脑机箱与主板跳线接法图解教程...
  7. 【英语学习】【English L06】U02 Food L1 Food on the menu
  8. 微信公众号可以开店吗?
  9. stm32如何设置蜂鸣器温度报警_有人喊冷?有人喊热?列车空调温度到底如何设置...
  10. win7多国语言包下载与安装
  11. C#中Panel控件的使用
  12. H.264中多参考帧预测技术的优化
  13. qq机器人智能聊天插件源码
  14. 独到理解@java数据类型
  15. 基于UCOSII的RS485通信(STM32F107)
  16. sap系统中的batch_SAP 批次管理(Batch management)配置介绍
  17. 行人重识别多个数据集格式统一为market1501格式
  18. 本周c++学习小结和心得
  19. Java学习笔记(九)抽象类
  20. SAP PCA利润中心会计案例教程前台操作

热门文章

  1. a commit git 参数是什么意思_git commit 命令
  2. 无连接可靠传输_尽力传输是什么 尽力传输原理介绍【图文】
  3. virtualbox中文技术文档_随笔--西门子STEP7中如何寻找技术文档
  4. 中国稀土永磁材料市场发展态势及产销需求规模预测报告2021版
  5. 判断vc2005运行库是否以已安装
  6. 粤东农批项目座谈会 农业大健康·李喜贵:功能性农业差异化加工
  7. java与js交互,相互调用传参
  8. 泛 归并排序 及 逆序对
  9. 前端开发工程师——网易云课堂
  10. System Monitor ArcGIS系统监控利器