[转帖]直接内存监控不准确,netty玩了什么花?
https://segmentfault.com/a/1190000044509636
是挺久没有“宠爱”我们netty小婊贝了,最近又开始搞事了。
于是,趁机探究了下MXBean关于direct memory的监控原理。
一、问题
通过arthas dashboard中的direct,visualvm的MBeans以及jmx获取的grafana监控都无法看到直接内存有大量占用,但实际上应用已经在OOM的边缘。
······
那难道拿这个“小可爱”没法了吗?只能祭出终极绝招:添加jvm启动参数-XX:NativeMemoryTracking=detail。
简单说一下NMT,NMT(本地内存跟踪)是JDK自带的功能,方法简单,可以用它跟踪JVM内存使用情况。使用方法:
1. 启用NMT(启动加参数):-XX:NativeMemoryTracking=detail
2. 简单的执行命令:jcmd $pid VM.native_memory detail
即可打印:Java Heap、Class、Thread、Code、GC、Compiler、Internal、Symbol、Native Memory Tracking、Arena Chunk 内存可用、已占用情况。
其中:Java Heap即-Xmx的设置和占用情况;
Thread包含线程数量和线程本身占用内存(-Xss乘以线程数量)的情况;
Internal包含直接内存(Direct Memory,受-XX:MaxDirectMemorySize限制)
二、MXBean监控直接内存案例
一般我们可以使用MXBean通过下面的方式获取直接内存的使用情况:
private static final Logger LOG = LoggerFactory.getLogger(MemoryStatics.class);
// direct memory
public static BufferPoolMXBean directMBean;
// mapped memory
public static BufferPoolMXBean mappedMXBean; static {
List<BufferPoolMXBean> bufferPoolMXBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); for (BufferPoolMXBean mbean : bufferPoolMXBeans) {
if (mbean.getName().equals("direct")) {
directMBean= mbean;
} else {
mappedMXBean = mbean;
}
}
}
public void monitor() { while (true) {
assert directMBean != null;
LOG.info("buffer pool name: " + directMBean);
LOG.info("memory used: " + directMBean.getMemoryUsed());
LOG.info("max memory : " + directMBean.getTotalCapacity());
LOG.info("contain buffers : " + directMBean.getCount());
LOG.info("---------------------------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
arthas的mbean命令和visualvm的MBeans中的BufferPool原理上也是类似的。
三、BufferPoolMXBean底层原理
上面的案例中,通过getMemoryUsed、getTotalCapacity、getCount方法获取实际direct memory的使用情况。而真正的实现类是JDK的sun.management.ManagementFactoryHelper(JDK8) 【可以直接打印mbean对象,可以看见类似对象信息:sun.management.ManagementFactoryHelper$1@de2b39c】:
而上面这段代码可以看到有getName、getCount、getTotalCapacity等方法,其真正实现都是在java.nio.Bits中,实现如下:
Bits类中有几个静态成员,简单说明:
// 最大直接内存,默认和-Xmx配置的大小一样
private static volatile long maxMemory = VM.maxDirectMemory();
// 已使用的直接内存大小
private static final AtomicLong reservedMemory = new AtomicLong();
// 总的直接内存大小,小于等于maxMemory
private static final AtomicLong totalCapacity = new AtomicLong();
在使用java.nio.ByteBuffer.allocateDirect或者DirectByteBuffer主构造函数时,每次分配直接内存都会调用Bits类进行实际分配并更新reservedMemory和totalCapacity等值。
关于DirectByteBuffer可以看之前的一篇《从HotSpot源码理解DirectByteBuffer》
DirectByteBuffer主构造函数如下:
netty的直接内存分配
简单说明下netty的直接内存分配。netty直接内存分配最终是通过PlatformDependent实现的,这个类有个原子类的静态成员DIRECT_MEMORY_COUNTER独立进行内存使用记录,不依赖Bits.
// PlatformDependent直接内存记录器
private static final AtomicLong DIRECT_MEMORY_COUNTER;
每次要申请一块新的direct memory的时候, 它就调用incrementMemoryCounter方法去增加 DIRECT_MEMORY_COUNTER 的值:
最终是通过反射实例化DirectByteBuffer,用的是下面的构造函数:
PlatformDependent0反射实例化代码:
因此netty所分配的直接内存大小,常规的监控手段无法监测,包括arthas、visualvm中的MBean、以及其他所有通过jmx获取直接内存数据的手段。
如果要监控,只能自定义实现,从PlatformDependent入手,网上已有不少资料。
[转帖]直接内存监控不准确,netty玩了什么花?的更多相关文章
- 一文了解 Redis 内存监控和内存消耗
Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多.所以,监控 Redis 的内存消耗并了解 Redis 内存模型对高效并长期稳定使用 Redis ...
- 用python 10min手写一个简易的实时内存监控系统
简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...
- Docker容器内存监控
linux内存监控 要明白docker容器内存是如何计算的,首先要明白linux中内存的相关概念. 使用free命令可以查看当前内存使用情况. [root@localhost ~]$ free tot ...
- iOS微信内存监控
WeTest 导读 目前iOS主流的内存监控工具是Instruments的Allocations,但只能用于开发阶段.本文介绍如何实现离线化的内存监控工具,用于App上线后发现内存问题. FOOM(F ...
- [转]用python 10min手写一个简易的实时内存监控系统
简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...
- docker内存监控与压测
一直运行的docker容器显示内存已经耗尽,并且容器内存耗尽也没出现重启情况,通过后台查看发现进程没有占用多少内存.内存的监控使用的是cadvisor,计算方式也是使用cadvisor的页面计算方式, ...
- 从Container内存监控限制到CPU使用率限制方案
转自:http://blog.csdn.net/Androidlushangderen/article/details/50282593 前言 最近在运维我们部门的hadoop集群时,发现了很多Job ...
- redis内存监控与回收
Redis有自己的内存分配器,当key-value对象被移除时,Redis不会马上向操作系统释放其占用内存.redis之所以这样的设计有两个原因. OS可能会将释放内存交换到虚拟内存,但OS的虚拟内存 ...
- 10min 手写一个内存监控系统
本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理,及思想.更容易去理解Nagios.Zabbix.Ganglia监控原理,文章最后还有视频教程链接哦,从零敲出来的全过程 思路分为下面几块: ...
- 【性能测试】:JVM内存监控策略的方法,以及监控结果说明
JVM内存监控主要在稳定性压测期间,监控应用服务器内存泄露等问题: [JVM远程监控设置] 1.打开WAS控制台:https://ip:port/ibm/console/login.do 2.进入路径 ...
随机推荐
- ja-netfilte-ja-netfilte
title: ja-netfilte date: 2022-10-16 16:13:50.339 updated: 2023-02-07 22:58:50.672 url: https://www.y ...
- 某RBAC管理系统审计
某RBAC管理系统审计 前言 这个管理系统的审计我去年就开始了但烂尾了,那时候太热闹了log4j2,cs的cve反制等等.这个都给忘了,所以本篇可能有些图有点老,现在就是旧图没一个个换遇到的新的就加上 ...
- 红日靶场4-wp
红日靶场4 环境搭建 注:130网段为模拟外网网段,111网段为内网网段 机器 用户 密码 网卡 kali root / 192.168.130.19 web(ubuntu) ubuntu ubunt ...
- STM32CubeMX教程1 工程建立
1.准备材料 开发板(STM32F407G-DISC1) ST-LINK/V2驱动 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) 2 ...
- Ubuntu 下建立 eclipse 启动图标,解决ADT没有菜单栏问题(转载)
原文地址 怎么在这应用程序里边建立图标$sudo gedit /usr/share/applications/Eclipse.desktop输入以下代码 [Desktop Entry]Name=Ecl ...
- Spring事务状态处理
Spring事务提交后执行:深入理解和实践 在Java开发中,Spring框架的事务管理是一个核心概念,尤其是在企业级应用中.理解和正确使用Spring事务对于保证应用的数据一致性和稳定性至关重要.本 ...
- GOF23--23种设计模式(三)
一.桥接模式 Java中的桥接模式(Bridge Pattern)是一种结构性设计模式,它将抽象部分和实现部分分离,使它们可以独立变化,同时通过桥接对象将它们连接起来. 这种模式将抽象与其实现解耦,使 ...
- flutter MaterialApp介绍
MaterialApp 是 Flutter 中常用的一个 widget,它是构建基于 Material Design 风格应用的根组件,主要负责各种全局状态的管理以及定义应用程序的主题样式等. voi ...
- 心理健康数据集:mental_health_chatbot_dataset
一.数据集描述 1.数据集摘要 该数据集包含与心理健康相关的问题和答案的对话对,以单一文本形式呈现.数据集是从流行的医疗博客(如WebMD.Mayo Clinic和HealthLine).在线常见 ...
- 视频编码耗时长、编码帧发送失败…DVPP视频编码问题典型案例分析
摘要:本期就分享几个关于DVPP视频编码问题的典型案例,并给出原因分析及解决方法 本文分享自华为云社区<DVPP媒体数据处理视频编码问题案例>,作者:昇腾CANN. DVPP(Digita ...