Java内存区域

来源:互联网 发布:atmega dip封装单片机 编辑:程序博客网 时间:2024/06/05 10:43

欢迎访问配色更好看的个人站

《深入理解Java虚拟机》第二章

Java虚拟机在运行时会把它所管理的内存划分为若干个区域。

程序计数器

  • 较小的内存空间
  • 线程隔离、私有
  • 不存在OutOfMemoryError情况

字节码解释器工作时通过改变计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常、线程恢复等基础功能都需要依赖这个计数器完成。

虚拟机栈

  • 存储:方法运行时的东西
  • 线程隔离、私有

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

局部变量表 存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference),其中64位长度的long和double会占用2个局部变量空间(slot),其余的数据类型只占用1个。在方法运行期间不会改变局部变量表的大小。

线程请求的栈深超过虚拟机的限制,会抛出 StackOverflowError 异常

虚拟机栈动态扩展时内存不足,会抛出 OutOfMemoryError 异常

本地方法栈

类似 虚拟机栈 ,为 Native 方法服务。 有的虚拟机中会把 本地方法栈虚拟机栈 合二为一。

Java 堆

  • 存储:对象实例
  • 线程共享
  • 虚拟机中最大的一块
  • GC的主要区域,又称作“GC堆”

由于现在垃圾收集器基本都采用分代收集算法,所以 Java堆 还可以细分为: 新生代和老年代;再细致一点有 Eden空间、 From Survivor空间、 To Survivor空间等。

线程可能会在 Java堆 上划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB),用于减少多线程并发分配内存时的资源冲突。

在实例分配时缺少内存,会抛出 OutOfMemoryError 异常。

方法区

  • 存储:类型信息、常量等
  • 线程共享

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

习惯使用HotSpot的开发,更愿意把 方法区 称为 “永久代”,本质上两者并不等价。

运行时常量池

运行时常量池是方法区的一部分。用于存放编译期生成的各种字面量和符号引用以及翻译出来的直接引用。

在编译期外也有方式可以进入常量池,常见的有 String.intern().

直接内存

  • 不属于虚拟机运行时数据

直接内存(Direct Memory)不属于虚拟机运行时数据区的一部分,也不是java虚拟机规范定义的内存区域。JDK1.4引入NIO类,可以使用 Native 函数库直接分配堆外内存然后通过 DirectByteBuffer 对象作为这块内存的引用进行操作,避免在Java堆和Native堆中来回复制数据。

本机直接内存分配不会受到Java堆大小的限制,但受到本机总内存的限制。忽略它,常容易产生 OutOfMemoryError

原创粉丝点击