JVM 堆外内存查看方法

news2024/11/14 15:11:45

JVM 堆外内存查看方法

概述

  • 是否曾经想过为什么Java应用程序通过众所周知的*-Xms-Xmx调整标志消耗的内存比指定的数量大得多 ?由于各种原因和可能的优化,JVM可能会分配额外的本机内存。这些额外的分配最终可能使消耗的内存超出-Xmx* 限制。
  • 在本教程中,我们将枚举JVM中本机内存分配的一些常见来源,以及它们的大小调整标志,然后学习如何使用本机内存跟踪来监视它们。

本机分配

  • 通常,堆是Java应用程序中最大的内存消耗者,但是还有其他一些。**除了堆之外,JVM从本地内存中分配了相当大的块来维护其类元数据,应用程序代码,由JIT生成的代码,内部数据结构等。**在以下各节中,我们将探讨其中的一些分配。

  • 在这里插入图片描述

  • 可以看到整个memory主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol、Native Memory Tracking、Arena Chunk这几部分;其中reserved表示应用可用的内存大小,committed表示应用正在使用的内存大小

  • Java Heap部分表示heap内存目前占用了463MB;

  • Class部分表示已经加载的classes个数为8801,其metadata占用了50MB;

  • Thread部分表示目前有225个线程,占用了27MB;

  • Code部分表示JIT生成的或者缓存的instructions占用了17MB;

  • GC部分表示目前已经占用了15MB的内存空间用于帮助GC;

  • Compiler部分表示compiler生成code的时候占用了26MB;

  • Internal部分表示命令行解析、JVMTI等占用了5MB;

  • Other部分表示尚未归类的占用了2MB;

  • Symbol部分表示诸如string table及constant pool等symbol占用了10MB;

  • Native Memory Tracking部分表示该功能自身占用了5MB;

  • Arena Chunk部分表示arena chunk占用了63MB

  • 一个arena表示使用malloc分配的一个memory chunk,这些chunks可以被其他subsystems做为临时内存使用,比如pre-thread的内存分配,它的内存释放是成bulk的

元空间 Class

  • 为了维护有关已加载类的某些元数据,JVM使用了称为*Metaspace*的专用非堆区域。在Java 8之前,等效项称为PermGenPermanent Generation。Metaspace或PermGen包含有关已加载类的元数据,而不是包含在堆中的有关它们的实例的元数据。
  • 这里重要的是,由于元空间是堆外数据区域,因此堆大小调整配置不会影响元空间的大小。为了限制元空间的大小,我们使用其他调整标志:
  • -XX:MetaspaceSize-XX:MaxMetaspaceSize设置最小和最大元空间大小
  • 在Java 8之前,使用*-XX:PermSize-XX:MaxPermSize*来设置最小和最大PermGen大小

线程数 Thread

  • JVM中最消耗内存的数据区域之一是堆栈,它与每个线程同时创建。堆栈存储局部变量和部分结果,在方法调用中起着重要作用。
  • 默认的线程堆栈大小取决于平台,但是在大多数现代的64位操作系统中,大约为1 MB。此大小可通过*-Xss *调整标志进行配置。
  • 与其他数据区域相比,当对线程数没有限制时,分配给堆栈的总内存实际上是不受限制的。 还值得一提的是,JVM本身需要一些线程来执行其内部操作,例如GC或即时编译。

代码缓存 Code

  • 为了在不同平台上运行JVM字节码,需要将其转换为机器指令。在执行程序时,JIT编译器负责此编译。
  • JVM将字节码编译为汇编指令时,会将这些指令存储在称为*代码缓存***的特殊非堆数据区域中 。 可以像JVM中的其他数据区域一样管理代码缓存。-XX:InitialCodeCacheSize **和 **-XX:ReservedCodeCacheSize **调谐标志确定用于代码高速缓存中的初始和最大可能大小。

