堆(未完待续)

116 阅读2分钟

2.4 堆

image-20210304195236205

对一个进程而言,堆和方法区都是唯一的。在这个进程里面的线程是共享堆和方法区的。对于一个线程而言,程序计数器、虚拟机栈和本地方法栈是不共享的。

堆是java内存管理的核心区域,在JVM启动的时候就被创建,其空间大小也确定了。是JVM最大的一块内存空间,在物理上不连续的内存空间,在逻辑上是连续的。堆内存是可以调节的(-Xmx(堆空间最大内存)和-Xms(堆区起始内存))。

  • 所有对象实例及数组都应当在运行时分配在堆上。
  • 数组和对象可能永远不会存储在栈上,因为栈帧存储引用,这个引用指向对象或者数组在堆中的位置。
  • 在方法结束后,堆中对象不会马上被移除,只有在垃圾收集的时候才会被移除
  • 堆是GC(垃圾收集器)执行垃圾回收的重点区域。

内存细分

现代垃圾收集器大部分都基于分代收集理论设计

Java7之前:新生区+老年区+永久区

java8之后:新生代 +老年代+元空间

堆空间大小设置

  • -Xms:设置堆空间起始大小
    • -X:jvm运行参数
    • ms:memory start
  • -Xmx:设置堆空间最大内存

一旦堆空间中内存大小超过 -Xmx所指定的最大内存时,会抛出OOM异常。

通常设置 -Xms-Xmx两个参数配置相同的值,目的是能够在java垃圾回收机制清理完堆内存后不需要重新分隔计算堆区大小从而提高性能

默认情况:起始内存大小:物理内存/64,最大内存大小:物理内存/4

新生代和老年代

存储在JVM中的java对象有两类:

  • 生命周期较短的瞬时对象
  • 生命周期较长的,极端点可以和JVM的生命周期保持一致

image-20210304210556029

配置新生代与老年代在堆中占比:(一般不修改参数)

  • 默认: -XX:NewRatio=2表示新生代占1 (1/3),老年代占2。
  • 可以修改 -XXwRatio=4表示新生代占1 (1/5) 老年代占4

image-20210304211630978

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

-XX:SurvivorRatio=8:伊甸园区:幸存者0区:幸存者1区=8:1:1

  • 几乎所有的对象都是在伊甸园区被new出来的

  • 绝大部分对象都被销毁在新生代(80%)

使用 -Xmn:设置新生代最大内存大小(一般使用默认值)(与上面冲突了,以这个为准)

对象分配的一般过程

image-20210304220112007

重点:

  • 幸运者0区(s0)和幸运者1区(s1):复制之后有交换,谁空谁为to
  • 关于垃圾回收:频繁在新生代收集,很少在老年代收集,几乎不在元空间收集。

image-20210304222455993