JVM内存结构
2019-08-17 本文已影响0人
橙味菌
JAVA内存区域分布图
组成部分 | 作用 | 可能异常 | |
---|---|---|---|
程序计数器 | 指示线程执行的代码位置 存储行号指示器——指示当前线程执行的字节码的行号(如果不是Java方法则标为undefined) | 线程私有 | 无 |
虚拟机栈 | 虚拟机线程执行时的方法调用栈 | 线程私有,生命周期与线程相同 | StackOverFlowError(栈溢出)线程调用的栈深度大于虚拟机允许的最大深度 OutOfMemoryError(内存溢出)请求扩展栈容量时发现内存不足 |
本地方法栈 | Native方法使用的栈 在很多虚拟机中会将本地方法栈与虚拟机栈放在一起使用。 | ||
堆 | 存放对象实例 | 所有线程共享,占地最大 | OutOfMemoryError:Java heap space 垃圾回收之后,仍没有足够的内存分配,也不能再扩展时抛出 |
方法区 | 存放: 已经被虚拟机加载的类信息 编译器即时编译的代码。 运行时常量池 | OutOfMemoryError:PermGen space 在内存不足时抛出 | |
直接内存 | JVM以外的机器内存 存储由C语言实现的native函数库等 | OutOfMemoryError直接内存受到本机器内存的限制 |
栈帧结构
一个栈帧对应一个方法的一次调用,存放方法调用和执行信息的数据结构。
JVM栈帧结构存储:
-
局部变量表 存放方法参数和局部变量
-
操作数栈 方法执行使用的栈
操作数栈帧可指向
- 同虚拟机栈另一个虚拟机栈帧的方法返回地址
- 堆内存对象的成员变量
- 方法区的常量运行池的常量
-
动态链接 指向运行时常量池中该帧所属方法的引用
-
方法返回地址 调用者的PC计数器值/异常处理器表
-
附加信息
运行时常量池
用于存储编译期就生成的字面常量、符号引用、翻译出来的直接引用
DirectByteBuffer对象
-
没有DirectByteBuffer对象时,来回复制,开销巨大:当JVM需要调用外部内存的对象(Native对象)时,通常需要将外部内存的对象复制到JVM的堆内存中,调用完成又需要重新复制到外部内存覆盖原对象,
-
DirectByteBuffer对象,内存映射,零拷贝,开销小:DirectByteBuffer对象基于通道和缓冲区的内存分配方式,提供了直接操作外部内存的方法,避免了来回拷贝
DirectByteBuffer对象对于的外部内存只能由Cleaner对象回收(System.gc可触发)