java虚拟机运行时数据区域的概括图如下所示:
下面将对运行时数据区进行讲解
程序计数器
1、说明:程序计数器可以看做是当前线程所执行的字节码的行号指示器。其实通俗点讲就是记录class文件运行到哪一行
2、注意的点:
(1)因为CPU执行时只能处理一个线程的代码,但是可能有多个线程在执行,所以需要记录每个线程执行到哪里,所以每个线程都有一个独立的程序计数器。所以这类区域是 “线程私有” 的内存
(2)此区域在Java虚拟机中是唯一一个没有 OutOfMemory 的区域
Java虚拟机栈
1、说明:Java虚拟机栈描述的是 Java 方法执行的内存模型。在每个方法执行时都会创建一个栈帧,用来存储局部变量表、操作数栈、动态链接、方法出口等信息。其实通俗来讲就是记录线程在执行方法过程中方法的相关信息
2、形象:一个方法执行完了就不在执行了,你可以想象一下,其实就是对应着栈这种数据结构的特点,方法调用时就入栈,方法执行完了就出栈
3、其实我们经常所说的 “堆栈” 中的栈指的就是这里,更确切的说是虚拟机栈中的局部变量表。
4、注意:该区域会抛出两种异常
(1)StackOverFlowError:如果线程请求的栈的深度超过虚拟机所允许的深度。因为栈你可以看做是一个井,往里边倒水,当水倒多了,水就溢出来了
(2)OutOfMemoryError:如果虚拟机栈的内存可以动态扩展且扩展时申请不到内存,那么就会报错
5、也是 线程不共享 的
本地方法栈
1、说明:本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间
的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚
拟机使用到的Native方法服务。
2、注意:该区域与Java虚拟机栈一样,都会抛出StackOverFlowError、OutOfMemoryError异常
Java堆
1、说明:java对是存放对象实例和数组的。是所有线程共享的。也是垃圾回收GC的主要区域
2、Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样
方法区
1、说明:它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区和堆一样,都是线程共享的。
2、除了和堆一样的内存数据可以不连续外,该区域可以不实现垃圾回收。该区域的内存回收主要是针对运行时常量池的回收和对类型的卸载
运行时常量池
1、说明:该区域是方法区中的一部分。主要用来存放编译期生成的各种字面量和符号引用
2、特性:运行时常量池具备动态性。如何理解呢?就比如 String 类的 intern() 方法。如果该字符串不在运行时常量池,那么会将该字符串保存到运行时常量池中,然后将该字符串的地址放回,你可以运行如下代码:
String aa = new String("aa");
String bb = new String("aa");
System.out.println(aa == bb);//false
String cc = new String("aa").intern();
String dd = new String("aa").intern();
System.out.println(cc == dd);//true
本文参考自:《深入理解Java虚拟机:JVM高级特性与最佳实践》