java虚拟机内存区域图例如下:
根据图示可以知道,java虚拟机内存区域可以分为线程共享和独有两大部分,现就各模块介绍如下:
java堆
该区域为所有线程共享,也是最大的一块内存区域,通常也是GC(垃圾回收)区域,因此也被成为“GC堆”。该区域主要存储对象实例以及数组实例。为对象划分内存通常有两种方法:指针碰撞和采用空闲列表,具体采用哪种取决于垃圾收集器是否带有压缩整理功能。另外还要考虑线程安全性,比如同时申请了两个对象内存时要避免冲突。解决这个问题有两个方案,一种是对分配内存空间的动作进行同步处理;另一种是给每个线程预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer ,TLAB)。当分配对象内存时,先使用自己的TLAB,当用完的时候才需要同步锁定去分配新的内存。
方法区
方法区(有些人称为“永久代”)主要存储被虚拟机加载的类信息、常量、静态变量、以及编译后的代码等数据。另外需要注意的是“运行时常量池”也在其中。Class文件中除了有类的版本、字段、方法、接口外,还有一项信息是常量池,用于存储编译器生成的各种字面值和符号引用,这类数据当类被加载时存入“运行时常量池”。运行时常量池具有动态性,也就是程序运行期间依然可以进入常量池。
这里补充一点String类的intern方法的介绍:参见http://www.cnblogs.com/wanlipeng/archive/2010/10/21/1857513.html
虚拟机栈
此区域属于单个线程独有,他描述了java方法的运行模型。每个方法运行前都会创建一个栈帧(statck frame),栈帧包括局部变量表(存储方法参数及方法类定义的变量。第一个Slot(最小单位)存所属对象实例,即this)、动态链接(部分符号引用在类加载阶段或者第一次使用的时候就转化为直接引用,这种转化称为静态解析。另外一部分将在第一次运行期间转化为直接引用,成为动态链接)、方法出口、操作数栈(计算过程中存储中间结果)等信息。每个方法的执行和结束就对应一个栈帧在虚拟机栈中进入和弹出的过程。
局部变量表信息存放了编译期就可知的基本数据类型、对象引用(reference类型,可能是一个指向对象的指针或者句柄)和一个returnAddress类型(指向了一条字节码指令的地址)。其中long/double类型是64位,占2个局部变量空间。局部变量表在编译期就确定,方法执行期间不会改变大小。
此处添加引用的介绍:参见http://blog.sina.com.cn/s/blog_4cd5d2bb0100ve9r.html
本地方法栈
跟虚拟机栈类似,只不过它对应于虚拟机执行本地方法(native方法,可以是用c/c++等其他语法编写)。
程序计数器
当线程执行java方法时,程序计数器记录正在执行的虚拟机字节码指令的地址。若线程执行native方法,该值为空(undefined)。