第2章 Java内存区域与内存溢出异常

来源:互联网 发布:离散数学 编程 编辑:程序博客网 时间:2024/04/30 12:34
运行时数据区域(虚拟机内存模型)



线程共享区域:
堆和方法区

线程私有区域:
程序计数器,虚拟机栈,本地方法栈

生命周期:
线程共享区域生命周期跟虚拟机一样,伴随虚拟机的启动而存在;
线程私有区域生命周期跟线程一样,伴随线程的启动和结束而建立和销毁。

1. 程序计数器
每个线程都有一个程序计数器,用来记录当前线程执行的字节码的行号。
当切换到不同线程时,根据程序计数器确定下一条需要执行的字节码指令。
没有规定任何内存溢出错误

2. 虚拟机栈(存放局部变量)
描述Java方法执行的内存模型:每个方法被执行时都会创建一个栈帧,用于存储局部变量表、操作栈等信息。
每个方法被调用直至执行完成的过程,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表存放基本数据类型和对象的引用,局部变量表所需的内存空间在编译期间完成分配
规定了两种异常情况:
StackOverflowError:线程请求的栈深度大于虚拟机允许的深度,会抛出StackOverflowError异常
OutOfMemoryError:动态扩展虚拟机栈时,当扩展时无法申请到足够的内存时,会抛出OutOfMemoryError异常

3. 本地方法栈
与虚拟机栈发挥的作用类似,区别是虚拟机栈为Java方法服务,本地方法栈为Native方法服务
与虚拟机栈一样,本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常

4. Java堆
主要用来为对象分配内存以及存放对象,几乎所有的对象都在这里分配内存
Java堆是垃圾收集器管理的主要区域,因此也被称为GC堆
物理上可以不连续,逻辑上连续即可
堆中内存不够时会抛出OutOfMemoryError异常

5. 方法区
主要用于存放类、常量、静态变量(除了局部变量放在虚拟机栈),属于堆的一部分
方法区的内存回收主要针对常量池的回收和类型卸载
对这个区域的限制非常宽松,虚拟机的内存泄露主要出现在方法区
内存不够时会抛出OutOfMemoryError异常

6. 常量池
属于方法区的一部分

7. 直接内存
NIO类会在堆外分配本机内存,在堆内引用堆外内存
因此本机在分配虚拟机内存时要考虑到直接内存,预留一部分本机内存用于直接内存

内存溢出异常总结:
程序计数器没有规定任何内存溢出错误
虚拟机栈和本地方法栈会抛出StackOverflowError和OutOfMemoryError异常
堆和方法区只抛出OutOfMemoryError异常
0 0