JUC与JVM(6)JVM堆Heap内存详解

3 篇文章 0 订阅

JVM堆内存划分

在这里插入图片描述
逻辑上分为3区:

  1. 新生代Young Gen
    1. 伊甸园区 --Eden
    2. 幸存者0区 --S0/from
    3. 幸存者1区 --S1/to
    4. 默认比例 eden:S0:S1=8:1:1
  2. 老年代Old Gen
  3. 元空间(jdk7:永久区)Perm Gen

物理上分为:新生代+老年代

新生代:老年代 = 1 :2;

堆new对象流程

在这里插入图片描述

新生区是对象的创建,成长,销毁的区域,一个对象在这里产生,应用,然后被GC(垃圾回收器)收集,结束生命;所有的类都是在新生代内的eden区被new的,幸存者有两个区,S0(又称from区),S1(又称to区);当eden区快 用完时,将进行一次垃圾回收,为MinorGC(轻量级的垃圾回收器),将新生代区,没有被引用的对象进行销毁,随后eden区的剩余对象,将升级机制,eden–》S0;若该对象经历了15次的垃圾回收机制,还没有被销毁,将进入老年代,若老年代区域内存快满,将进行FullGC(重量级),若执行了FullGC后依然发现无法进行对象的保存,将抛出OOM错误(Out Of Memory);

MinorGC原理

from区和to区,这两个区域位置和名次不固定,每次GC后互换,谁空谁是to区

GC过程(复制–清空—交换)

  1. eden区第一次满触发MinorGC;
  2. 还存活的对象复制到From区;/也可理解为到to区(因为此时from 和 to 内存都为0,没有严格的区分,谁空谁是to区)
  3. 清空eden区
  4. 当eden区再次出发GC,扫描eden和from区,一起回收
  5. 存活的对象复制到to区(to区为0),年龄+1(若年龄符合,此时升级为老年代)
  6. 清空eden和from区
  7. 此时from区清空变为to区,to区有存活存活成为from区;
  8. 直到年龄15,升级为老年代

永久代

经研究和统计:98%的对象为临时对象,即只在eden区活动

实际而言:方法区和堆一样。是各个线程共享的内存区域,它用来存储虚拟机加载的,类信息+普通常量+编译器编译后的代码等等,虽然JVM规范把方法区描述成堆的一个逻辑部分,但它还有一个别名no-heap(非堆),目的是把它和heap分开;

对于hotspot虚拟机而言,很多开发者习惯把方法区成为永久代,但严格意义上讲两者是不同的,或者说使用永久代来实现方法区,永久代是方法区(理解为接口)的实现;jdk1.7中,已经把原在永久代的字符常量池移走;

永久代:

是一个常驻内存的区域,用来存放JDK自身携带的Class,interface的元数据,也就是它存储的是运行环境所必须的类信息,该区域不会被GC所清除,关闭JVM才会被释放;

堆参数调优

以JDK1.8+hotspot为例

JDK7:
在这里插入图片描述
-Xx:Permisize :调整永久代的空间

JDK8:
在这里插入图片描述

永久代移除,元空间代替,

永久代和元空间的最大区别:

永久代使用的JVM的堆内存,但是元空间使用的空间,并不属于JVM范畴,而是使用本机物理内存,因此元空间大小受本地内存限制,类的元数据放入native memory,字符串和类的静态变量放入堆中,这样可以加载多少类的元数据不再由JDK1.7的MaxPermiSize控制,而由系统实际可用空间来控制;

-xms:设置初始分配大小,默认物理内存的“1/64”;

-xmx:最大分配内存,默认物理内存的“1/4”;

-XX:printGCDetails:输出GC的详细日志;

Runtime类:对应JVM runtime

    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
        System.out.println("xms:"+Runtime.getRuntime().totalMemory()/1024/1024+"Mb");
        System.out.println("xmx:"+Runtime.getRuntime().maxMemory()/1024/1024+"Mb");
    }

最好xms和xmx设置为一样,避免频繁开辟内存空间所带来的资源消耗,避免内存忽高忽低;同时在判断gc是否运行时,gc和开辟内存相互竞争,导致程序异常

idea中配置jvm参数

在这里插入图片描述
在这里插入图片描述
gc运行解析

运行下列代码

    public static void main(String[] args) {
        String str = "test";
        while (true){
            str +=  str +new Random().nextInt(88888)+new Random().nextInt(9999999);
        }
    }

调节jvm参数

-Xms10m -Xmx10m -XX:+PrintGCDetails

报错:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

观察GC日志

在这里插入图片描述
在这里插入图片描述
结论:开始minor GC,随后FullGC,最后FullGC也没法开辟空间---->报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值