JVM分为哪几部分?

JDK1.8之前:
在这里插入图片描述
JDK1.8之后:
在这里插入图片描述
在这里插入图片描述

各个区域的作用:

1.2.2.1 程序计数器
  • 字节码解释器通过改变程序计数器来依次读取指令,从⽽实现代码的流程控制,如:顺序执⾏、选择、循环、异常处理。

  • 在多线程的情况下,程序计数器⽤于记录当前线程执⾏的位置,从⽽当线程被切换回来的时候能够知道该线程上次运⾏到哪⼉了

    程序计数器是唯一不会出现OutOfMemoryError的内存区域

1.2.2.2 Java虚拟机栈

它的生命周期和线程相同,随着线程的创建而创建,随着线程的死亡而死亡。每次方法调用的数据都是通过栈传递的。

实际上Java虚拟机栈是由一个个栈帧(拥有:局部变量表、操作数栈、动态链接、方法出口信息)组成。

  • Java栈就好比数据结构中的栈,Java栈中保存的是栈帧,每一次函数调用都会有一个对应的栈帧压入Java栈,调用结束后栈帧就会弹出
1.2.2.3 本地方法栈

和Java虚拟机栈相似。区别:虚拟机栈为虚拟机执⾏ Java ⽅法 (也就是字节码)服务,⽽本地⽅法栈则为虚拟机使⽤到的 Native ⽅法服务。

1.2.2.4 堆

Java虚拟机启动的时候创建。用途: 存放对象实例。

几乎所有的对象实例和数组都在堆上面分配内存。但是JDK1.7之后默认开启逃逸分析 (如果某些⽅法中的对象引⽤没有被
返回或者未被外⾯使⽤(也就是未逃逸出去),那么对象可以直接在栈上分配内存)。

在这里插入图片描述

JDK8开始,Hotspot的永久代被彻底移除,取而代之的是元空间

对象都会⾸先在 Eden 区域分配,在⼀次新⽣代垃圾回收后,如果对象还存活,则会进⼊ s0 或者 s1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到⼀定程度(默认为 15 岁),就会被晋升到⽼年代中。对象晋升到⽼年代的年龄阈可以通过参数 -XX:MaxTenuringThreshold 来设置

1.2.2.5 方法区

⽅法区与 Java 堆⼀样,是各个线程共享的内存区域,它⽤于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

1.2.2.6 运行时常量池
  1. JDK1.7之前运⾏时常量池逻辑包含字符串常量池存放在⽅法区, 此时hotspot虚拟机对⽅法区的实现为永久代.
  2. JDK1.7 字符串常量池被从⽅法区拿到了堆中, 这⾥没有提到运⾏时常量池,也就是说字符串常量池被单独拿到堆,运⾏时常量池剩下的东⻄还在⽅法区, 也就是hotspot中的永久代 。
  3. JDK1.8 hotspot移除了永久代⽤元空间(Metaspace)取⽽代之, 这时候字符串常量池还在堆, 运⾏时常量池还在⽅法区, 只不过⽅法的实现从永久代变成了元空间(Metaspace)

Java常量池中存储的对象的引用,实际上对象还是存储在Java堆上的。

1.2.2.7 直接内存

直接内存并不是虚拟机运⾏时数据区的⼀部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使⽤。⽽且也可能导致 OutOfMemoryError 错误出现 。

参考:SnailClimb&JavaGuide

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值