概述
不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
直接内存是在Java堆外的、直接向系统申请的内存区间。
来源于NIO(New IO / Non-Blocking IO),通过存在堆中的DirectByteBuffer操作Native内存
通常,访问直接内存的速度会优于Java堆。即读写性能高。
因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
直接内存是在Java堆外的、直接向系统申请的内存区间。
来源于NIO(New IO / Non-Blocking IO),通过存在堆中的DirectByteBuffer操作Native内存
通常,访问直接内存的速度会优于Java堆。即读写性能高。
因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
JVM-027-运行时数据区-对象的实例化内存布局与访问定位
JVM-025-运行时数据区-方法区(Method Area)-垃圾回收
有些人认为方法区(如Hotspot虚拟机中的元空间或者永久代)是没有垃圾收集行为的,其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的,提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在(如JDK11时期的ZGC收集器就不支持类卸载)。
一般来说这个区域的回收效果比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。
方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不再使用的类型(即:运行时常量池和类信息)。
JVM-024-运行时数据区-方法区(Method Area)-方法区的演进细节
首先明确:只有Hotspot才有永久代。
BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,并不要求统一
Hotspot中方法区的变化:
版本 | 说明 |
---|---|
JDK1.6及以前 | 有永久代(permanent generation),字符串常量池(StringTable)和静态变量存储在永久代上 |
JDK1.7 | 有永久代,但已经逐步 “去永久代”,字符串常量池(StringTable)和静态变量移动保存在堆中 |
JDK1.8 | 无永久代,类型信息,字段,方法,常量保存在本地内存的元空间,但字符串常量池(StringTable)和静态变量仍然在堆中。 |
JVM-020-运行时数据区-堆(Heap)-逃逸分析-代码优化
使用逃逸分析,编译器可以对代码做如下优化:
JVM-019-运行时数据区-堆(Heap)-逃逸分析(Escape Analysis)
堆是分配对象的唯一选择么?
在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述:
此外,基于OpenJDK深度定制的TaoBao VM,其中创新的GCIH(GC invisible heap)技术实现off-heap,将生命周期较长的Java对象从heap中移至heap外,并且GC不能管理GCIH内部的Java对象,以此达到降低GC的回收频率和提升GC的回收效率的目的。