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的回收效率的目的。

阅读更多

JVM-018-运行时数据区-堆(Heap)-对象分配的过程

概述

为新对象分配内存是一件非常严谨和复杂的任务,JVM的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑GC执行完内存回收后是否会在内存空间中产生内存碎片。

阅读更多

JVM-017-运行时数据区-堆(Heap)-年轻代和老年代

定义

  • 存储在 JVM 中的 Java 对象可以被划分为两类:
    • 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速
    • 另外一类对象的生命周期却非常长,在某些极端的情况下还能与 JVM 的生命周期保持一致。
  • Java 堆区进一步细分的话:可以分为 年轻代(YoungGen)老年代(OldGen)
    • 其中年轻代又可以划分为:Eden(伊甸园)空间Survivor0(幸存者0)空间Survivor1(幸存者1)空间(有时也叫做 from区to区
阅读更多

JVM-015-运行时数据区-堆(Heap)-堆的核心概念

介绍

  • 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的核心区域。
  • Java 堆区在 JVM 启动的时候即被创建,其空间大小也就确定了。是 JVM 管理的最大一块内存空间。
    • 堆内存的大小是可以调节的。
  • 《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。
  • 所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)。
阅读更多