JVM内存模型
Java虚拟机(Java Virtual Machine = JVM)的存储空间分为五个部分,即:
1.程序计数器
2.Java虚拟机堆栈
3.本地方法堆栈
4.堆
5.方法区域。
以下是对这五个领域的深入介绍。
1.程序计数器1. 1.什么是程序计数器?
程序计数器是一个很小的存储空间,可以看作当前线程正在执行的字节码的行号指示符。换句话说,程序计数器记录了当前线程正在执行的字节码指令的地址。
注意:但是,如果当前线程正在执行本地方法,则程序计数器此时为空。
1. 2.程序计数器的作用
程序计数器具有两个功能:
字节码解释器通过更改程序计数器顺序读取指令,从而实现代码流控制,例如顺序执行,选择,循环和异常处理。在多线程的情况下,程序计数器用于记录当前线程执行的位置,以便当线程切换回时,您可以知道线程上次运行的位置。
1. 3.程序计数器的特征是线程专用的较小存储空间。每个线程都有一个程序计数器。这是唯一不会发生OutOfMemoryError的内存区域。生命周期是在创建线程时创建的,并程结束时终止。
2.Java虚拟机堆栈(JVM堆栈)2.1.什么是Java虚拟机堆栈?
Java虚拟机堆栈是描述Java方法运行过程的内存模型。

Java虚拟机堆栈为每个将要运行的Java方法创建一个称为“堆栈框架”的区域。该区域用于存储该方法在其操作期间所需的一些信息。这些信息包括:
局部变量表
存储基本数据类型变量,引用类型变量和returnAddress类型变量。操作数堆栈动态链接方法导出信息等。
当一种方法即将执行时,Java虚拟机堆栈将首先在Java虚拟机堆栈中为该方法创建一个“堆栈框架”。堆栈框架包含局部变量表,操作数堆栈,动态链接和方法出口。信息等。当该方法需要在运行过程中创建局部变量时,该局部变量的值将存储在堆栈框架的局部变量表中。
执行此方法时,与此方法相对应的堆栈帧将从堆栈中弹出,并释放内存空间。
注意:经常有人说Java的内存空间分为“堆栈”和“堆”。局部变量存储在堆栈中,对象存储在堆中。
这句话并不完全正确!可以通过这种方式理解此处的“堆”,但是此处的“堆栈”仅表示Java虚拟机堆栈的局部变量表部分。真正的Java虚拟机堆栈由堆栈框架组成,每个堆栈框架具有:局部变量表,操作数堆栈,动态链接,方法导出信息。
2.2.Java虚拟机堆栈的特征本地变量表的创建是在执行该方法时以及堆栈框架的创建。此外,局部变量表的大小是在编译时确定的,仅在创建时需要分配预定大小。此外,在方法运行期间,局部变量表的大小不会改变。 Java虚拟机堆栈中有两个例外:StackOverFlowError和OutOfMemoryError。
a)StackOverFlowError:
如果Java虚拟机堆栈的内存大小不允许动态扩展,则当线程请求堆栈的深度超过当前Java虚拟机堆栈的最大深度时,将引发StackOverFlowError异常。
b)OutOfMemoryError:
如果Java虚拟机堆栈的内存大小允许动态扩展,并且当线程请求堆栈时内存已用完,并且无法再动态扩展,则会引发OutOfMemoryError异常。 Java虚拟机堆栈也是线程专用的,每个线程都有自己的Java虚拟机堆栈,该堆栈是在创建线程时创建的,并程死亡时死亡。
注意:StackOverFlowError与OutOfMemoryError之间的异同吗?
StackOverFlowError表示当前线程请求的堆栈超出了堆栈的预定最大深度,但是可能有很多内存空间。
OutOfMemoryError意味着当线程申请堆栈时,发现堆栈已满,并且内存全部用完。
3.本机方法堆栈3. 1.什么是本机方法堆栈?
由本地方法堆栈和Java虚拟机堆栈实现的功能相似,不同之处在于本地方法区域是本地方法的内存模型。
执行本地方法时,将在本地方法堆栈中创建一个堆栈框架,以存储本地变量表,操作数堆栈,动态链接和本地方法的导出信息。
执行该方法后,将弹出相应的堆栈帧并释放内存空间。
它还会引发StackOverFlowError和OutOfMemoryError异常。
4.堆4. 1.什么是堆?
堆是用于存储对象的内存空间。
几乎所有对象都存储在堆中。
4. 2.堆线程共享的功能
整个Java虚拟机只有一个堆,并且所有线程都访问同一堆。程序计数器,Java虚拟机堆栈和本地方法堆栈都与每个线程相对应。启动虚拟机时,请创建垃圾收集的主要位置。它可以进一步细分为:新一代和老一代。
新一代可以分为:伊甸园,从幸存者到幸存者。
不同区域存储具有不同生命周期的对象。这样,可以根据不同的区域使用不同的垃圾收集算法,这更有针对性和效率。堆大小可以固定或扩展,但是主流虚拟机堆大小是可扩展的,因此,当线程请求分配内存但堆已满,并且内存已满且无法扩展时,将引发OutOfMemoryError。
5.方法区域5. 1.什么是方法区域?
Java虚拟机规范中定义的方法区域是堆的逻辑部分。
方法区域存储虚拟机已加载的类信息,常量,静态变量,即时编译器编译的代码等。
5. 2.方法区域的功能线程共享
方法区域是堆的逻辑部分,因此它由堆等线程共享。整个虚拟机中只有一个方法区域。永久世代

