当前位置: 首页 > news >正文

JVM第十四讲:调试排错 - Java 内存分析之堆内存和MetaSpace内存

调试排错 - Java 内存分析之堆内存和MetaSpace内存

本文是JVM第十四讲,以两个简单的例子(堆内存溢出MetaSpace (元数据) 内存溢出)解释Java 内存溢出的分析过程。

文章目录

  • 调试排错 - Java 内存分析之堆内存和MetaSpace内存
    • 1、常见的内存溢出问题(内存和MetaSpace内存)
      • 1.1、Java 堆内存溢出
        • 1、`OutOfMemoryError: Java heap space`
        • 2、`OutOfMemoryError: GC overhead limit exceeded`
      • 1.2、MetaSpace (元数据) 内存溢出
    • 2、分析案例
      • 2.1、堆内存dump
      • 2.2、使用MAT分析内存

1、常见的内存溢出问题(内存和MetaSpace内存)

常见的内存溢出问题(内存和MetaSpace内存)。

1.1、Java 堆内存溢出

Java 堆内存(Heap Memory)主要有两种形式的错误:

  1. OutOfMemoryError: Java heap space
  2. OutOfMemoryError: GC overhead limit exceeded
1、OutOfMemoryError: Java heap space

在 Java 堆中只要不断的创建对象,并且 GC-Roots 到对象之间存在引用链,这样 JVM 就不会回收对象。

只要将-Xms(最小堆),-Xmx(最大堆) 设置为一样禁止自动扩展堆内存。

当使用一个 while(true) 循环来不断创建对象就会发生 OutOfMemory,还可以使用 -XX:+HeapDumpOutofMemoryErorr 当发生 OOM 时会自动 dump 堆栈到文件中。

伪代码:

public static void main(String[] args) {List<String> list = new ArrayList<>(10) ;while (true){list.add("1") ;}
}

当出现 OOM 时可以通过工具来分析 GC-Roots 引用链 ,查看对象和 GC-Roots 是如何进行关联的,是否存在对象的生命周期过长,或者是这些对象确实该存在的,那就要考虑将堆内存调大了

Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:3210)at java.util.Arrays.copyOf(Arrays.java:3181)at java.util.ArrayList.grow(ArrayList.java:261)at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)at java.util.ArrayList.add(ArrayList.java:458)at com.crossoverjie.oom.HeapOOM.main(HeapOOM.java:18)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)Process finished with exit code 1

java.lang.OutOfMemoryError: Java heap space表示堆内存溢出。

2、OutOfMemoryError: GC overhead limit exceeded

GC overhead limt exceed 检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出 OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。“

PS:-Xmx最大内存配置2GB

public void testOom1() {List<Map<String, Object>> mapList = new ArrayList<>();for (int i = 0; i < 1000000; i++) {Map<String, Object> map = new HashMap<>();for (int j = 0; j < i; j++) {map.put(String.valueOf(j), j);}mapList.add(map);}
}

上述的代码执行会:old区占用过多导致频繁Full GC,最终导致GC overhead limit exceed。

java.lang.OutOfMemoryError: GC overhead limit exceededat java.util.HashMap.newNode(HashMap.java:1747) ~[na:1.8.0_181]at java.util.HashMap.putVal(HashMap.java:642) ~[na:1.8.0_181]at java.util.HashMap.put(HashMap.java:612) ~[na:1.8.0_181]at tech.pdai.test.oom.controller.TestOomController.testOom1(TestOomController.java:33) ~[classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.9.jar:5.3.9]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.9.jar:5.3.9]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.9.jar:5.3.9]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.9.jar:5.3.9]at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.50.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.9.jar:5.3.9]at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.50.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.50.jar:9.0.50]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.9.jar:5.3.9]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.9.jar:5.3.9]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]

还可以使用 -XX:+HeapDumpOutofMemoryErorr 当发生 OOM 时会自动 dump 堆栈到文件中。

JVM还有这样一个参数:-XX:-UseGCOverheadLimit 设置为false可以禁用这个检查。其实这个参数解决不了内存问题,只是把错误的信息延后,替换成 java.lang.OutOfMemoryError: Java heap space。

1.2、MetaSpace (元数据) 内存溢出

JDK8 中将永久代移除,使用 MetaSpace 来保存类加载之后的类信息,字符串常量池也被移动到 Java 堆。

PermSizeMaxPermSize 已经不能使用了,在 JDK8 中配置这两个参数将会发出警告。

JDK 8 中将类信息移到了本地堆内存(Native Heap)中,将原有的永久代移动到了本地堆中成为 MetaSpace ,如果不指定该区域的大小,JVM 将会动态的调整。

