java内存区域的分布
读了《深入理解Java虚拟机》之后,当时理解了,过段时间又忘记了,在此做下记录,方便自我回顾,也希望能帮到想要学习虚拟机的同学。
Java虚拟机在执行java程序时会把它所管理的内存分为5个不同的数据区域(也可以细分为7个不同的区域,后续做介绍):程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区
java虚拟机运行时数据区
1、程序计数器:用来记录正在执行的虚拟机字节码指令地址。可通过改变这个计数器的值来选取下一条需要执行的字节码指令。
-
- 线程私有:为了线程切换后能恢复到正确的位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响。
2、Java虚拟机栈:线程私有,生命周期与线程相同,每当创建一个线程时,JVM就会为这个线程创建一个对应的java栈。在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。
-
- 局部变量表:存放编译器可知的各种基本数据类型、对象引用。
3、本地方法栈:与虚拟机栈发挥的作用相似,区别在于:虚拟机栈为虚拟机执行java方法(也就是字节码)服务,本地方法栈为虚拟机使用到的Native方法服务。
4、java堆:存储对象实例以及数组。是垃圾收集器管理的主要区域。
-
- 线程共享。java堆可以处于物理上不连续的内存空间,只要逻辑上连续即可。
5、方法区:用于存放类信息(如类名、访问修饰符等)、常量池、静态变量、即时编译器便宜后的代码等。虽然JVM规范把方法区描述为堆的一个逻辑部分, 但它却有个别名non-heap(非堆),目的应该是与Java堆区分开来。
6、运行时常量池:方法区的一部分,用于存放编译期生成的各种字面量和符号引用。
-
- 常量池:指的是编译期被确定并被保存在已编译的.class文件中的一些数据,除了包含代码中所定义的各种基本类型(如int、long等)和对象类型(如String和数组)的常量值(final),还包含一些以文本形式出现的一些符号引用。
7、直接内存:堆外的内存。它不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。