线上故障排查-频繁fullGC问题排查

环境准备

  1. centos 7
  2. tomcat 8 / 7
  3. jdk1.8
  4. 开发工具idea
  5. spring boot2.0+
  6. MemoryAnalyzer

1 idea创建spring boot默认项目

在这里插入图片描述
贴下pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.learning</groupId>
	<artifactId>jvm-learn</artifactId>
	<version>1.0</version>
	<name>jvm-learn</name>
	<packaging>war</packaging>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

简单说下这个listing(商品) 模拟一个大的实体对象(详见下)
在这里插入图片描述
这里我们采用war包的形式发布 spring boot打包war 使用tomcat 部署项目 所以需要集成SpringBootServletInitializer

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class JvmLearnApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(JvmLearnApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(JvmLearnApplication.class);
    }

}

代码基础阶段准备结束

2 准备模拟问题代码

package com.learning.controller;

import com.learning.dto.Listing;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


@RestController
@RequestMapping("/jvm")
@Slf4j
public class JvmController {


    private static List<Listing> lists = new ArrayList<>();

    @GetMapping("/mem")
    public String menTest() {
        for (int i = 0; i < 20; i++) {
            Listing listing = new Listing();
            listing.setCode(i + "code");
            listing.setName(i + "name");
            Byte[] bytes = new Byte[1024 * 1024 * 10];
            listing.setMem(bytes);
            lists.add(listing);
        }
        return "success";

    }

}

在简单解释下 把lists 放到属性位置上是为了让该对象可达(GC root如果没有指针指向它,lists这个对象就会被回收。看不到效果) 然后就是打包发布到tomcat

  1. 打包项目
    在这里插入图片描述
  2. 将war包发布到tomcat 的root目录下面 使用命令解压文件
    unzip jvm-learn-1.0.war
  3. 启动tomcat (切换到bin目录下面 )使用命令启动服务
    sh startup.sh

3 分析问题

  1. 访问接口 http://192.168.80.128:8080/jvm/mem (访问结果可能报错 500 因为已经内存泄露了)
  2. 使用命令 top 查看服务器内存 ,然后按大写M以内存占用倒叙排序
    在这里插入图片描述
  3. 使用jdk提供命令 jmap -dump:format=b,file=heapdump.phrof 3687 dump下内存使用情况 (会在当前文件夹下生成phrof文件)
    在这里插入图片描述
  4. 分析内存
    使用eclipse 工具MAT 分析内存文件 MAT绿色版下载地址 。并且选择导入刚才使用jmap生成的文件
    在这里插入图片描述
    导入文件后 注意观察下面几个地方
    在这里插入图片描述
    点击Histogram 以Retain heap 排序 Retain heap 简单解释下 Retain heap 是指这个对象中所指向的对象占用内存的大小 问题基本找到
    在这里插入图片描述
    查看这个listing 到底那里用到 里面存放了什么东西导致内存溢出
    在这里插入图片描述
    按照上面操作后 会显示出来
    在这里插入图片描述
    大体上问题已经定位到. 就是因为 JvmController 的 menTest() 方法处理不合适导致 lists 里面存放了大对象 并且没有被GC回收然后就是jvm内存溢出。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值