-
程序计数器: 没有OOM, 线程私有, 线程间互不干扰, 用来指示线程执行指令地址的. Native方法没有计数器值.
-
虚拟机栈: 线程私有, 生命周期同线程, 方法在执行的时候会创建一个栈帧用来存局部变量, 动态链接, 方法出口等信息. 一个方法从调用到执行完毕, 对应着一个栈帧从入栈到出栈. 通常被称为”栈内存”.
当线程请求的栈深度大于虚拟机所允许的深度, 抛出
StackOverflowError
. -
如果虚拟机栈可以动态扩展(Java可以动态扩展也可以固定长度), 在扩展时若无法申请到足够内存则抛出OutOfMemoryError.
-
本地方法栈: 作用类似虚拟机栈, 不过本地方法栈执行Native方法. 也会有
StackOverflowError
和OutOfMemoryError
出现. -
方法区: 线程共享, 存储类的信息、常量池、方法数据、方法代码(编译器编码后的)等.”
java.lang.OutOfMemoryError: PermGen space
“就是指的方法区. -
堆: 内存最大, 线程共享, 在虚拟机启动时创建. 用作存放对象实例, 也是GC的主要区域.细分为新生代和老年代.
-
永久代(即方法区): 1.8之后永久代转换成了元空间(
Metaspace
), 且PermSize
和MaxPermSize
会被忽略并给出警告.在1.7中开始移除, 但未完全移除.其中原因可能有:
字符串在永久代中不利于GC, 容易出现性能问题和内存溢出.
类和方法的信息比较难确定大小, 所以永久带不好指定大小, 大了老年代溢出, 小了永久代溢出
-
元空间: 元空间内存储的类元数据的生命周期等于该类的类加载器生命周期, 不再单独回收某各类, 且对象的位置是固定的, 当类加载器不再存活, 被gc声明死亡后, 该类加载器对应的空间就会被回收.
元空间使用
-XX:MinMetaspaceFreeRatio
和-XX:MaxMetaspaceFreeRatio
进行调节. -
常量池: 方法区的一部分. 用于存放编译期和运行时生成的各种字面量和符号引用. 比如String类的intern方法
-
直接内存: 也就是堆外内存, NIO可以通过Native函数直接分配, 通过在堆中的
DirectByteBuffer
作为引用进行操作. 注意内存泄漏导致的OOM.
Q.E.D.
Comments | 0 条评论