可以使用 -XX:MaxMetaspaceSize=10M 来限制最大元数据。这样当不停的创建类时将会占满该区域并出现 OOM

public static void main(String[] args) {while (true){// 动态代理Enhancer  enhancer = new Enhancer() ;enhancer.setSuperclass(HeapOOM.class);enhancer.setUseCache(false) ;enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {return methodProxy.invoke(o,objects) ;}});enhancer.create() ;}
}

使用 cglib 不停的创建新类,最终会抛出:

Caused by: java.lang.reflect.InvocationTargetExceptionat sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)... 11 more
Caused by: java.lang.OutOfMemoryError: Metaspaceat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:763)... 16 more

注意: 这里的 OOM 伴随的是 java.lang.OutOfMemoryError: Metaspace 也就是元数据溢出。

2、分析案例

在实际工作中,如何去定位内存泄漏问题呢?

2.1、堆内存dump

  • 通过OOM获取

即在 OutOfMemoryError 后获取一份HPROF二进制Heap Dump文件,在jvm中添加参数:

-XX:+HeapDumpOnOutOfMemoryError
  • 主动获取

在虚拟机添加参数如下,然后在Ctrl+Break组合键即可获取一份Heap Dump

-XX:+HeapDumpOnCtrlBreak
  • 使用HPROF agent

使用Agent可以在程序执行结束时或受到 SIGOUT信号时生成Dump文件

配置在虚拟机的参数如下:

-agentlib:hprof=heap=dump,format=b
  • jmap获取 (常用)

jmap可以在cmd里执行,命令如下:

jmap -dump:format=b file=<文件名XX.hprof> <pid>
  • 使用JConsole

Acquire Heap Dump

  • 使用JProfile

Acquire Heap Dump

2.2、使用MAT分析内存

MAT 等工具可以看:Java 问题排查之JVM可视化工具 - MAT

相关文章:

JVM第十四讲:调试排错 - Java 内存分析之堆内存和MetaSpace内存

调试排错 - Java 内存分析之堆内存和MetaSpace内存 本文是JVM第十四讲&#xff0c;以两个简单的例子(堆内存溢出和MetaSpace (元数据) 内存溢出&#xff09;解释Java 内存溢出的分析过程。 文章目录 调试排错 - Java 内存分析之堆内存和MetaSpace内存1、常见的内存溢出问题(内存…...

【1day】泛微e-office OA SQL注入漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现...

线上问题:所有用户页面无法打开

线上问题&#xff1a;所有用户页面无法打开 1 线上问题2 问题处理3 复盘3.1 第二天观察 1 线上问题 上午进入工作时间&#xff0c;Cat告警出现大量linda接口超时Exception。 随后&#xff0c;产品和运营反馈无法打开页面&#xff0c;前线用户大量反馈无法打开页面。 2 问题处…...

RabbitMQ和spring boot整合及其他内容

在现代分布式应用程序的设计中&#xff0c;消息队列系统是不可或缺的一部分&#xff0c;它为我们提供了解耦组件、实现异步通信和确保高性能的手段。RabbitMQ&#xff0c;作为一款强大的消息代理&#xff0c;能够协助我们实现这些目标。在本篇CSDN博客中&#xff0c;我们将探讨…...

iperf3交叉编译

简介 iperf3是一个用于执行网络吞吐量测量的命令行工具。它支持时序、缓冲区、协议&#xff08;TCP&#xff0c;UDP&#xff0c;SCTP与IPv4和IPv6&#xff09;有关的各种参数。对于每次测试&#xff0c;它都会详细的带宽报告&#xff0c;延迟抖动和数据包丢失。 如果是ubuntu系…...

TARJAN复习 求强连通分量、割点、桥

TARJAN复习 求强连通分量、割点、桥 文章目录 TARJAN复习 求强连通分量、割点、桥强连通分量缩点桥割点 感觉之前写的不好&#xff0c; 再水一篇博客 强连通分量 “有向图强连通分量&#xff1a;在有向图G中&#xff0c;如果两个顶点vi,vj间&#xff08;vi>vj&#xff09;有…...

python实现批量数据库数据插入

import pandas as pd import pymysql # 连接 MySQL 数据库 conn pymysql.connect( hostlocalhost, useryour_username, passwordyour_password, databaseyour_database_name, charsetutf8mb4, ) # 读取已有数据 existing_data pd.read_csv("86w全…...

python安装,并搞定环境配置和虚拟环境