垃圾收集 GC

  • JVM附带了几种GC算法,每种算法都适合不同的用例。所有这些GC算法都有一个共同的特征:它们需要使用一些堆外数据结构来执行任务。这些内部数据结构消耗更多的本机内存。

Symbols

  • 让我们从字符串开始 , 它是应用程序和库代码中最常用的数据类型之一。由于它们无处不在,因此它们通常占据堆的很大一部分。如果大量的这些字符串包含相同的内容,那么堆的很大一部分将被浪费。
  • 为了节省一些堆空间,我们可以存储每个String的一个版本, 并让其他版本引用存储的版本。 此过程称为字符串实习。由于JVM只能内生 编译时间字符串常量,因此 我们可以对要内生的字符串手动调用intern() 方法。
  • JVM将内联的字符串存储在特殊的本机固定大小的哈希表中,该哈希表称为String Table,也称为String Pool。我们可以通过**-XX:StringTableSize** 调整标志来配置表的大小(即桶数) 。
  • 除了字符串表外,还有另一个本机数据区域,称为运行时常量池。 JVM使用此池存储必须在运行时解析的常量,例如编译时数字文字,方法和字段引用。

本机字节缓冲区 Native Byte Buffers

  • JVM通常是大量本机分配的可疑对象,但有时开发人员也可以直接分配本机内存。最常见的方法是通过JNI和NIO的直接ByteBuffers进行**malloc **调用

Additional Tuning Flags

  • 在本节中,我们针对不同的优化方案使用了少数JVM调整标志。使用以下技巧,我们几乎可以找到与特定概念相关的所有调整标志:

  • $ java -XX:+PrintFlagsFinal -version | grep <concept>
    
  • PrintFlagsFinal打印所有- *XX *在JVM选项。例如,要查找所有与Metaspace相关的标志:

  • $ java -XX:+PrintFlagsFinal -version | grep Metaspace      // truncated      uintx MaxMetaspaceSize                          = 18446744073709547520                    {product}      uintx MetaspaceSize                             = 21807104                                {pd product}      // truncated
    

本机内存跟踪(NMT)

  • 既然我们知道了JVM中本机内存分配的常见来源,那么该是时候找出如何监视它们了。**首先,我们应该使用另一个JVM调整标志启用本地内存跟踪:*-XX:NativeMemoryTracking = off | sumary | detail。 ***默认情况下,NMT处于关闭状态,但我们可以使它查看其观测结果的摘要或详细视图。

  • 假设我们要跟踪典型的Spring Boot应用程序的本机分配:

  • $ java -XX:NativeMemoryTracking=summary -Xms300m -Xmx300m -XX:+UseG1GC -jar app.jar
    
  • 在这里,我们使用G1作为GC算法,在分配300 MB堆空间的同时启用NMT。

即时快照

  • 启用NMT后,我们可以随时使用*jcmd *命令获取本机内存信息 :

  • $ jcmd <pid> VM.native_memory
    
  • 为了找到JVM应用程序的PID,我们可以使用 jps命令:

  • $ jps -l                    7858 app.jar // This is our app7899 sun.tools.jps.Jps
    
  • 现在,如果我们将 jcmd *与适当的*pid一起使用, *VM.native_memory *将使JVM打印出有关本机分配的信息:

  • $ jcmd 7858 VM.native_memory
    
  • 让我们逐节分析NMT输出。

总分配

  • NMT报告保留和提交的内存总量,如下所示:

  • Native Memory Tracking:Total: reserved=1731124KB, committed=448152KB
    
  • 保留的内存代表我们的应用程序可能使用的内存总量。相反,已提交的内存等于我们的应用程序当前正在使用的内存量。

  • 尽管分配了300 MB的堆,但我们的应用程序的总保留内存几乎为1.7 GB,远不止于此。同样,已提交的内存大约为440 MB,这又远远超过了300 MB。

  • 在合计部分之后,NMT报告每个分配源的内存分配。因此,让我们深入探讨每个来源。

  • NMT按预期报告了我们的堆分配:

  • Java Heap (reserved=307200KB, committed=307200KB)          (mmap: reserved=307200KB, committed=307200KB)
    
  • 300 MB的保留和提交内存,与我们的堆大小设置匹配。

