JVM内存结构

JVM内存结构

JVM在执行程序的过程中会将内存划分为五个不同的数据区域:虚拟机栈、本地方法栈、方法区、堆、程序计数器。
JVM五个区中虚拟机栈、本地方法栈、程序计数器为线程私有,方法区和堆为线程共享区。JVM不同区域的占用内存大小不同,一般情况下堆最大,用来存放”对象“,程序计数器较小

在这里插入图片描述

  • 堆(Heap):线程共享。
  • 方法区(Method Area):线程共享。
  • 虚拟机栈(VM Stack):线程私有。
  • 程序计数器(Program Counter Register):线程私有。
  • 本地方法栈(Native Method Stack):线程私有。
1.堆

堆是Java虚拟机所管理的内存中最大的一块存储区域。堆内存被所有线程共享。主要存放使用new关键字创建的对象。所有对象实例以及数组都要在堆上分配。垃圾收集器就是根据GC算法,收集堆上对象所占用的内存空间(收集的是对象占用的空间而不是对象本身)。

在这里插入图片描述

Java堆分为年轻代(Young Generation)和老年代(Old Generation);年轻代又分为伊甸园(Eden)和幸存区(Survivor区);幸存区又分为From Survivor空间和 To Survivor空间。

在这里插入图片描述

年轻代存储“新生对象”,我们新创建的对象存储在年轻代中。当年轻内存占满后,会触发Minor GC,清理年轻代内存空间。

老年代存储长期存活的对象和大对象。年轻代中存储的对象,经过多次GC后仍然存活的对象会移动到老年代中进行存储。老年代空间占满后,会触发Full GC。

GC类型:

Minor GC(又称Young GC):主要用于收集年轻代中的非存活对象。Minor GC在Eden区空间不足时触发。

Major GC:主要用于收集老年代中的非存活对象。Major GC在老年代空间不足时触发。注意:Major GC一般都会伴随一次Minor GC,Major GC的速度一般会比Minor GC慢10倍,因此,STW的时间会更长(应尽量避免Minor GC)。

Mixed GC(混合收集):主要用于收集年轻代以及部分老年代中的非存活对象。

Full GC:主要用于收集整个堆(含:年轻代和老年代)中的非存活对象,即:Major GC+Minor GC组合。Full GC触发条件:

  • 调用System.gc()方法时,可通过参数-XX:+ DisableExplicitGC来禁止调用System.gc()。
  • 方法区空间不足时。
2.方法区

方法区同 Java 堆一样是被所有线程共享的区间,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码

更具体的说,静态变量+常量+类信息(版本、方法、字段等)+运行时常量池存在方法区中。常量池是方法区的一部分。

在JDK8及之前,方法区属于永久代,而在JDK8之后,永久代被移除,方法区被移到了本地内存中,即:元空间(Meta Space)。

元空间逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫非堆。元空间是各个线程共享的内存区域,它主要存储两部分内容:

  • 类信息。
  • 运行时常量池 。

元空间相关参数:

  • MetaspaceSize :初始化元空间大小,控制发生GC阈值,默认值为20MB。
  • MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存,默认值为-1(表示无限制)。
3.虚拟机栈

JVM 中的栈包括 Java 虚拟机栈本地方法栈,两者的区别就是,Java 虚拟机栈为 JVM 执行 Java 方法服务,本地方法栈则为 JVM 使用到的 Native 方法服务

在这里插入图片描述

虚拟机栈为线程私有,它描述的是Java方法执行的内存模型。每个栈由多个栈帧(Stack Frame)组成,每个方法被执行时,Java虚拟机都会同步创建一个栈帧用于存储该方法的局部变量表、操作数栈、动态链接、方法返回地址等信息。

4.程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,可以看作是当前线程所执行字节码的行号指示器,指向下一个将要执行的指令代码,由执行引擎来读取下一条指令。更确切的说,一个线程的执行,是通过字节码解释器改变当前线程的计数器的值,来获取下一条需要执行的字节码指令,从而确保线程的正确执行。

程序计数器特点:

  • 每个线程都有一个独立的程序计数器,各线程之间计数器互不影响,独立存储。
  • 执行Java方法时,程序计数器的值不为空;执行Native本地方法时,程序计数器的值为空(Undefined)。
  • 程序计数器是唯一一个在Java虚拟机规范中没有规定任何内存溢出情况的区域。
5.本地方法栈

本地方法栈与虚拟机栈类似,不同的是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。在Java程序调用Native方法时,Native方法所需要的内存空间在本地方法栈中开辟。

本地方法栈特点:

  • 本地方法栈为线程私有。

  • 本地方法栈允许被实现成固定或者是可动态扩展的内存大小:

    • 固定内存大小,当线程请求分配的栈容量超过本地方法栈允许的最大内存大小时,Java虚拟机会抛出StackOverflowError异常。
    • 可动态扩展内存大小,当本地方法栈尝试扩展时无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,Java虚拟机会抛出OutOfMemoryError异常。
  • Native方法一般由C/C++实现,它的具体做法是先在本地方法栈中登记Native方法,然后在执行引擎中加载本地方法库并执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值