0
点赞
收藏
分享

微信扫一扫

JVM 堆内存模型

堆内存模型

JVM 将对象存放在堆内存中,堆内存所需要的空间是比较大的。我们对于 JVM 的调优

也主要是针对堆内存的调优,比如分配堆内存的空间,那么我们如何能确定堆内存需要分配

多少空间呢?我们需要大概计算每个对象所占的空间大小。

1 JAVA 对象内存布局

JVM 堆内存模型_堆内存

JAVA 对象在内存中主要有以下几部分:

对象头

MarkWord:一系列标记位(哈希码、分代年龄、锁状态标记等),在 64 位系统中占

8 字节。

ClassPoint:对象对应的类信息的内存地址,在 64 位系统中占 8 字节。

Length:数组对象特有,表示数组长度,占 4 字节。

实例数据

包含了对象的所有成员变量,大小由变量类型决定。

byte、boolean:1 字节

short:2 字节

char:2~3 字节

int、float:4 字节

long、double、引用数据类型:8 字节

对其填充

将对象大小填充为 8 字节的整数倍

12

2 JVM 内存溢出和垃圾回收机制

为什么要进行垃圾回收:

如果对象只创建不回收,会造成堆内存溢出(OOM)异常。

为什么要进行堆内存分区:

\1. 提高搜索垃圾的效率。

\2. 垃圾回收后可以更好的利用内存空间,存放大对象。

\3. 尽可能减少 GC 次数

3 JVM 堆内存的划分

老年代:

对象会优先分配到新生代内存中,每次 GC 后没有回收的对象年龄加 1,年龄到

15 还没有被回收,对象会存放到老年代内存中;如果对象较大,超过新生代内存的一

半,对象也会存放到老年代区域

新生代:

为了减少young区垃圾回收后的空间碎片,新生代又分为Eden区和两个Survivor

区,且始终有一个 Suvivor 区保持闲置。对象会先存放到 Eden 区当中,Eden 区空间

满了之后会进行 young 区的垃圾回收,之后将 young 区所有存活的对象复制到闲置

的 Suvivor 区中,并清空 Eden 区和正在使用的 Survivor 区。

JVM 堆内存模型_堆内存_02

4 YoungGC 和 OldGC

YoungGC

新生代区域的垃圾回收称之为 YoungGC,也叫 MinorGC,Eden 区满后会触发

YoungGC

OldGC

老年代区域的垃圾回收称之为 OldGC,也叫 MajorGC,OldGC 非常浪费性能,

所以我们的 JVM 调优要尽可能减少 OldGC 的次数, OldGC 往往伴随着 YoungGC。

YoungGC+OldGC = FullGC

1. Survivor 区空间并不大,如果满了怎么办?

(1)一般情况下 GC 会回收 95%的对象,且超过 15 次 GC 的对象会存放到 old

去,所以 Survivor 区不容易满。

(2)如果 Survivor 区满了,会触发担保机制,提前将对象存入 Old 区。

2. 为什么需要 Survivor 区?

为了减少垃圾回收带来的空间碎片,空间碎片过多会频繁触发 YoungGC。

3. 为什么需要两块 Survivor 区?

为了减少 Survivor 区的空间碎片

5 JVM 运行监控工具 VisualVM

打开 JAVA 安装目录/bin/jvisualvm.exe

JVM 堆内存模型_垃圾回收_03

JVM 堆内存模型_老年代_04

安装 VisualGC 插件。

JVM 堆内存模型_老年代_05

注:JDK9 之后需自行下载该工具

修改堆内存大小的指令

-Xms10M -Xmx10M :对象比较消耗内存,一般占用电脑本机内存1/4,如16G内存,占用4G,修改有助于明显查看

(springboot版本修改堆内存)

JVM 堆内存模型_垃圾回收_06

(一般项目版本修改堆内存)

JVM 堆内存模型_堆内存_07

5.1实体类



/**
* @Author yqq
* @Date 2021/5/20 21:53
* @Version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;

private String sex;

private Integer age;
}


5.2 测试类



/**
* @Author yqq
* @Date 2021/5/20 21:55
* @Version 1.0
*/
public class TestGC {
public static void main(String[] args) throws Exception{
List<Student> studentList=new ArrayList<>();
while (true){
/**
* 对象比较消耗内存,一般占用电脑本机内存1/4,如16G内存,占用4G
*/
studentList.add(new Student());
studentList.add(new Student());
studentList.add(new Student());
studentList.add(new Student());
studentList.add(new Student());
studentList.add(new Student());
Thread.sleep(1);
}
}
}

监测创建Student对象堆内存详情

JVM 堆内存模型_老年代_08

由于创建对象过快,当Eden来不及回收对象时导致内存溢满报异常

JVM 堆内存模型_老年代_09


举报

相关推荐

0 条评论