08-堆(一)

简介: 08-堆(一)

1 堆(Heap)的核心概述


网络异常,图片无法展示
|


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


堆空间演示例子:

public class HeapDemo {
  // 设置堆内存空间-Xms10m -Xmx10m
  public static void main(String[] args) {
    System.out.println("start...");
    try {
      Thread.sleep(10000000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("end....");
  }
}


启动程序后,使用Java VisualVm工具查看


打开方式: win+R -> 输入cmd -> jvisualvm回车


打开VisualGC(安装方式:工具-> visual GC 安装,然后重启工具)


可以看到 Eden Space 2M + Survivor 0 512k + Survivor 1 512k + Old Gen 7M 加起来总共10M


网络异常,图片无法展示
|


  • 《Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都应该在运行时分配在堆上。(The heap is the run-time data area from which memory for all class instances and arrays is allocated)
  • “几乎“所有的对象实例都在这里分配内存。——从实际使用角度来看。
  • 数组和对象可能永远不会存在栈上,因为栈帧中保存引用,这个引用指向对象或者数组在堆中的位置。
  • 在方法结束后,堆中的对象不会马上被移出,仅仅在垃圾收集的时候才会被移出。
  • 堆,是GC(Garbahe Collection, 垃圾收集器)执行垃圾回收的重点区域。


网络异常,图片无法展示
|


堆的核心概述:内存细分


现代垃圾收集器大部分都是基于分代收集理论设计,堆空间细分为:


  • Java 7及之前堆内存逻辑上分为三部分:新生区+养老区+永久区
  • Young Generation Space   新生区    Young/New
  • 又被划分为Eden区和Survivor区
  • Tenure generation space   养老区   Old/Tenure
  • Permanent Space                永久区    Perm
  • Java 8及之后堆内存逻辑上分为三部分: 新生区 + 养老区 + 元空间
  • Young Generation Space      新生区   Young/New
  • 又被划分为Eden区和Survivor区
  • Tenure generation space     养老区    Old/Tenure
  • Meta Space                             元空间    Meta


约定:新生区<=>新生代<=>年轻代   养老区<=>老年区<=>老年代    永久区<=>永久代


堆空间内部结构(JDK 7)


网络异常,图片无法展示
|


堆空间内部结构


网络异常,图片无法展示
|


2 设置堆空间内存大小与OOM


堆空间大小的设置


  • Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项“-Xmx"和”Xms"来进行设置。
  • ”-Xms"用于表示堆区的起始内存,等价于-XX:InitialHeapSize
  • "-Xmx"用于表示堆区的最大内存,等价于-XX:MaxHeapSize
  • 一旦堆区中的内存大小超过“-Xmx”所指定的最大内存时,将会抛出OutOfMemoryError异常。
  • 通常会将 -Xmx 和 -Xmx 两个参数配置相同的值,其目的是为了能够在Java垃圾回收机制清理完堆区后不需要重新分割计算堆区的大小,从而提高性能。
  • 默认情况下,初始内存大小:物理电脑内存大小/64, 最大内存大小:物理电脑内存大小/4


-X 是jvm的运行参数 ms 是memory start


使用默认堆内存大小,代码示例:


public class HeapSpaceInitial {
  public static void main(String[] args) {
    // 返回java虚拟机中堆内存总量
    long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
    // 返回Java虚拟机试图使用的最大堆内存两
    long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
    System.out.println("-Xms:" + initialMemory + "M");
    System.out.println("-Xmx:" + maxMemory + "M");
    System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");
    System.out.println("系统内存大小为:" + maxMemory * 4.0 / 1024 + "G");
  }
}

结果


-Xms:491M
-Xmx:7257M
系统内存大小为:30.6875G
系统内存大小为:28.34765625G

设置JVM参数为:-Xms600m -Xms600m


// 返回java虚拟机中堆内存总量
long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
// 返回Java虚拟机试图使用的最大堆内存两
long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
Thread.sleep(10000000);

查看堆内存大小,发现只有575M:

-Xms:575M
-Xmx:575M

使用jsp 和 jstat -gc 进程号 查看具体信息


网络异常,图片无法展示
|


结论:少的那25M为s0 或者s1


或者使用 -XX:+PrintGCDetails参数查看


OutOfMemory举例


         

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Picture.(OOMTest.java:24)
at OOMTest.main(OOMTest.java:16)


Java VisualVM的界面展示


网络异常,图片无法展示
|


3 年轻代与老年代


年轻代与老年代


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


网络异常,图片无法展示
|


下面这参数开发中一般不会调:


网络异常,图片无法展示
|


  • 配置新生代与老年代在堆结构的占比。
  • 默认-XX:NewRatio=2(默认值), 表示新生代占1,老年代占2,新生代占整个堆的1/2
  • 可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5


查看方式:


jinfo -flag NewRatio 进程号


  • 在HotSpot中,Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1
  • 当然开发人员可以通过选项:“-XX:SurvivorRatio"调整这个空间比例。比如-XX:SurvivorRatio=8
  • 几乎所有的Java对象都是在Eden区被new出来的
  • 绝大部分的Java对象的销毁都在新生代进行了。
  • IBM公司的专门研究表名,新生代中80%的对象都是“朝生夕死”的
  • 可以使用选项“-Xmn”设置新生代最大内存大小 (一般不设置,权限比比例设置大)
  • 这个参数一般使用默认值就可以了。


-XX: -UseAdaptiveSizePolicy  关闭自适应的内存分配策略


网络异常,图片无法展示
|


目录
相关文章
|
7月前
|
存储 算法 索引
堆的实现(C版)
堆的实现(C版)
26 0
|
5天前
|
存储 程序员
什么是堆,什么是栈
什么是堆,什么是栈
6 0
|
4月前
|
存储 缓存 JavaScript
|
9月前
|
算法
堆的实现以及应用
我们说堆在物理上是一个数组,逻辑上它是一个完全二叉树,我们可以通过它的下标来计算父亲和孩子之间的关系。
堆(什么是堆以及怎样自己创建堆)
堆(什么是堆以及怎样自己创建堆)
|
存储 缓存 Oracle
08-堆(三)
08-堆(三)
62 0
|
存储 缓存 算法
08-堆(二)
08-堆(二)
111 0