Java基础之JVM内存模型

JVM内存模型

JVM内存模型的标准是拥有五个区域,分别为程序计数器、Java栈、本地方法栈、方法区以及堆;其中程序计数器、Java栈和本地方法栈是线程私有的,方法区和堆是线程共享的;接下来详细介绍下这几个区域。

1. 程序计数器

1.1 程序计数器的介绍

程序计数器只拥有一块很小的内存空间,是唯一一个不会发生内存溢出的区域。主要用来记录当前线程所执行指令的行数,但需要注意的是,如果执行的是本地方法,那么程序计数器是空的。

1.2 程序计数器的作用

  • 流程控制:实现程序的顺序执行、选择、循环以及异常处理。
  • 线程的上下文切换:帮助线程完成上下文切换工作,快速恢复上次的工作场景。

2. Java栈

2.1 Java栈的介绍

Java虚拟机栈会为每一个即将运行的Java方法创建一块叫做“栈帧”的区域,这块区域用于存储该方法在运行过程中所需要局部变量表、动态链接、操作数栈以及方法出口等信息。

2.2 Java栈的特点

  • 局部变量表的创建是在方法被执行的时候,随着栈帧的创建而创建。而且,局部变量表的大小在编译时期就确定下来了,在创建的时候只需分配事先规定好的大小即可。此外,在方法运行的过程中局部变量表的大小是不会发生改变的。

  • Java虚拟机栈也是线程私有的,每个线程都有各自的Java虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡。

  • Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError。StackOverFlowError 是栈的请求深度超过当前Java虚拟机栈的最大深度的时候抛出的异常,例如:死递归;OutOfMemoryError是栈请求的内存无法分配时抛出的异常。

3. 本地方法栈

3.1 本地方法栈的介绍

本地方法栈和Java虚拟机栈实现的功能类似,只不过本地方法栈是为本地(native)方法服务的。

4. 方法区

4.1 方法区的介绍

Java 虚拟机规范中定义方法区是堆的一个逻辑部分。方法区中存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等,其中常量存放在运行时常量池之中。

4.2 方法区的“前世今生”

永久代(“PermGen space”)是HotSpot虚拟机对“方法区”的具体实现,这是HotSpot虚拟机特有的,在JRockit(Oracle)、J9(IBM) 并没有“PermGen space”。
在Java7的时候,存储在永久代的部分数据就已经转移到了Java Heap或者是 Native Heap,其中运行时常量池移动到了Java Heap,符号引用(Symbols)转移到了Native Heap。
在Java8的时候,HotSpot将永久代彻底移除了,将剩余未转移的数据都放在了元空间(Metaspace)中。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小。

5. 堆区

堆区的介绍

堆是用来存放对象的内存空间,堆内存随着JVM启动而创建。堆可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。

若进一步细分,可以将堆区分为年轻代和老年代。其中年轻代中又可以细分为Eden、From Survior以及To Survior三个区域,三者的默认占比为8:1:1,两个Survior区主要是为了方便“***回收”算法处理回收不再使用的对象。

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务