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

堆内存的详细结构以及java中内存溢出和排查方式

三种JVM

我们可以通过Java -version来查看我们使用的虚拟机版本。

我们大部分使用的就是HotSpot虚拟机,还有两种分别是JRockit JVMIBM J9VM

Oracle JRockit JVM是业界性能最高的 Java 虚拟机,现内置于 Oracle 融合中间件中。

与 HotSpot 类似,支持 服务器端桌面应用嵌入式系统,是 IBM 产品(如 WebSphere、AIX、z/OS)的默认 JVM2017 年 IBM 将 J9 开源并交由 Eclipse 基金会管理,更名为 Eclipse OpenJ9

我们学习的虚拟机大部分都是HotSpot虚拟机。

堆(Heap)我们的虚拟机里面只有一块堆内存,同时我们可以对其进行调整大小。

类加载器读取了类文件之后,会把类,方法,常量,变量,保存我们创建对象的真实对象。

在我们的堆内存当中可以细分为三个区域:

  • 新生区:存放新创建的对象(绝大多数对象在此区域被快速回收),高频 Minor GC 处理短期对象,复制算法高效无碎片。

  • 养老区:存放长期存活的对象(如缓存、全局变量等),低频 Major GC 处理长期对象,标记-整理算法减少碎片。

  • 永久存储区:存储 JVM 的元数据(类信息、方法、常量池等),Java 8 后被元空间取代,存储元数据,不再受堆大小限制。

特性永久代(PermGen)元空间(Metaspace)
存储位置堆内存中本地内存(非堆)
溢出错误java.lang.OutOfMemoryError: PermGenjava.lang.OutOfMemoryError: Metaspace
大小限制固定上限(需手动调整)默认无上限(受物理内存限制)
调优参数-XX:PermSize / -XX:MaxPermSize-XX:MetaspaceSize / -XX:MaxMetaspaceSize

我们通过代码来进行内存的模拟,我们通过对字符串的无限增加,可以使堆内存被加爆,就会出现内存溢出OOM

package com.JvmTest.TestjVMDemo1;
​
import java.util.Random;
​
public class HeapTest {public static void main(String[] args) {String string = "HeapTest";while(true){string+=string+ new Random().nextInt(999999999)+new Random().nextInt(999999999);}}
}

新生区

  • 类诞生和成长的地方,甚至死亡。

  • 伊甸园区,所有的对象都是在伊甸园区产生的

  • 幸存者区(0,1)

因为我们程序当中绝大部分都是临时对象,所以我们基本上很少见到OOM

永久区

永久区这个区域是常驻内存的,用来存放JDK自身携带的Class对象,interface元数据,存储的是java运行时的一些环境或类信息,这个区域不存在垃圾回收机制,当虚拟机关闭的时候才会进行内存的释放

当启动类加载过多的第三方JAR包,或在Tomcat中部署过多应用时,加之持续生成动态反射类不断被加载,最终会导致内存耗尽,从而引发OOM问题。

上图当中元空间这片区域也叫做非堆,事实上这片区域里面的方法区是线程公用的,所以它是非堆,非堆并不是说不是堆,它还是堆,只是用来区分开,jdk8以上就把元空间永久替换了永久代,所以这片区域叫过,永久代,元空间,方法区。

  • 方法区:是《Java 虚拟机规范》定义的逻辑区域,用于存类信息、常量、静态变量等,本身属于非堆范畴(区分于存储对象的堆),JDK 1.7 及之前,HotSpot 用 “永久代” 实现它;JDK 8+ 改用 “元空间” 实现,元空间是方法区的落地实现(物理存储)。

  • “非堆” 是区分于新生代、老年代组成的 “堆(Heap)” 的内存分类,包含方法区(元空间 / 永久代)、直接内存等。它属于 JVM 管理的内存,但不参与堆的垃圾回收分代流程,本质是 “JVM 内存的非堆存储区”,并非 “不是堆”,而是逻辑概念上与堆(存对象实例)区分。

元空间这一片区域我们逻辑上存在,内存不存在解释过程如下。

我们通过代码来查看虚拟机试图使用的最大内存和jvm初始化总内存

