【JVM之美】运行时数据区
运行时数据区
1、程序计数器
记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空)
2、java虚拟机栈
每个java方法在执行的同时会创建一个栈帧用于存储局部变量表,操作数栈、常量池引用等信息。从调用直至执行完成的过程,就对应着一个栈帧在java虚拟机中入栈和出栈的过程、
可以通过-Xss这个虚拟机参数来指定每个线程的java虚拟机内存大小。
java -Xss=512M HackTheJava
该区域可能抛出一下这个异常
当线程请求的栈深度超过最大值 会抛出StackOverFlowError异常。
栈进行动态拓展时如果无法申请足够内存,会抛出OutofMemoryError异常
3、本地方法栈
本地方法一般是用其他(c c++ 或汇编语言)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理
本地方法栈与java虚拟机栈类似,他们之间的区别只不过是本地方法栈为本地方法服务。
4、堆
所有对象都在这里分配内存,是垃圾收集的主要区域(GC堆)
现代的垃圾收集器基本都是采用分代收集算法。针对不同类型的对象采用不同的垃圾回收算法,可以将堆分成两块。
新生代 (Young Generation)
老年代(Old Generation)
新生代可以继续划分成一下三个空间
Eden(伊甸园)
From Survivor(幸存者)
To Survivor
堆不需要连续内存,并且可以动态增加其内存,增加失败会抛出OutOfMemoryError异常。
可以通过-Xms和-Xmx 两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值
java -Xms=1M -Xmx=2M HackTheJava //初始值1M 最大值2M
5、方法区
用于存放已被加载的类信息,常量、静态变量。即时编译器编译后的代码等数据
和堆一样不需要连续的内存,并且可以动态拓展,动态拓展失败一样会抛出OutOfMemoryError异常。
对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现。
jdk1.7 之前,Hotspot虚拟机把它当成永久代来进行垃圾回收,但是从jdk1.7开始,已经把原本放在永久代的字符串常量移到Native Method中了
6、运行时常量池
运行时常量池是方法区的一部分
Class文件中的常量池(编译器生成的各种字面量和符号引用)会在类加载后被放入这个区域。
除了在编译器生成的常量,还允许动态生成。例如String类的intern();
7、直接内存
在jdk1.4中新加入了NIO类,它可以使用native函数库直接分配堆外内存,然后通过一个存储在java堆里的DirectByteBuffer对象作为这块内存的引用进行操作。