方法区域中的信息通常需要存在很长时间,并且它是堆的逻辑分区,因此我们使用划分堆的方法。我们称方法区为老年。内存恢复效率低
方法区域中的信息通常需要存在很长时间,并且在回收内存之后,只有少量信息可能是无效的。
方法区域中的内存恢复的主要目标是:恢复常量池和卸载类型。 Java虚拟机规范对方法区域的要求相对宽松。
就像堆一样,它允许固定大小,可扩展大小,并且没有垃圾回收。
5. 3.什么是运行时常量池?
方法区域中存储了三种类型的数据:类信息,常量,静态变量和由即时编译器编译的代码。常量存储在运行时常量池中。
我们通常通过public static final在类中声明一个常量。编译该类后,将生成一个Class文件,并将该类的所有信息存储在该类文件中。
当Java虚拟机加载此类时,该类文件中的常量存储在方法区域中的运行时常量池中。并且在操作过程中,您可以向常量池添加新的常量。例如,String类的intern()方法可以在运行时将字符串常量添加到常量池中。
当常量池中的某些常量在运行时没有被对象引用,也没有由变量引用时,则需要垃圾回收器来回收它们。
6.直接存储
直接内存是Java虚拟机以外的内存,但是Java也可以使用它。
NIO中引入了基于通道和基于缓冲区的IO方法。它可以通过调用本地方法在Java虚拟机外部直接分配内存,然后通过存储在Java堆中的DirectByteBuffer对象直接操作内存,而无需先将外部存储器中的数据复制到堆中然后再进行操作,从而改进了改进。数据操作的效率。
直接内存的大小不受Java虚拟机的控制,但是由于它是内存,因此当内存不足时会引发OOM异常。
总而言之,上述Java虚拟机的内存模型中有两个“堆栈”,即:Java虚拟机堆栈和本地方法堆栈。
两个“堆栈”的功能是相似的,并且都是方法运行过程的内存模型。而且这两个“堆栈”的内部结构是相同的,都是线程私有的。
只是Java虚拟机堆栈描述了Java方法运行过程的内存模型,而本机方法栈是描述Java本机方法运行过程的内存模型。 Java虚拟机的内存模型中有两个“堆”,一个是原始堆,另一个是方法区。方法区域本质上是堆的逻辑部分。对象存储在堆中,并且类信息,常量,静态变量和即时编译器编译的代码存储在方法区域中。堆是Java虚拟机中最大的内存区域,也是垃圾收集器的主要工作区域。程序计数器,Java虚拟机堆栈和本地方法堆栈是线程专用的,也就是说,每个线程都有自己的程序计数器,Java虚拟机堆栈和本地方法区域。它们的生命周期与它们所属的线程相同。
堆和方法区域由线程共享。 Java虚拟机中只有一个堆和一个方法堆栈。它是在JVM启动时创建的,只有在JVM停止时才被销毁。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-354032-1.html
2楼的就知道瞎叫