03_堆+MAT工具

news2024/9/27 23:37:50

堆栈方法区的关系:

HotSpot是使用指针的方式来访问对象:

  • Java堆中会存放访问类元数据的地址

  • reference存储的就是对象的地址

三种JVM:

  • Sun公司的HotSpot
  • BEA公司的JRockit
  • IBM公司的J9 VM

一、堆体系概述

Java7之前

Heap 堆:一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存逻辑上分为三部分:

  • Young Generation Space 新生区 Young/New

  • Tenure generation space 养老区 Old/Tenure

  • Permanent Space 永久区 Perm

也称为:新生代(年轻代)、老年代、永久代(持久代)。

其中JVM堆分为新生代和老年代

1. 新生区

新生区是对象的诞生、成长、消亡的区域,一个对象在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) ,所有的对象都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。若幸存 0区也满了,再对该区进行垃圾回收,然后移动到 1 区。那如果1 区也满了呢?再次垃圾回收,满足条件后再移动到养老区。若养老区也满了,那么这个时候将产生MajorGC(FullGC),进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。

如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:

(1)Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。

(2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

2. 老年代

经历多次GC仍然存在的对象(默认是15次),老年代的对象比较稳定,不会频繁的GC

3. 永久代

永久存储区是一个常驻内存区域,用于存放JDK自身所携带的 Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。

如果出现java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致Perm区被占满。

Jdk1.6及之前: 有永久代,常量池1.6在方法区

Jdk1.7: 有永久代,但已经逐步“去永久代”,常量池1.7在堆

Jdk1.8及之后: 无永久代,常量池1.8在元空间(Metaspace)

实际而言,方法区(Method Area)和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码等等,虽然JVM规范将方法区描述为堆的一个逻辑部分,但它却还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。

对于HotSpot虚拟机,很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” ,但严格本质上说两者不同,或者说使用永久代来实现方法区而已,永久代是方法区(相当于是一个接口interface)的一个实现,jdk1.7的版本中,已经将原本放在永久代的字符串常量池移走。

常量池(Constant Pool)是方法区的一部分,Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放。

二、堆参数调优入门

均以JDK1.8+HotSpot为例

jdk1.7:

jdk1.8:

-XX:MetaspaceSize 这个参数是初始化的Metaspace大小

-XX:MaxMetaspceSize 指定元数据区域最大的大小。

1. 常用JVM参数

怎么对jvm进行调优?通过参数配置

参数备注
-Xms初始堆大小。只要启动,就占用的堆大小,默认是内存的1/64
-Xmx最大堆大小。默认是内存的1/4
-Xmn新生区堆大小
-XX:+PrintGCDetails输出详细的GC处理日志

java代码查看jvm堆的默认值大小:

Runtime.getRuntime().maxMemory()   // 堆的最大值,默认是内存的1/4
Runtime.getRuntime().totalMemory()  // 堆的当前总大小,默认是内存的1/64

2. 怎么设置JVM参数

程序运行时,可以给该程序设置jvm参数,不同的工具设置方式不同。

如果是命令行运行:

java -Xmx50m -Xms10m HeapDemo

eclipse运行的设置方式如下:  

idea运行时设置方式如下:

3. 查看堆内存详情

public class Demo2 {
    public static void main(String[] args) {

        System.out.print("最大堆大小:");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");
        System.out.print("当前堆大小:");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");
        System.out.println("==================================================");

        byte[] b = null;
        for (int i = 0; i < 10; i++) {
            b = new byte[1 * 1024 * 1024];
        }
    }
}

执行前配置参数:-Xmx50m -Xms30m -XX:+PrintGCDetails

执行:看到如下信息

新生代和老年代的堆大小之和是Runtime.getRuntime().totalMemory()

4. GC演示

public class HeapDemo {

    public static void main(String args[]) {

        System.out.println("=====================Begin=========================");
        System.out.print("最大堆大小:Xmx=");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");

        System.out.print("剩余堆大小:free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("当前堆大小:total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        System.out.println("==================First Allocated===================");
        byte[] b1 = new byte[5 * 1024 * 1024];
        System.out.println("5MB array allocated");

        System.out.print("剩余堆大小:free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("当前堆大小:total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        System.out.println("=================Second Allocated===================");
        byte[] b2 = new byte[10 * 1024 * 1024];
        System.out.println("10MB array allocated");

        System.out.print("剩余堆大小:free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("当前堆大小:total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        System.out.println("=====================OOM=========================");
        System.out.println("OOM!!!");
        System.gc();
        byte[] b3 = new byte[40 * 1024 * 1024];
    }
}

jvm参数设置成最大堆内存100M,当前堆内存10M:-Xmx100m -Xms10m -XX:+PrintGCDetails

再次运行,可以看到minor GC和full GC日志:

5. OOM演示

把上面案例中的jvm参数改成最大堆内存设置成50M,当前堆内存设置成10M,执行测试: -Xmx50m -Xms10m

====================Begin=========================
最大堆大小:Xmx=44.5M
剩余堆大小:free mem=8.186859130859375M
当前堆大小:total mem=9.5M
=================First Allocated=====================
5MB array allocated
剩余堆大小:free mem=3.1868438720703125M
当前堆大小:total mem=9.5M
================Second Allocated====================
10MB array allocated
剩余堆大小:free mem=3.68682861328125M
当前堆大小:total mem=20.0M
=====================OOM=========================
OOM!!!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.atguigu.demo.HeapDemo.main(HeapDemo.java:40)

实际开发中怎么定位这种错误信息?MAT工具

三、MAT工具

安装方式:eclipse插件市场下载

1. MAT工具的使用

运行参数:-Xmx30m -Xms10m -XX:+HeapDumpOnOutOfMemoryError

重新刷新项目:看到dump文件

打开:

2. idea分析dump文件

把上例中运行参数改成:

-Xmx50m -Xms10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\tmp 

-XX:HeapDumpPath:生成dump文件路径。

再次执行:生成C:\tmp\java_pid20328.hprof文件

生成的这个文件怎么打开?jdk自带了该类型文件的解读工具:jvisualvm.exe

双击打开:

文件-->装入-->选择要打开的文件即可

装入后:

四、常用命令行(了解)

查看java进程:jps -l

查看某个java进程所有参数:jinfo 进程号

查看某个java进程总结性垃圾回收统计:jstat -gc 进程号

S0C:幸存者0区的大小
S1C:幸存者1区的大小
S0U:幸存者0区的使用大小
S1U:幸存者1区的使用大小
EC:伊甸区的大小
EU:伊甸区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

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

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

相关文章

LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间

LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间 桌面执行节点可以控制模拟时间&#xff0c;因此开发人员可以使用模拟I/O在开发计算机上执行期间更改关键点的激励。要成功使用此功能&#xff0c;需要测量FPGA VI完成所需的时间&#xff0c;或者需要以直观地知道…

将矩阵各行顺序进行反排numpy.flipud()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将矩阵各行顺序进行反排 numpy.flipud() [太阳]选择题 请问关于以下代码的表述错误的是&#xff1f; import numpy as np a np.array([[1,2,3],[4,5,6],[7,8,9]]) print("【显示】a: \…

PLC/DCS系统中电磁干扰的来源及解决办法

自动化系统中所使用的各种类型DCS/PLC等自动化设备&#xff0c;有的是集中安装在控制室&#xff0c;有的是安装在生产现场和各种电机设备上&#xff0c;它们大多处在强电电路和强电设备所形成的恶劣电磁环境中。要提高这类控制系统可靠性&#xff0c;必须消除各种干扰才能有效保…

lwIP更新记08:TCP 回调函数中调用 tcp_abort 终于安全了

从 lwIP-1.4.0 开始&#xff0c;tcp 回调函数中调用 tcp_abort 函数终于安全了。 在此之前&#xff0c;如果从 tcp 回调函数中调用 tcp_abort&#xff0c;则会访问未分配的内存。 应用程序关闭连接&#xff0c;正常情况下是调用 tcp_close 函数&#xff0c;经过 4 次握手安全的…

XSS - 跨站脚本攻击

一、XSS简介。 XSS跨站脚本&#xff08;Cross-Site Scripting&#xff0c;XSS&#xff09;自1996年诞生以来&#xff0c;如今已经历十多年的演化。由于和另一种网页技术-层叠样式表&#xff08;Cascading Style Sheets&#xff0c;CSS&#xff09;的缩写一样&#xff0c;为了防…

Netty和Tomcat的区别、性能对比

文章目录 一、Netty和Tomcat有什么区别&#xff1f;二、为什么Netty受欢迎&#xff1f;三、Netty为什么并发高 &#xff1f; 一、Netty和Tomcat有什么区别&#xff1f; Netty和Tomcat最大的区别就在于通信协议&#xff0c;Tomcat是基于Http协议的&#xff0c;他的实质是一个基…

【AI创作】用AI创作助手写的文章--提问Git系列

目录 解释 Git 的基本概念和使用方式。Git 的使用方式如下&#xff1a; git常用命令有哪些&#xff1f;git异常报错解决方法最后 解释 Git 的基本概念和使用方式。 Git 是一种分布式版本控制系统&#xff0c;它通过记录文件的变化来管理文件版本&#xff0c;可以保存文件的历史…

在树莓派上控制GPIO常用的编程语言有哪些

在树莓派上控制GPIO(General Purpose Input Output,通用输入输出接口),比较常用和简单的编程语言有: 1. Python 这是树莓派官方推荐语言&#xff0c;控制GPIO只需要导入RPi.GPIO库,简单易学,代码如下: import RPi.GPIO as GPIOGPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.…

​路由器端口映射怎么设置?内网IP不能映射怎么办?​

使用路由器后&#xff0c;Internet用户无法访问到局域网内的主机&#xff0c;因此不能访问内网搭建的Web、FTP、Mail等服务器。路由器 端口映射功能可以实现将内网的服务器映射到Internet&#xff0c;从而实现服务器对外开放。 建议在设置路由器端口映射之前&#xff0c;确认以…

ServletOutputStream下载文件名中文乱码或不显示

废话不多说&#xff0c;直接上代码。。。 下载文件名中文乱码或不显示情况 下载文件名是一道下滑线 改造代码 pdfName是下载文件的名字&#xff0c;带后缀。 String s URLEncoder.encode(pdfName, "utf-8").replaceAll("\\", "%20"); Stri…

生成式人工智能(generative AI)对公共部门的影响

作者&#xff1a;Leanne Link, Dave Erickson 在过去的几个月里&#xff0c;我们看到了对生成式人工智能 (generative artificial intelligence - GAI) 的极大兴趣。 人们正在试用 ChatGPT 等 GAI 应用程序&#xff0c;企业正在思考它对客户体验、会计、营销等方面的影响。 鉴于…

分享这几个简单好用的手机使用技巧给大家

技巧一&#xff1a;微信的听文字消息功能是一项方便而实用的功能&#xff0c;旨在帮助用户通过语音合成技术将文字消息转化为语音&#xff0c;以便用户可以通过听觉方式收听和理解信息。 这项功能适用于用户在某些情况下无法阅读或不方便阅读文字消息的场景。当用户收到一条文…

springboot、Mybatis-plus工程多数据源字段映射不生效

1、多数据源配置文件 2、配置项 多个数据源配置项中分别添加配置 bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); //配置驼峰命名 或者 参考地址 Configuration MapperScan(basePackages "it.aspirin.riderserver.mapper.mysql", sqlS…

C++模板初阶(函数模板、类模板)知识点+完整思维导图+实操图+深入细节通俗易懂建议收藏

绪论 思想决定行动&#xff0c;行动养成习惯&#xff0c;习惯形成品质&#xff0c;品质决定命运。——陶行知 本章讲的是c的初阶模板&#xff0c;全文不算代码字数少的可怜&#xff0c;但模板是我们c必须学的一个宝物&#xff0c;他的出现可是c的飞跃性成就&#xff01;下面将主…

如何在华为OD机试中获得满分?Java实现【打印文件】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

jsp基于 JavaWeb+springboot 的校园快递驿站管理系统

不同的系统提供的服务也不相同&#xff0c;其对应的功能也不相同&#xff0c;所以&#xff0c;系统开工前&#xff0c;需要明确其用途&#xff0c;确定其功能。由此&#xff0c;才可以进行各个任务的开展。 校园驿站管理系统经过分析&#xff0c;确定了其需要设置管理员的角色&…

如何使用Word控件Spire.Doc创建专属条码?

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

chatgpt赋能python:Python修改变量名:提高代码可读性和维护性

Python修改变量名&#xff1a;提高代码可读性和维护性 Python是一门通用编程语言&#xff0c;被广泛应用于Web开发、数据分析、人工智能等领域。在实际开发中&#xff0c;我们可能会遇到需要修改变量名的情况。本文将介绍如何使用Python修改变量名&#xff0c;提高代码的可读性…

LiveGBS流媒体平台国标GB/T28181功能-作为下级级联到海康大华宇视华为等第三方国标平台同样支持对接政务公安内网国标视频平台

LiveGBS流媒体平台国标GB/T28181功能-作为下级级联到海康大华宇视华为等第三方国标平台同样支持对接政务公安内网国标视频平台 1、什么是GB/T28181级联2、搭建GB28181国标流媒体平台3、获取上级平台接入信息3.1、如何提供信息给上级3.2、上级国标平台如何添加下级域3.2、接入Li…

【vim neovim】从入门到放弃(“四种”模式、常用命令、正则表达式、文件属性、插件安装--代码补全、文件树)

本文所有操作均通过ssh连接腾讯云服务器完成。如果你正在使用安装GNOME桌面的Linux&#xff0c;很多操作可以通过鼠标完成&#xff0c;或许更加直观。 推荐使用neovim&#xff08;结合鼠标操作更加丝滑&#xff09;。 nvim效果展示&#xff1a; 一、vim简介二、vim操作2.1 三种…