【大厂必考之JVM】02,作为Java开发程序员

2021/12/13 14:18:46

本文主要是介绍【大厂必考之JVM】02,作为Java开发程序员,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

总结


一、堆的结构

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

===================================================================

  • 新生区:新生区分为三部分,一块较大的Eden(伊甸)空间和两块较小的Survivor(幸存者)空间,默认比例为8:1:1。
  • 养老区
  • 永久存储区/元空间:JDK1.8之后元空间替代永久区

新生区和养老区是垃圾回收的主要区域。新生区和养老区的面积比是1:2

逻辑结构

逻辑结构

物理结构

物理结构

1.1新生区


新生成的对象全部优先存放在新生区中,新生区对象朝生夕死,存活率很低,在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高。

1.2 养老区


在新生代中经历了多次(具体看虚拟机配置的阀值)GC后仍然存活下来的对象会进入老年代中。养老区的空间满了之后会进行Full GC,也叫重GC,FGC。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。当FGC之后,养老区依然没有足够的空间,堆内存溢出。OOM:

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

1.3堆结构的代码验证


首先 idea 进入 Edit configuration -> VM options:

添加:-XX:+PrintGCDetails

/**

  • @Author: 一条IT

  • @Date: 2020/12/6 12:47

*/

public class TestJVM {

public static void main(String[] args) {

// jvm分配的最大内存 默认物理内存的1/4

System.out.println("-Xmx:"+Runtime.getRuntime().maxMemory()/1024/1024+“Mb”);

// jvm分配的初始内存 默认物理内存的1/64

System.out.println("-Mms:"+Runtime.getRuntime().totalMemory()/1024/1024+“Mb”);

}

}

输出结果

-Xmx:1787Mb

-Mms:121Mb

Heap

PSYoungGen total 37888K, used 4592K [0x00000000d6200000, 0x00000000d8c00000, 0x0000000100000000)

eden space 32768K, 14% used [0x00000000d6200000,0x00000000d667c370,0x00000000d8200000)

from space 5120K, 0% used [0x00000000d8700000,0x00000000d8700000,0x00000000d8c00000)

to space 5120K, 0% used [0x00000000d8200000,0x00000000d8200000,0x00000000d8700000)

ParOldGen total 86016K, used 0K [0x0000000082600000, 0x0000000087a00000, 0x00000000d6200000)

object space 86016K, 0% used [0x0000000082600000,0x0000000082600000,0x0000000087a00000)

Metaspace used 3226K, capacity 4496K, committed 4864K, reserved 1056768K

class space used 351K, capacity 388K, committed 512K, reserved 1048576K

可以看到-Mns:初始化分配的内存大小121mb,新生代37888k,老年代86016k,相加约等于121*1024k。证明元空间在物理结构上不属于堆。

以上分配的大小和各自的比例,都可以调整,在JVM调优讲。

二、对象的生命周期和垃圾回收

==============

1.对象被回收的流程


总结:复制——清空——交换

新生成的对象在Eden区分配(大对象除外,大对象直接进入老年区),当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC也叫轻GC,YGC。

GC进行时,Eden区中所有存活的对象都会被复制到To Survivor区,而在From Survivor区中仍存活的对象会根据它们的年龄值决定去向,年龄值达到年龄阀值(默认为15,新生代中的对象每熬过一轮垃圾回收,年龄值就加1,GC分代年龄存储在对象的header中)的对象会被移到老年区中,没有达到阀值的对象会被复制到To Survivor区。

接着清空Eden区和From Survivor区,新生代中存活的对象都在To Survivor区。接着, From Survivor区和To Survivor区会交换它们的角色,这样新的To Survivor区就又是空的,来承接下一次的轻GC。

交换:from区和to区并不是固定的,而是随时在交换身份,谁是空的是作为to区

当To Survivor区没有足够的空间存放上一次新生代收集下来的存活对象时,需要依赖老年代进行分配担保,将这些对象存放在老年代中。

2.永久代/元空间


永久代其实是方法区的一个实现jdk1.8之后。永久代改为元空间。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,可以指定元空间的大小。



这篇关于【大厂必考之JVM】02,作为Java开发程序员的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程