JVM-028-运行时数据区-直接内存(JDK8及以上)

概述

  • 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。

  • 直接内存是在Java堆外的、直接向系统申请的内存区间。

  • 来源于NIO(New IO / Non-Blocking IO),通过存在堆中的DirectByteBuffer操作Native内存

  • 通常,访问直接内存的速度会优于Java堆。即读写性能高。

    • 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。

    • Java的NIO库允许Java程序使用直接内存,用于数据缓冲区

阅读更多

JVM-027-运行时数据区-对象的实例化内存布局与访问定位

创建对象的方式

  1. new:最常见的方式、单例类中调用getInstance的静态类方法,XXXFactory的静态方法
  2. Class的newInstance方法:在JDK9里面被标记为过时的方法,因为只能调用空参构造器,并且权限必须为 public
  3. Constructor的newInstance(Xxxx):反射的方式,可以调用空参的,或者带参的构造器
  4. 使用clone():不调用任何的构造器,要求当前的类需要实现Cloneable接口中的clone方法
  5. 使用反序列化:从文件中,从网络中获取一个对象的二进制流,序列化一般用于Socket的网络传输
  6. 第三方库 Objenesis
阅读更多

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)-逃逸分析-代码优化

介绍

使用逃逸分析,编译器可以对代码做如下优化:

  1. 栈上分配:将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会发生逃逸,对象可能是栈上分配的候选,而不是堆上分配
  2. 同步省略:如果一个对象被发现只有一个线程被访问到,那么对于这个对象的操作可以不考虑同步。
  3. 分离对象或标量替换:有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。
阅读更多

JVM-019-运行时数据区-堆(Heap)-逃逸分析(Escape Analysis)

背景

堆是分配对象的唯一选择么?

  • 在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述:

    • 随着JIT(及时编译器)编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。
    • 在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无须进行垃圾回收了。这也是最常见的堆外存储技术。
  • 此外,基于OpenJDK深度定制的TaoBao VM,其中创新的GCIH(GC invisible heap)技术实现off-heap,将生命周期较长的Java对象从heap中移至heap外,并且GC不能管理GCIH内部的Java对象,以此达到降低GC的回收频率和提升GC的回收效率的目的。

阅读更多