鄙人使用Python来进行项目的开发&#xff0c;一般都是通过Anaconda来完成的。Anaconda不但封装了Python&#xff0c;还包含了创建虚拟环境的工具。 anaconda安装 安装anaconda&#xff0c;可以搜索清华镜像源&#xff0c;然后搜索anaconda&#xff0c;点击进入&#xff0c;然…...

Flink 的集群资源管理

集群资源管理 一、ResourceManager 概述 1、ResourceManager 作为统一的集群资源管理器&#xff0c;用于管理整个集群的计算资源&#xff0c;包括 CPU资源、内存资源等。 2、ResourceManager 负责向集群资源管理器申请容器资源启动TaskManager实例&#xff0c;并对TaskManag…...

STM32学习笔记

前言 今天开始学习STM32&#xff0c;公司封闭git网络&#xff0c;所以选择CSDN来同步学习进度&#xff0c;方便公司和家里都能更新学习笔记。 参考学习资料 江科大STM32教学视频&#xff1a; 江科大自动协STM32视频_哔哩哔哩_bilibili...

Java应用性能问题诊断技巧

作者&#xff1a;张彦东 参考&#xff1a;https://developer.aliyun.com/ebook/450?spma2c6h.20345107.ebook-index.28.6eb21f54J7SUYc 文章目录 &#xff08;一&#xff09;内存1.内存2.内存-JMX3.内存-Jmap4.内存-结合代码确认问题 &#xff08;二&#xff09;CPU1.CPU-JMX或…...

监控系列(六)prometheus监控DMHS操作步骤

一、监控的操作逻辑 给操作系统安装expect命令expect脚本执行dmhs_console脚本执行 cpt / exec 命令用脚本进行过滤字符串过滤dm_export读取脚本与当前日期作比较&#xff0c;然后返回差值 二、安装步骤 1. linux中Expect工具的安装及使用方法 https://blog.csdn.net/wangta…...

SLAM从入门到精通(dwa速度规划算法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 要说搜路算法&#xff0c;这个大家都比较好理解。毕竟从一个地点走到另外一个地点&#xff0c;这个都是直觉上可以感受到的事情。但是这条道路上机…...

嵌入式实时操作系统的设计与开发(aCoral线程学习)

真正的RTOS&#xff0c;基本上没有做到进程&#xff0c;只是停留在多线程&#xff0c;因为多进程要解决很多问题&#xff0c;且需要硬件支持&#xff0c;这样就使得系统复杂了&#xff0c;从而就可能影响系统实时性。 线程之间是共享地址的&#xff0c;也就是说当前线程的地址…...

JAVA基础(JAVA SE)学习笔记(二)变量与运算符

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 正文 第一阶段&#xff1a;Java基本语法 1. Java 语言概述 JAVA基础&#xff08;JAVA SE&#xff09;学习…...

chatgpt 接口 和 jupyter版本安装

一 接口代码 有时间继续测试 import openai # 填入你的api_key openai.api_key ""models openai.Model.list()# 定义API参数 params {role: "user", "content": }# 定义循环 while True:# 获取用户输入user_input input("请输入您的消…...

ubuntu20.04 nerf开山之作

源码 GitHub - yenchenlin/nerf-pytorch: A PyTorch implementation of NeRF (Neural Radiance Fields) that reproduces the results. 代码的相关解读 NeRF代码解读-相机参数与坐标系变换 - 知乎 原文题目&#xff1a;NeRF: Representing Scenes as Neural Radiance Field…...

Java 中实现单例模式

单例模式 单例模式&#xff0c;就是一个类在任何情况下绝对只有一个实例&#xff0c;并且提供一个全局访问点来获取该实例。 要实现单例&#xff0c;至少需要满足两个点&#xff1a; 私有化构造方法&#xff0c;防止被外部实例化造成多实例问题 提供一个静态方位作为全局访问点…...

标签页的使用

目录 1、引用TabSheet.h和TabSheet.cpp文件&#xff1a; 2、主窗口添加标签页&#xff1a; &#xff08;1&#xff09;、标签页的创建和属性更改 &#xff08;2&#xff09;、添加俩个标签页的类 &#xff08;3&#xff09;、主窗口添加成员变量 &#xff08;4&#xff09…...

新一代开源语音库CoQui TTS冲到了GitHub 20.5k Star

Coqui TTS 项目介绍 Coqui 文本转语音&#xff08;Text-to-Speech&#xff0c;TTS&#xff09;是新一代基于深度学习的低资源零样本文本转语音模型&#xff0c;具有合成多种语言语音的能力。该模型能够利用共同学习技术&#xff0c;从各语言的训练资料集转换知识&#xff0c;来…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...