您的位置:首页 > 编程语言 > Java开发

java内存区域

2015-10-15 14:40 471 查看
总述:

java虚拟机运行时数据区



一、程序计数器

如果线程正在运行的是一个java方法,则PC记录的是正在执行的字节码指令的地址。

如果线程正在运行的是一个Natvie方法,则PC为空。

此区域是java虚拟机中唯一一个没有规定任何OutOfMemory情况的区域。

二、java虚拟机栈

其生命周期与线程相同 ,描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)。

用于存储局部变量表,操作数栈,动态链接,方法的出口信息等。

每一个方法的调用直到执行完,对应一个 Stack Frame 在虚拟机栈中入栈 出栈的过程 。示意图职下



局部变量表存放的了编译期可知的各种基本类型(boolean ,byte ,char ,short, int ,float, long ,double),对象的引用(reference类型 ),returnAddress类型(指向了一条字节码指令的地址).

注意:reference类型,不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是一个指向指向对象的句柄

64位长度的long,double会占用2个局部变量空间的Slot,其它的只占用一个,局部变量表所要的内存空间在编期间完成分配,当进入一个方法时已经确定,在运行时不能改变局部变量表的大小。

VM Stack中的异常有StackOverFlow, OOM.

三、本地方法栈

与VM Stack相似,只是其为Native方法服务。

四、Java堆

是虚拟机内存管理的最大的一块,被所有线程共享,在虚拟机启动时创建。唯一的作用就是存放 对象的实例,所有的对象实例与数组都在堆上分配。

注意:随着JIT的发展与逃逸分析技术的成熟,栈上分配 ,标替换等优化技术也可能 使对象在VM stack上分配成为可能。

从内存回收的角度 ,目的是为了更好的回收内存:

现在收集器基本使用分代收集算法 ,所以 Java Heap可以分为 新生代,老年代。再细致可以分为,Eden, From Survivor, To Survivor.

从内存分配的角度,目的是为了更快的分配内存:

线程共享的Java Heap中可以分配出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)。

可以抛出异常为OOM.

五、方法区

线程共享 ,用于存放 已经被虚拟机加载的类信息,常量 ,静态变量,即时编译器编译后的代码等,

在HotSpot虚拟机中,常常称为永久代,本质上两者并不一样,只是HotSpot虚拟机中选择使用永久代的回收方法来实现方法区而已。现在看来,这并不是一个方法,因为容易出现OOM的问题(由于永久代的上限),在新的HotSpot中,可能会放弃这种做法 。

相对而言,回收在方法区还是很少发生的,其回收的主要目标是常量池的回收与类型的卸载,两者都比较复杂。

可以抛出的异常是OOM。

运行时常量池

方法区的一部分。Class文件中除了类的版本,字段,方法,接口等描述信息外,还有常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号的引用,将在类加载后进入方法区的运行时常量池中。

运行时常量池具备动态性,运行期间也可以将新的常量放入池中,这种特性使用多的就是String.intern()方法。

可以抛出的异常是OOM .

六、直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,但是也常常被使用,也可能会有OOM出现。在NIO中有使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: