Java内存管理

为什么要了解Java内存管理?

虽然Java是自动内存分配,但是一旦出现内存泄露和溢出方面的问题,排查错误时还需要懂虚拟机是如何使用内存的。

1. 运行时数据区域

1.1 程序计数器

每个线程都有一个独立的程序计数器 (线程私有),记录线程正在执行的虚拟机字节码的地址。

程序计数器是Java虚拟机中唯一一个没有规定任何OutOfMemoryError的区域。

1.2 Java虚拟机栈

Java虚拟机栈也是线程私有,生命周期与线程相同。

每个方法被执行的时候都会同时创建一个栈帧 (Stack Frame) 用于存储局部变量表、操作栈、动态链接、方法出口等信息。

每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

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

如果线程的请求深度大于虚拟机允许的深度,将会抛出StackOverflowError异常。

如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。

1.3 本地方法栈

本地方法栈 (Native Method Stacks) 与虚拟机栈发挥的作用极其相似,虚拟机栈为Java方法服务,而本地方法栈为Native方法服务。

本地方法栈会抛出StackOverflowError和OutOfMemoryError异常。

1.4 Java堆

Java堆是最大的一块,Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。

此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这了分配内存。

Java堆是垃圾收集器管理的主要区域,因此也被称为“GC堆" (Garbage Collected Heap) 。

Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

1.5 方法区

方法区 (Method Area) 也是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

虽然Java虚拟机桂法把方法区描述为堆的一个逻辑部分,但它有一个别名叫做Non-Heap。

当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

1.6 运行时常量池

1.7 直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。

但这部分内存也被频繁使用,而且也可能导致OutOfMemoryError异常出现。 

 

posted on 2016-02-25 22:45  lima  阅读(333)  评论(0编辑  收藏  举报

导航