package com.JvmTest.TestjVMDemo1;
​
public class JvmDemo1 {public static void main(String[] args) {//返回虚拟机试图使用的最大内存long maxMemory = Runtime.getRuntime().maxMemory();//返回JVM的初始化总内存long totalMemory = Runtime.getRuntime().totalMemory();
​
​System.out.println("maxMemory="+maxMemory+"字节\t"+(maxMemory/(double)1024/1024)+"MB");System.out.println("totalMemory"+totalMemory+"字节\t"+(totalMemory/(double)1024/1024)+"MB");
​}
}

默认情况下默认分配的总内存是电脑内存的1/4,而初始化的内存为1/64

我们可以通过参数的调优来查看一下内存的分布,调优的参数为-Xms1024m -Xmx1024m -XX:+PrintGCDetails

  • -XX:+PrintGCDetails启用 详细垃圾回收日志,打印每次 GC 的详细信息

注意!! jdk9+的需要通过配置文件的方式才能够出现,9以下的参数无需更改

我们将新生代和老年代的内存相加然后进行内存的换算,最后结果也就是我们的虚拟机初始化总内存。

我们出现OOM的情况的时候就需要我们首先尝试扩大内存看结果是否改变,如果依然报错就说明代码内部存在着问题,就需要我们分析内存查看问题

我们对于之前的一个OOM的例子来进行解析

如上图我们就可以看出,当所有的内存都满了之后,就会出现错误OOM。

很经典的面试问题,当出现OOM怎么进行排错。

  • 内存快照分析工具,MAT,Jprofiler这两个都是java的插件。

    作用:

    • 分析Dump内存文件,快速定位内存泄漏。

    • 获得堆中的对象

    • 获得大的对象

我们需要下载Jprofiler下载地址:ej-technologies - JProfiler

下载之后需要在图中的地址配置文件位置。

下载之后需要配置一下idea的参数

-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

参数的意思是Xms8m设置JVM初始堆内存大小-Xmx8m最大堆内存文件,HeapDumpOnOutOfMemoryError当出现OOM错误的时候dump这个错误。这个时候当我们有错误的时候,就能够在idea里面看到dump文件

package TestjVMDemo1;
​
import java.util.ArrayList;
​
public class Demo2 {byte[] bytes = new byte[1024*1024];//-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryErrorpublic static void main(String[] args) {ArrayList<Demo2> list = new ArrayList<>();int count = 0;try {while (true){list.add(new Demo2());count=count+1;}} catch (Error e) {System.out.println(e);}}
}

我们把文件打开就可以在大文件的错误里面看到我们运行的出现的问题。

我们通过下面的设置就可以看到我们的程序当中具体到哪一行出现了OOM的错误。

http://www.dtcms.com/a/276689.html

相关文章:

  • Jinja2模板引擎技术在dify中的应用方法
  • Python基于Django的WEB服务统一身份认证协议的设计与实现【附源码、文档说明】
  • 3 c++提高——STL常用容器(一)
  • 【理念●体系】路径治理篇:打造可控、可迁移、可复现的 AI 开发路径结构
  • 【一起来学AI大模型】RAG系统组件:检索器(LangChain)
  • 深度学习-LeNet5-AlexNet
  • ZeroNews 版本升级预告!
  • 【PMP备考】敏捷专题 - 敏捷概述
  • CPU 与存储器连接方式的深入理解
  • Java使用Langchai4j接入AI大模型的简单使用(三)--输入文字生成图片
  • C++结构体数组应用
  • 我自建服务器部署了 Next.js 全栈项目
  • hot100 hot75 栈、队列题目思路
  • os.machine()详解
  • 开阳630HV100芯片的外设配置
  • 如何重置被入侵服务器的Root密码?并且提高服务器安全?
  • 《当技术遇见毁灭:rm -rf的哲学隐喻与现实警示》
  • 【八股消消乐】Kafka集群 full GC 解决方案
  • pytorch深度学习—RNN-循环神经网络
  • 服务端高效处理拖拽排序
  • [创业之路-502]:企业管理层 - 什么是企业经营,什么是企业管理?什么是业务?
  • [Token]Token merging for Vision Generation
  • 2025全网最详细的软件测试面试八股文
  • 面试150 翻转二叉树
  • FreeRTOS内核实现与应用之0——编码风格
  • 【离线数仓项目】——电商域DWS层开发实战
  • 【AI大模型】部署优化量化:INT8压缩模型
  • 深入理解设计模式:原型模式(Prototype Pattern)
  • 深入解析5G核心网容灾:SMF在PCF全故障下的PDU会话处理机制
  • 绘制气候预报图:利用地理空间技术解锁气候洞察