JVM内存模型简介

JVM内存模型

JVM构成如下图:
在这里插入图片描述
在这里插入图片描述
这里重点聊一下运行时数据区,如图所示,Java运行时数据区主要分为方法区、堆、虚拟机栈、本地方法栈、程序计数器组成。其中方法区和堆为线程共享的,虚拟机栈、本地方法栈和程序计数器是线程私有。
1. 程序计数器
程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。由于Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。如果线程正在执行的是一个Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie 方法,这个计数器值则为空(Undefined)。
2. 虚拟机栈
每一个Java方法都对应了虚拟机栈中的一个栈帧,而每个栈帧又由局部变量表、操作数栈、动态链接、方法出口组成。对于执行引擎来说,活动线程中,只有栈顶的栈帧是有效的,称为当前栈帧,这个栈帧所关联的方法称为当前方法。执行引擎所运行的所有字节码指令都只针对当前栈帧进行操作。
3. 本地方法栈
原理上可以看作于虚拟机栈类似,只不过本地方法栈是服务于本地Native方法的。
4. 堆
堆是Java 虚拟机所管理的内存中最大的一块,几乎我们创建出来的所有对象都存在堆里面,为什么要用几乎?因为随着JIT 编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了,在后面的文章中会专门进行逃逸分析和标量替换等的分析。
从上面的图中可以看出,堆又可以分为老年代和年轻代,而年轻代又分为EDEN区、S1/S2区。在不考虑逃逸分析的情况下,我们创建出来的对象首先一定是分配在EDEN,随着GC次数的增加,对象还会在S1和S2之间反复复制,当对象的年龄达到一定的值(默认是15)时,就会被分配到老年代。一个对象是否被分配到老年代还有很多因素,后续的文章会慢慢分析~~
5. 方法区
方法区主要用来存放类的元信息,比如这个类的全限定名、这个类型的访问修饰符、字段信息、方法信息等;另外JVM为每个已加载的类型都维护一个常量池。常量池就是这个类型用到的常量的一个有序集合,包括实际的常量和对类型,域和方法的符号引用。池中的数据项类似于数组,是通过索引访问的。每个类的这些元数据,无论是在构建这个类的实例还是调用这个类某个对象的方法,都会访问方法区的这些元数据。
在jdk1.8之前,方法区很多情况下被称为永久代,但到jdk1.8之后永久代就被元空间取代了,与永久代不同的是,元空间共享的是整个物理主机的内存。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值