程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
线程私有
虚拟机栈
1.(与线程的生命周期相同,私有)放栈帧(与方法的生命周期相同),栈帧里面有局部变量表(我们常说的栈就只这里,基本数据类型,对象引用),操作数栈,动态链接(运行会,将符号引用转换为直接引用)方法出口(两种 异常和return)
2.会出现两个异常 StackOverFlowError线程请求的深度大于虚拟机锁允许的深度
OutOfMemoryError,可以动态扩展时,无法申请到足够内存
本地方法栈类似于虚拟机栈,有的虚拟机进行二合一
java堆:无论怎么划分,都是为了更好的回收,因为JIT编译器(jvm会将编译的代码进行解释执行,翻译成机器码,即时编译器会将解释后的代码保存起来在方法区,下次就可以执行使用)和 逃逸技术的成熟,对象在堆上变得不那么绝对,
方法区:
1.方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
2.在目前已经发布的JDK 1.7的HotSpot中,已经把原本放在永久代的字符串常量池移出。
3.Java虚拟机规范对方法区的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,这区域的内存回收目标主要是针对常量池的回收和对类型的卸载
运行时常量池:
1.三个常量池:
class文件中的常量池(静态,存储编译期间生成的字面量和符号引用),
这部分内容将在类加载后进入方法区的运行时常量池(动态)中存放。
运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,用的比较多的是String 类中的intern();
字符串常量池(1.7之后在堆上)StringTable维护了为每一个常量一直维护一个引用,一直都会被引用指向,所以也不会被垃圾回收,调用intern的时候,如果池中有就把SringTable中的的该常量的引用返回
2.运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时
会抛出OutOfMemoryError异常。
注意:直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分