JVM所管理的内存包括几个运行时数据区域:
2虚拟机栈(VM stack):也是线程私有的,生命周期与线程相同。每个方法被执行时都会同时创建一个栈帧(stack frame)用于存储局部变量表、操作栈、动态链接、方法出口等。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在vm stack中从入栈到出栈的过程。
局部变量表存放了编译期可知的基本类型,对象引用和returnAddress类型。局部变量表所需的内存空间在编译期间完成分配,某个方法需要在帧中分配多大的局部变量是完全确定的,在方法运行时不会改变局部变量表的大小。
该区域两种异常状况:1线程请求的栈深度大于vm所允许的深度,抛出StackOverflowError 2当扩展时无法申请到足够的内存时,抛出outOfMemoryError
3本地方法栈(native method stack):与vm stack相似,是为native调用服务,也可抛出stackOverflowError和outofmemoryError
4堆(heap):jvm所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在vm启动时创建,唯一目的存放对象实例。几乎多有的对象实例以及数组都要在heap上分配。Heap是gc管理的主要区域。可处于物理上不连续的内存空间,只要逻辑上连续即可。如果heap中没有内存完成实例分配,并且无法再扩展时,抛出outofmemeoryError
5方法区(method area,别名Non-Heap):于heap一样,各个线程共享内存区域,用于存储已被vm加载的类信息、常量、静态变量、即时编译器编译后的代码等。gc行为在这个区域比较少出现,gc的目标主要是针对常量池和对类型的卸载,一般来说回收的成绩难以令人满意。当方法无法满足内存分配时,抛出outofmemoryError
运行时常量池(runtime constant pool)是方法区的一部分。class文件中除了有类的版本、字段、方法、接口等外,还有一项是常量池(constant pool table),用于存放编译期生成的字面量和符号引用,这会在类加载后存放到运行时常量池中。
直接内存(direct memory)并不是vm运行时数据区的一部分,也不是jvm规范中定义的内存区域,但也被频繁使用,也可导致outofmemoryError。
对象访问:
即时最简单的访问,也会牵涉stack,heap,方法区之间的关系
Object obj = new Object();"Object obj"将会反映到stack的局部变量表中,作为一个reference类型出现,“new Obejct()”反映到heap中,形成一块存储了Object类型所有实例数据值的结构化内存。另外,在heap中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则放在方。法区中。
不同vm实现对象访问方式不同,主流两种:句柄访问和直接指针。P31图。
句柄访问最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只需改变句柄中的实例数据指针,而reference不需改变。
直接指针访问最大好处是速度更快,节省指针定位的时间开销,但需改变reference。
如若转载,请说明出处!http://blog.csdn.net/xukunddp