前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线上问题解决:java之full gc问题分析,定位及解决

线上问题解决:java之full gc问题分析,定位及解决

作者头像
IT架构圈
发布2021-03-17 14:51:48
2.2K0
发布2021-03-17 14:51:48
举报
文章被收录于专栏:IT架构圈IT架构圈

结合生产环境的一些案例,可能有些案例,你知道了,或者是听说过,可能你还不了解,一起说下,过下生产中的问题。

full gc
  • ① 启动参数配置

-Xms2g -Xmx2g JVM堆内存的最小值,最大值设置成相等的。

预热过程(堆内存小于最小值),慢慢的增长到最小值,而不是直接打到最小值的2g,如果需要直接像操作系统申请足够的内存,请在参数中增加:-XX:+AlwaysPreTouch,直接申请2g的内存。

  • ② GC

了解GC的配置,而不是需要了解GC代码是怎么写,其实就是熟悉JVM的应用,还有JVM的更新信息,一定要跟着官网走肯定是没有错的。要掌握的是梳理的方式。很多事情不是出了问题去解决,很多时候是提前的预防工作。

线上的系统:GC的并行 (-XX:+UseParNewGC) + CMS机制(用户线程和GC线程同步),官方建议是G1,不久将来肯定都是G1。

提前的预防:日志不能缺少。不要stop the world,运行过程中犹豫GC导致的停顿,暂停,java代码运行不了,需要一定的时间进行垃圾回收。

打印gc的信息,filepath是日志的路径。

代码语言:javascript
复制
-verbose:gc -XX:+PrintGCDetails -Xloggc:filepath -XX:+HeapDumpOnOutOfMemoryError
  • ② 代码写作错误

正常的情况下,不需要控制gc,依赖操作系统的gc就够了,但是代码里面却写了System.gc()。导致程序不稳定。写这个比较头疼,不像写其他的异常,在高并发场景或者特殊场景下面,应用暂停,应用无法访问,如何排查,首先需要了解,那些情况会出现full gc的情况,内存不够用固然是一个方面,很多时候代码写的有问题。

下面这段代码,本身设置512m的内存,结果每次申请256M的内存,明显内存不够,进行了gc。还有个gc就是代码里面自带的gc情况。

代码语言:javascript
复制
// 频繁调用system.gc导致fullgc次数过多
// 使用server模式运行 开启GC日志
// -Xmx512m -server -verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
public class FullGCDemo1 {
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 1000; i++) {
            byte[] tmp = new byte[1024 * 1024 * 256]; // 256兆
            System.gc(); // 8G堆 128兆。full GC
            System.out.println("我GC一次了");
            Thread.sleep(2000L);
        }
    }
}
  • ③ 案例分析

一个服务器部署了一个应用,这个应用有很多的功能,其中有个execl的表格读取。用到了一个jar,JXL。

pom.xml

代码语言:javascript
复制
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.study.jvm</groupId>
    <artifactId>om-demo</artifactId>
    <version>1.0.0</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>net.sourceforge.jexcelapi</groupId>
            <artifactId>jxl</artifactId>
            <version>2.6.12</version>
        </dependency>
        <!-- 自动下不了,就手动添加到自己的maven本地仓库 -->
        <!-- https://mvnrepository.com/artifact/com.dianping.cat/cat-client -->
        <dependency>
            <groupId>com.dianping.cat</groupId>
            <artifactId>cat-client</artifactId>
            <version>3.0.0</version>
        </dependency>

    </dependencies>

</project>
代码语言:javascript
复制
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.WorkbookSettings;

import java.io.File;

// 使用server模式运行 开启GC日志
// -Xmx512m -server -verbose:gc -XX:+PrintGCDetails
// 很多人都会建议的规避System.gc带来的fullgc风险  -XX:+DisableExplicitGC 禁止程序显示调用gc方法
public class FullGCDemo2 {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 1000; i++) {

            Workbook book = Workbook.getWorkbook(new File(FullGCDemo2.class.getClassLoader().getResource("FullGCDemo2.xls").getFile()));
            // 获得第一个工作表对象
            Sheet sheet = book.getSheet(0);
            // 得到第一列第一行的单元格
            Cell cell1 = sheet.getCell(0, 0);
            String result = cell1.getContents();
            System.out.println(result);
            book.close(); // 第三方依赖包,内部可能适用了system.gc()
            Thread.sleep(2000L);
        }
    }
}

resources 目录下 添加一个excel文件

excel文件

正常情况下没有任何的报错

加入gc的监控看看,发现了很多System.gc();

检查发现源码中存在Sytem.gc() ,本以为开源代码很健全谁料,这么多坑,真是防不胜防啊,怎么办?

其实别人在写开源的代码都想到了。仔细看里面的源码发现。

再次运行,发现没有full gc的情况了。

总结下,可能这一个框架有可以禁用gc,一个大项目用了很多框架我不可能每个都看看源码吧,所以需要提前做性能的测试,发现里面的System.gc();解决他。但是有可能有的框架本身必须需要进行gc,例如大数据这块。其实这就是调优去衡量,那些需要gc,那些不需要gc。太极玩的就是一个平衡,并不是这个事情多严重,但是这个坑一定得注意,这就是性能测试的必要性。小功能的jar自带的gc,可能导致这个系统的gc,本来10秒一次的gc,因为这个小功能1秒中gc一次,导致整个系统也是1秒1个次,本身开发系统就是为了减少耦合。针对这些问题应该如何解决。dubbo这个框架里面引用了spring框架,其实根本没有引用里面的jar,而是把里面的源码放到dubbo的一个包下面,做定制的开发,这样我可以控制gc了。这就可以完全避免耦合性,因为代码都是我的,我可以随意的控制。一定要检查第三方包的使用情况。

在jdk很多源码中都存在 //help GC,其实就是first =null 这样就释放了,gc就自动的回收了。针对文件导入excel中需要通过list导入,list里面有10万条数据,导入后,可能list就不管了,如果想让jvm跑的更快的话,可以在最后写个list= null。jvm在做垃圾回收计算的时候,就不需要做任何分析直接就回收掉了。

PC:通过上边的代码应该可以明白,jvm在做回收统计的时候真得会一个一个统计的。开发时,借鉴线程安全,接触到大数据的地方,就有泄露的可能,被反被执行,也有可能出现泄露。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程坑太多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • full gc
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档