元空间

  • NMT关于已加载类的类元数据的说明如下:

  • Class (reserved=1091407KB, committed=45815KB)      (classes #6566)      (malloc=10063KB #8519)       (mmap: reserved=1081344KB, committed=35752KB)
    
  • 保留了将近1 GB的空间,并有45 MB的空间用于加载6566类。

线程

  • 这是关于线程分配的NMT报告:

  • Thread (reserved=37018KB, committed=37018KB)       (thread #37)       (stack: reserved=36864KB, committed=36864KB)       (malloc=112KB #190)        (arena=42KB #72)
    
  • 总共为37个线程的堆栈分配了36 MB的内存–每个堆栈几乎1 MB。JVM在创建时将内存分配给线程,因此保留和提交的分配是相等的。

代码缓存

  • 让我们看看NMT对JIT生成和缓存的汇编指令的评价:

  • Code (reserved=251549KB, committed=14169KB)     (malloc=1949KB #3424)      (mmap: reserved=249600KB, committed=12220KB)
    
  • 当前,将近有13 MB的代码被缓存,并且该数量可能会增加到大约245 MB。

GC

  • 这是有关G1 GC内存使用情况的NMT报告:

  • GC (reserved=61771KB, committed=61771KB)   (malloc=17603KB #4501)    (mmap: reserved=44168KB, committed=44168KB)
    
  • 我们可以看到,几乎有60 MB的空间被保留并致力于帮助G1。

  • 让我们看看一个简单得多的GC(例如串行GC)的内存使用情况:

  • $ java -XX:NativeMemoryTracking=summary -Xms300m -Xmx300m -XX:+UseSerialGC -jar app.jar
    
  • 串行GC几乎不使用1 MB:

  • GC (reserved=1034KB, committed=1034KB)   (malloc=26KB #158)    (mmap: reserved=1008KB, committed=1008KB)
    
  • 显然,我们不应该仅仅因为内存使用率就选择了GC算法,因为串行GC的“停滞不前”性质可能会导致性能下降。

符号Symbol

  • 这是有关符号分配的NMT报告,例如字符串表和常量池:

  • Symbol (reserved=10148KB, committed=10148KB)       (malloc=7295KB #66194)        (arena=2853KB #1)
    
  • 将近10 MB分配给符号。

随着时间的NMT

  • NMT使我们能够跟踪内存分配如何随时间变化。**首先,我们应将应用程序的当前状态标记为基线:

  • $ jcmd <pid> VM.native_memory baseline
    
  • 然后,过一会儿,我们可以将当前内存使用量与该基准进行比较:

  • $ jcmd <pid> VM.native_memory summary.diff
    
  • NMT使用+和–符号将告诉我们在此期间内存使用量如何变化:

  • Total: reserved=1771487KB +3373KB, committed=491491KB +6873KB-             Java Heap (reserved=307200KB, committed=307200KB)                        (mmap: reserved=307200KB, committed=307200KB) -             Class (reserved=1084300KB +2103KB, committed=39356KB +2871KB)// Truncated
    
  • 保留和提交的总内存分别增加了3 MB和6 MB。可以很容易地发现内存分配中的其他波动。

详细的NMT

  • NMT可以提供有关整个内存空间映射的非常详细的信息。要启用此详细报告,我们应该使用*-XX:NativeMemoryTracking = detail *调整标志。

-----------------------------------------------------------------------------------

offer突击训练营简介:

1:针对不知道怎么面试,面试没有信心的小伙伴,我们会给你一个offer保障。

2:我们会监督你15-20天内把面试体系技术点掌握至少7成,这样足够你去找到满意的工作了。

3:我们是面向面试学习指导,不会带你们去写代码,会把项目真实开发的迭代过程和技术细节如何实现业务功能都详细教清楚,你能在面试中流畅表达清楚就行了,项目经验你不用担心(技术老师提供的真实项目经验肯定拿的出手),自己学和别人带着系统学,效率完全不一样。

详情请点击这里:offer突击训练营,给你一个offer的保障,求职跳槽的看过来!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1122672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第6周 .NET

好嘛&#xff01;本来以为上周SQL Server环境配置等已经够恶心了&#xff0c;没想到这周又得去搞所谓的Microsoft Visual Studio 2005了。 首先非常离谱的是&#xff0c;这个Microsoft Visual Studio 2005如果就是指Visual Studio 2005&#xff0c;那么已经是8年前的老的不行的…

【技能树笔记】网络篇——练习题解析(八)

目录 前言 一、LAN技术 1.1 堆叠与集群 1.2 MSTP的特点 二、WAN技术 2.1 PPP链路建立 2.2 PPPoE 2.3 组播 2.3.1 组播的IP 2.3.2 组播分发树 2.3.3 组播协议 三、IPv6基础 3.1 IPv6地址 3.2 IPv6协议 3.3 IPv6过渡技术 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1…

快速拿下 AI Prompt 工程师证书攻略!

Datawhale干货 贡献者&#xff1a;许文豪、司玉鑫、甘元琦 Prompt 是 AI 2.0 时代打开大模型能力的金钥匙&#xff0c;它能够大大的提高工作效率。 如果把大语言模型 (LLM&#xff0c;Large Language Model) 具象成一个的员工&#xff0c;那 Prompt 提示词则好比是你给员工下的…

留意差距:弥合网络安全基础设施的挑战

您最近一直在关注日益增加的网络威胁吗&#xff1f;如果您发现自己沉浸在 IT 或技术中&#xff0c;那么您可能会永远追求与时俱进。每天都会出现新的漏洞&#xff0c;这对保持消息灵通提出了巨大的挑战。 构建和维护能够应对复杂攻击者的网络安全基础设施所面临的挑战是真实存…

idea的debug调试

目录 断点条件设置(condition) 断点表达式(evaluate expression) 断点回退(reset frame) 断点条件设置(condition) 条件断点&#xff0c;一般是满足我们设置的某个条件时&#xff0c;debug断点才会生效。这种条件断点设置&#xff0c;我们一般用在多重循环中。 这儿我们以li…

codeforces (C++ In Love )

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、在一个集合中有多组线段&#xff0c;如果有不相交的两组线段&#xff0c;则输出YES&#xff0c;否则输出NO。 2、每次操纵可以选择增加一组线段或者删除一组线段后&#xff0c;输出YES或者NO。 3、用flag标记该线段是否…

数据结构: map与set的简单实现

目录 map与set的模拟实现 1.基本框架 2.模拟实现map与set所需要做的事 1.使用模板 , 达到泛性编程 2.比较问题 3.迭代器 RBTree中: operator operator-- 4.map [ ] 的实现 5.使用普通迭代器构造const迭代器 效果 map与set的模拟实现 1.基本框架 map set 2.模拟实…

nodejs+vue旅行社网站系统-计算机毕业设计

激发了管理人员的创造性与主动性&#xff0c;对旅行社网站系统而言非常有利。 模块包括主界面&#xff0c;首页、个人中心、用户管理、景点分类管理、旅游景点管理、景点购票管理、酒店信息管理、酒店预定管理、旅游路线管理、系统管理等进行相应的操作。 目 录 摘 要 I ABST…

力扣刷题 day52:10-22

1.数组拆分 给定长度为 2n 的整数数组 nums &#xff0c;你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) &#xff0c;使得从 1 到 n 的 min(ai, bi) 总和最大。 返回该 最大总和 。 方法一&#xff1a;排序 #方法一&#xff1a;排序 def arrayPai…

【计算机网络】UDP的报文结构和注意事项

UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是一种无连接的协议&#xff0c;它在传输层中提供了简单、不可靠的数据传输服务。与TCP&#xff08;Transmission Control Protocol,传输控制协议&#xff09;不同&#xff0c;UDP不需要建立连接&…

驱动开发3 ioctl函数的使用+3个实例(不传递第三个参数、第三个参数为整型、第三个参数为地址)

开发板&#xff1a;stm32mp157aaa&#xff08;Cortex-A7*2 Cortex-M4*1&#xff09;开发环境&#xff1a;vscode、串口工具 1 引入ioctl函数的意义 linux操作系统中有意将数据的读写和读写功能的选择分别交给不同的函数去完成。就让read/write函数只进行数据的读写即可&#x…

手把手创建属于自己的ASP.NET Croe Web API项目

第一步&#xff1a;创建项目的时候选择ASP.NET Croe Web API 点击下一步&#xff0c;然后配置&#xff1a; 下一步&#xff1a;

Openssl数据安全传输平台007:共享内存及代码的实现 ——待完善项目具体代码和逻辑

文章目录 0. 代码仓库1. 使用流程案例代码&#xff1a; 2. API解析2.1 创建或打开一块共享内存区2.2 将当前进程和共享内存关联到一起2.3 将共享内存和当前进程分离2.4 共享内存操作 -&#xff08; 删除共享内存 &#xff09; 3. 思考问题3. ftok函数4. 共享内存API封装-以本项…

rust学习——栈、堆、所有权

文章目录 栈、堆、所有权栈(Stack)与堆(Heap)栈堆性能区别所有权与堆栈 所有权原则变量作用域所有权与函数返回值与作用域 栈、堆、所有权 栈(Stack)与堆(Heap) 栈和堆是编程语言最核心的数据结构&#xff0c;但是在很多语言中&#xff0c;你并不需要深入了解栈与堆。 但对于…

互联网Java工程师面试题·Java 面试篇·第五弹

目录 79、适配器模式和装饰器模式有什么区别&#xff1f; 80、适配器模式和代理模式之前有什么不同&#xff1f; 81、什么是模板方法模式&#xff1f; 82、什么时候使用访问者模式&#xff1f; 83、什么时候使用组合模式&#xff1f; 84、继承和组合之间有什么不同&#…

【BIGRU预测】基于双向门控循环单元的多变量时间序列预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

改进YOLO系列 | YOLOv5/v7 引入 Dynamic Snake Convolution | 动态蛇形卷积

准确分割拓扑管状结构,如血管和道路,在各个领域中至关重要,可以确保下游任务的准确性和效率。然而,许多因素使任务复杂化,包括细小的局部结构和可变的全局形态。在这项工作中,我们注意到管状结构的特殊性,并利用这一知识来引导我们的DSCNet,以在三个阶段同时增强感知:…

1 Go的前世今生

概述 Go语言正式发布于2009年11月&#xff0c;由Google主导开发。它是一种针对多处理器系统应用程序的编程语言&#xff0c;被设计成一种系统级语言&#xff0c;具有非常强大和有用的特性。Go语言的程序速度可以与C、C相媲美&#xff0c;同时更加安全&#xff0c;支持并行进程。…

微信小程序设计之主体文件app-json-tabBar

一、新建一个项目 首先&#xff0c;下载微信小程序开发工具&#xff0c;具体下载方式可以参考文章《微信小程序开发者工具下载》。 然后&#xff0c;注册小程序账号&#xff0c;具体注册方法&#xff0c;可以参考文章《微信小程序个人账号申请和配置详细教程》。 在得到了测…

LeetCode讲解篇之40. 组合总和 II

文章目录 题目描述题解思路题解代码 题目描述 题解思路 按升序排序candidates&#xff0c;然后遍历candidates&#xff0c;目标数减去当前candidates的数&#xff0c;若该结果小于0&#xff0c;因为candidates的元素大于0&#xff0c;所以后续不会再出现让计算结果等于0的情况…