在上一章中我们介绍了JVM运行时参数以及jstat指令相关内容:[JVM教程与调优] 什么是JVM运行时参数?。下面我们来介绍一下jmap+MAT内存溢出。
首先我们来介绍一下下JVM的内存结构。
JVM内存结构介绍
从图中我们可以看到,JVM
的内存结构分为两大块。一块叫堆区,一块叫非堆区。
堆区又分为两大块,一块Young,一块叫Old。Young区又分为Survivor区和Eden区。Survivor区我们又分为S0与S1。可以结合下图进行理解
非堆区呢,是属于我们操作系统的本地内存。它是独立于我们堆区之外的。它在JDK1.8里面有一个新的名字,叫Metaspace
。Metaspace
里面还包含几个块,其中有一块就是CCS
,还有一块是CodeCache
。当然,在我们的Metaspace中还包含很多其他块,这里就不做扩展了。
接下来,我们来通过实战,来更加深入的理解JVM
结构,以及出现JVM内存溢出的原因。
实战理解
我们通过spring.start快速来生成一个springboot项目。
如图,我们快速的创建一个springboot项目,并将其下载下来。
这里我使用Eclipse,小伙伴们也可以使用IDEA或者其他开发工具也是可以的。
这里我们使用的是SpringBoot工程,如果有的小伙伴对SpringBoot还不太熟悉的,可以上网找一些教程先学习了解一下。
堆内存溢出演示
那么我们如何来构建一个堆内存溢出呢?其实很简单,我们只要定义一个List
对象,然后通过一个循环不停的往List
里面塞对象。因为只要Controller不被回收,那么它里面的成员变量也是不会被回收的。这样就会导致List里面的对象越来越多,占用的内存越来越大,最后就把我们的内存撑爆了。
创建User对象
这里我们先创建一个User对象。
/**
*
* <p>Title: User</p>
* <p>Description: </p>
* @author Coder编程
* @date 2020年3月29日
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
}
这里面@Data
、@AllArgsCo