JVM自动内存管理机制自动内存管理机制
Java自动内存管理机制包含两部分:内存分配和内存回收,要想理解内存分配和回收的机制,则需要了解下Java内存区域
(Java运行时数据区),这篇随笔将按照下面的线索进行逐步解析:
1.Java运行时数据区
2.对象“已死”的判定算法
3.垃圾收集算法
4.垃圾收集器
5.结束语
好,接下来我们一一来看。
一、Java运行时数据区
根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括如下几个运行时数据区域
程序计数器:用来记录当前线程所执行的字节码指令的行号指示器。字节码计时器需要通过改变改值来选取下一条需要执行的
字节码指定,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个指示器来完成。程序计数器是唯一一个没有
规定任何OutOfMemoryError情况的区域。
Java虚拟机栈:虚拟机栈描述的是Java方法执行的内存模型,每个方法执行时都会创建一个栈帧用来存储局部变量表(存放
编译器可知的各种基本数据类型、对象引用和returnAddress类型,所需的内存空间在编译器完成分配)、操作数栈、动态链
接、方法出口等信息。Java虚拟机栈有两种异常情况:OutOfMemoryError(扩展时无法申请到足够内存)和
StackOverflowError(线程请求的栈深度大于虚拟机所允许的深度)。
本地方法栈:同Java虚拟机栈类似,只不过Java虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用Native方法
服务。HotSpot直接将两个栈合二为一。也规定了两种异常:OutOfMemoryError和StackOverflowError。
堆:JVM所管理的内存中最大的一块,也是GC管理的主要区域。理论上所有的对象实例和数组都要在堆上分配。堆的大小是
可以扩展的,通过-Xms和-Xms控制,并且堆无法扩展的时候就会报OutOfMemoryError异常。
方法区:用来存储JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描
述为堆的一个逻辑部分,但是为了和堆区分开来,它也叫Non-Heap(非堆)。方法区无法满足内存分配需求时,报
OutOfMemoryError异常。
直接内存:并不是虚拟机运行时数据区的一部分,也不是JVM规范中定义的内存区域,但是却被经常使用。JDK1.4中新加入
的NIO类,引入了基于通道和缓冲区的I/O方式,他可以直接分配对外内存,以提高性能。不收堆大小的限制,但是会受物理
内存的约束。也会报OutOfMemoryError异常。
附栈到堆的关联例子(基于HotSpot):