①. 堆的概述
1>.
堆的概述(共享|垃圾回收)
-
①. 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域
-
②.
Java堆区在JVM启动的时候即被创建,其空间大小也是确定的。是Jvm管理最大的一块内存空间
-
③. 堆可以在物理上不连续的内存空间中,但在逻辑上是连续的
-
④.
所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)
-
⑤.
在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才有被移除 (注意:一个进程就是一个JVM实例,一个进程中包含多个线程)
②. 堆的内存结构
2>.
堆的内存结构
- ①. 现在垃圾收集器大部分都基于分带收集理论设计的,堆空间细分为:
- ②. jdk1.7 堆中的结构
- ③. jdk 1.8 堆中的结构
③. 堆空间大小的设置
3>.堆空间大小的设置
-
①. Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项"-Xmx 和 -Xms"来设置
-
②. -Xms(物理内存的1/64):表示堆区的起始内存,等价于-XX:InitialHeapSize
-
③. -Xmx(物理内存的1/4):则用于表示堆区的最大内存,等价于-XX:MaxHeapSize
-
④.
通常会将-Xms和-Xmx两个参数配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小,从而提升性能
-
案列演示
package com.xiaozhi.heap;
import java.util.concurrent.TimeUnit;
/**
* -Xms:600m
* -Xmx:600m
* 查看设置的参数:
* 方式一(cmd中):jps / jstat -gc 进程id
* 方式二(XX:+PrintGCDetails)
*/
public class HeapDemo1 {
public static void main(String[] args)throws Exception {
//返回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");
//TimeUnit.SECONDS.sleep(1000000);
}
}
④. 新生代与老年代参数设置
4>.新生代与老年代参数设置
-
①. 配置新生代与老年代在堆结构占比
默认:-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3
可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5
-
②. -XX:SurvivorRatio调整这个空间比例(Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1)
-
③. -Xmn:设置新生代最大内存大小
-
④. 几乎所有的Java对象都是在Eden区被new出来的,觉大部分的Java对象的销毁都在新生代进行的
⑤. 复制算法
5>.
复制算法重点
- ①. 一般过程(图解)
- ②. 过大对象
- ③. 复制算法详解
掌握
(伊甸园满了,就会触发gc(minor gc),而gc就会把标识为垃圾的对象干掉,不是垃圾的对象就要转移到幸存区,把伊甸园让出来给新的对象用)
过程:
⑥. Minor GC | Major GC | Full GC
6>.
Minor GC | Major GC | Full GC
- ①. YONG GC(minor GC):
- 只针对新生代区域的GC,指发生在新生代的垃圾收集动作,因为大多数Java对象存活率都不高,所以Minor GC非常频繁,一般回收速度也比较快
- 当Eden代满,会触发minor GC ,Survivor 满不会引发GC
- minor gc 会引发STW,暂停其他用户线程,等垃圾回收结束,用户线程才能恢复
- ②. Major GC:
- major GC 是回收老年代的垃圾;
- major gc 的速度一般比Minor gc 慢10倍以上,STW时间更长
- ③. Full GC:
- full GC 就会出现所谓的STW(stop the world)现象,即所有的进程都挂起等待清理垃圾
- full GC是回收老年代和年轻代的垃圾
- full gc 是开发调优中尽量避免的,这样暂时时间会短一些
- ④. 全局GC(major GC or Full GC):
(指发生在老年代的垃圾收集动作,出现了Major GC,经常会伴随至少一次的Minor GC(但并不是绝对的)。Major GC的速度一般要比Minor GC慢上10倍以上)
⑦. 针对不同年龄阶段的对象分配
7>.针对不同年龄阶段的对象分配原则如下所示:
⑧. TLAB(Thread Local Allocation Buffer)
8>.
TLAB(Thread Local Allocation Buffer) 掌握
-
①.
从内存模型而不是垃圾收集的角度,对Eden区域继续进行划分,JVM为每个线程分配了一个私有缓存区域,它包含在Eden空间内
-
②.
尽管不是所有的对象实例都能够在TLAB中成功分配内存,但JVM确实是将TLAB作为内存分配的首选
-
③. 默认情况下,TLAB空间的内存非常小,仅占有整个Eden空间的1%,当然可通过选项"-XX:TLABWasteTargePercent"设置TLAB空间所占用Eden空间的百分比大小
-
④. 一旦对象在TLAB空间分配内存失败时,JVM就会尝试着通过使用加锁机制确保数据操作的原子性,从而直接在Eden空间中分配内存
-
图解:
⑨. 堆空间参数总结
9>.
堆空间参数总结
-
①.
-XX:+PrintFlagsInitial :
查看所有的参数的默认初始值 -
②.
-XX:+PrintFlagsFinal :
查看所有的参数的最终值(可能会存在修改(:表示修改了),不再是初始值) -
③. 具体查看某个参数的指令:
(jps:查看当前运行中的进程
jinfo -flag SurvivorRatio 进程id) -
④.
-Xms
:初始堆空间内存 (默认为物理内存的1/64) -
⑤.
-Xmx
:最大堆空间内存(默认为物理内存的1/4) -
⑥. -Xmn:设置新生代的大小。(初始值及最大值)
-
⑦. -XX:NewRatio:配置新生代与老年代在堆结构的占比
(默认:-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3
可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5)
-
⑧. -XX:SurvivorRatio:设置新生代中Eden和S0/S1空间的比例
(Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1) -
⑨. -XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄
-
⑩.
-XX:+PrintGCDetails
:输出详细的GC处理日志
(如下这两种方式是简单的打印
打印gc简要信息:① -XX:+PrintGC ② -verbose:gc) -
⑩①. -XX:HandlePromotionFailure:是否设置空间分配担保
(JDK6之后,只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC)