jvm脉络梳理2-堆,内存调优

11.堆:调优,在jvm中

在这里插入图片描述

  • Heap一个JVM只有一个堆内存,存在垃圾。堆内存的大小可以调节。

  • 类加载器读取类文件后,会把:类、方法、常量、变量保存所有引用类型的真实对象,引用废弃后真实对象在堆中成为垃圾

  • 堆内存细分为3个区域:

  • 新生区:

  • 养老区:

  • 永久区:
    在这里插入图片描述

  • GC垃圾回收主要存在于新生区和养老区

  • 堆内存满了,OOM,程序严重out of memoryERROR

  • JDK8以后,永久存储区更新为元空间

12.新生区
  • 类:产生、成长甚至死亡;大部分被在此GC掉

  • 伊甸园区:所有的对象都是在此区new出来的,此区满了就会触发一次轻GC ,把幸存的移到幸存区,

  • 幸存区(0、1):经过几轮轻GC,幸存区也满了那会移动到养老区

  • 实际上99%的对象是临时对象。用过一次后就不在管理了,进养老去的情况不过,在幸存1区就GC了,少见oom的错误

13.老年区
  • 从新生区活下来的存入到老年区,老年区满了就进行重GC。
14.永久区:和对象关系不大,无垃圾回收
14.1概述
  • 此区域常驻内存,用来存放jdk自带的Class对象。包括接口数据和元数据,存储的是java运行时环境或,同jre,放在磁盘中,第三方JAR包,关闭虚拟机释放永久区

  • jdk1.6 之前:永久代,常量池在方法区中,是方法区的实现,此时永久代还在堆内。

  • jdk1.7 :永久代,慢慢退化,去永久代,常量池在堆中,常量池不好控制,方法区小,所以会经常出现永久带溢出问题。

  • 1.8之前方法区逻辑上是在堆中,实际和堆内其他区完全隔离开

  • jdk1.8:无永久代,常量池在元空间中,在本地内存中,取代jvm中的方法区。运行时常量池在元空间。放常量、方法原信息、类原信息。元空间和堆不是连续物理内存,改为使用本地内存

  • oom和永久区无关,除非一个启动类加载了大量的第三方JAR包。如Tomcat部署了太多的应用,大量动态生成的反射类。不断的被加载直到内存满,就会oom

14.2 方法区是个规范:实现方式是永久代、元空间
  • 方法区是堆的一部分,但故意把方法区称为非堆,目的和堆区分
  • 解决方法:微服务不用加载那么多类
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZvhuBoo-1651398147079)(E:\zkNote\typora-user-images\image-20220419220454475.png)]
    在这里插入图片描述
  • 元空间逻辑上存在:物理上不存在,使用本地内存
  • 每次轻GC幸存区都换位置
15.堆内存调优
15.1 查看堆内存,调优命令
//返回jvm初始化的内存
       long totalMemory = Runtime.getRuntime().totalMemory();
       //返回虚拟机视图使用的最大内存
       long maxMemory = Runtime.getRuntime().maxMemory();  //字节
       //初始、最大
       //-Xms500m -Xmx1024m -XX:+PrintGCDetails
       /*
       * 字节 byte:8个二进制位为一个字节(B),最常用的单位,字节也就是B。

           1KB (Kilobyte 千字节)=1024B

           1MB (Megabyte 兆字节 简称“兆”)=1024KB

           1GB (Gigabyte 吉字节 又称“千兆”)=1024MB*/

       System.out.println("maxMemory="+maxMemory+"字节"+maxMemory / (double) 1024 / 1024+"MB");
       System.out.println("totalMemory="+totalMemory+"字节"+totalMemory / (double) 1024 / 1024+"MB");
       //有损失,解释空间会丢、厂家以1000算,实际是1024
       //占真实内存的1/4
       /*maxMemory=3779067904字节3604.0MB
       //占真实内存的1/64 =  PSYoungGen+ParOldGen
       totalMemory=255328256字节243.5MB*/

       //oom
       //1.尝试扩大堆内存看结果
       //2.分析内存,看一下那个地方出现问题(专业工具)
       //3.查看代码是否有死循环
       /*
       * Heap
PSYoungGen      total 75776K, used 7815K [0x000000076b900000, 0x0000000770d80000, 0x00000007c0000000)
 eden space 65024K, 12% used [0x000000076b900000,0x000000076c0a1d80,0x000000076f880000)
 from space 10752K, 0% used [0x0000000770300000,0x0000000770300000,0x0000000770d80000)
 to   space 10752K, 0% used [0x000000076f880000,0x000000076f880000,0x0000000770300000)
ParOldGen       total 173568K, used 0K [0x00000006c2a00000, 0x00000006cd380000, 0x000000076b900000)
 object space 173568K, 0% used [0x00000006c2a00000,0x00000006c2a00000,0x00000006cd380000)
Metaspace       used 3258K, capacity 4496K, committed 4864K, reserved 1056768K
 class space    used 354K, capacity 388K, committed 512K, reserved 1048576K*/
15.2 调优命令参数列表

在这里插入图片描述

  • 大对象直接进入老年代:指字符串和数组,虚拟机提供了一个-XX:PretenureSizeThreshold参数,大于这个值的参数直接在老年代分配这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存复制(新生代采用复制算法)
15.3 排错
  • 能够看到代码第一行出错:内存快照分析工具。(eclipse中MAT)IDEA(Jprofiler工具)

  • Debug一行行分析代码

  • MAT/Jprofiler测试工具

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

  • 获得堆中数据

  • 获得大的对象

15.4 jprofiler安装
  • 下载并使用注册机注册
  • 在idea中安装jprofiler插件,清空缓存后重启
    在这里插入图片描述
  • idea关联jprofiler可执行文件
    在这里插入图片描述
  • 若要出现oom,则要调整堆内存大小,让代码出现死循环
/*-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError*/  vm option
  • 在项目根目录出现dump错误文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 装入了一次
    在这里插入图片描述
  • 具体报错点
    在这里插入图片描述
下一篇:jvm探究-02-jvm脉络梳理3-GC垃圾回收
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值