java虚拟机---运行时数据区
我们熟知的对java内存区域的分类就是:栈(stack),堆(heap),但实际上比这复杂一些:
程序计数器
就是一个记录字节码执行的行号的一个计数器,字节码解释器工作时就是通过改变这个计数器的值来获取下一条要执行的字节码指令;线程私有;唯一一个没有规定任何OutOfMemoryError的内存区域。
虚拟机栈
线程私有,生命周期与线程相同;虚拟机栈描述的是java方法执行的内存模型:每个方法的执行对应着一个栈帧的建立,每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈上入栈到出栈,栈帧存储着局部变量表(也就是所谓的“栈”),操作数栈,动态链接,方法出口等信息; 内存大小可动态扩展;如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常,如果虚拟机栈动态扩展时无法申请到足够的内存空间,就会抛出OutOfMemoryError异常。
本地方法栈
与虚拟机栈相同,区别是虚拟机栈为java方法服务,本地方法栈为Native方法服务。
方法区
存储内容包括:运行时常量池,已加载类信息,常量,静态变量,即时编译器编译后的代码等;线程共享;在hotspot虚拟机上把方法区称为java堆的“永久代”;不需要连续的内存区域来存储,可以选择内存为固定大小或可扩展,可以选择不实现垃圾回收。
java堆
就是所谓的“堆”,所有的对象实例及数组都要在堆上分配内存;被所有线程共享;内存大小可固定也可扩展;如果在堆中没有内存完成实例分配且堆没有内存空间可扩展时,将抛出OutOfMemoryError异常。
好像太官方了。。。。如果结合java代码来讨论的话,大概就是这样子的:
对象本身(包括对象的成员变量)存储在java堆中;对象的类型信息,对象的常量成员变量,静态成员变量存储在方法区;而对象方法的执行对应栈帧在虚拟机栈中的入栈与出栈,方法中的局部变量的reference指针存储在栈帧中的局部变量表。