28.JVM运行时数据区之堆区概述

 

1.堆(Heap)核心概述

堆是JVM运行时数据区中的重点内容。
1.堆区是进程私有的。一个进程对应一个JVM实例。一个JVM实例中有一个Runtime实例(Runtime实例对应的就是运行时数据区),里面包含了运行数数据区的各个部分(堆区、方法区、虚拟机栈、程序计数器、本地方法栈)。一个JVM实例都有自己的一个堆区。
2.一个进程包含多个线程,线程共享了堆区和方法区,同时各个线程拥有自己的虚拟机栈,本地方法栈,程序计数器。
3.堆区在JVM启动的时候被创建。
4.堆区的大小可以被调节。
5.堆区被所有的线程共享。还可以划分出线程私有的缓存区(Thread Local Allocation Buffer, TLAB)
在这里插入图片描述
6.几乎所有的对象实例以及数组都是在堆上分配的空间。之所以是几乎,是因为存在栈上分配的情况(后面的博客会讲到)。
7.数组和对象可能永远不会存储在栈上,栈帧中保存的是引用(局部变量表中存放的引用),这个引用指向的是对象或者数组在堆中的位置。
8.在方法结束执行之后,堆中的对象不会被立即被移除,需要等待垃圾回收器来回收。
9.堆是GC的重点区域。
在这里插入图片描述

2.堆与栈、方法区之间的关系

public class SimpleHeap {
    private int id;//属性、成员变量
    public SimpleHeap(int id) {
        this.id = id;
    }
    public void show() {
        System.out.println("My ID is " + id);
    }
    public static void main(String[] args) {
        SimpleHeap sl = new SimpleHeap(1);
        SimpleHeap s2 = new SimpleHeap(2);
       // int[] arr = new int[10];
       //Object[] arr1 = new Object[10];
    }
}

上面的java代码,在堆空间中创建了两个对象s1s2
1.Java栈的栈帧中的成员变量表存储着s1s2这两个实例的引用。
2.堆区存储着s1s2对象的实例。
3.方法区中有着关于堆区中s1s2实例的类SimpleHeap的相关信息以及方法的实现。
在这里插入图片描述

3.堆的内存细分

1.现代垃圾收集器大部分都是基于分代收集理论设计。
2.在Java7及之前堆内存逻辑上分为三部分:新生代+老年代+永久区。事实上堆空间不包括永久代。
3.在Java8及之前堆内存逻辑上分为三部分:新生代+老年代+元空间。事实上堆空间不包括元空间。
约定:新生区=新生代=年轻代;养老区=老年区=老年代;永久区=永久代。
在这里插入图片描述
4.JDK7及以前堆空间内部结构:
Java7及之前堆内存逻辑上分为三部分:年轻代+老年代+永久区。事实上堆空间不包括永久代,它是属于方法区的具体实现。
也就是说堆空间实际上只包含新生代和老年代两个部分。
在这里插入图片描述
JDK8及以后堆空间内部结构:
Java8及之前堆内存逻辑上分为三部分:年轻代+老年代+元空间。事实上堆空间不包括元空间,它是属于方法区的具体实现。
也就是说堆空间实际上只包含新生代和老年代两个部分。
5.堆空间内部结构
a)在Java8之前,堆空间逻辑上划分为新生代(New Gen)、老年代(Old Gen)和永久代(Perm Gen)
b)在Java8及之后,堆空间逻辑上划分为新生代(New Gen)、老年代(Old Gen)和元空间(Metaspace)。永久代变成了元空间。
c)其中新生代又划分为伊甸园区(Eden)和生存区(Survicor)
在这里插入图片描述

posted @ 2020-11-18 11:14  跃小云  阅读(137)  评论(0编辑  收藏  举报