fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

com.alibaba.fastjson2.util.DynamicClassLoader 类加载过多,造成jvm元空间内存使用达到99%

Open Swordsman007 opened this issue 1 year ago • 6 comments

问题描述

我在线上服务排查发现,class loader数量巨多,导致监控内存飙升,元空间内存使用率达到 99.1% 通过arthas发现fastjson2中类加载数量很大,但是我自己项目中都是正常使用的fastjson,没有哪里可能有那么大的类加载。而且类加载数量一致持续升高,垃圾回收不掉,不知道是不是fastjson包里面哪里类加载过大还是什么问题

image

image

环境信息

请填写以下信息:

  • JDK信息: [Openjdk 1.8.0_391]
  • 版本信息:[Fastjson2 2.0.42]

重现步骤

如何操作可以重现该问题:

  1. 使用 xxx.xxx 方法
  2. 输入 ... 数据
  3. 出现 ... 错误
//可在此输入示例代码

期待的正确结果

对您期望发生的结果进行清晰简洁的描述。

相关日志输出

请复制并粘贴任何相关的日志输出。

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

Swordsman007 avatar Dec 19 '23 02:12 Swordsman007

现在的信息无法诊断问题,需要你自己诊断装载了哪些类?使用fastjson2的方式也发下出来,方便大家诊断

wenshao avatar Dec 20 '23 01:12 wenshao

现在的信息无法诊断问题,需要你自己诊断装载了哪些类?使用fastjson2的方式也发下出来,方便大家诊断

项目中使用的:com.alibaba.fastjson2.JSON#parseObject() 我跟到源码看了下,里面有使用到ThreadLocal,怀疑是没有remove造成了内存泄漏

image

Swordsman007 avatar Dec 20 '23 01:12 Swordsman007

我写了一个Demo,复现了这种情况 package com.mtt.javabase.json.fastjsonv2.mem;

import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONReader; import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.PropertyNamingStrategy; import com.alibaba.fastjson2.writer.ObjectWriterProvider;

import java.lang.management.ClassLoadingMXBean; import java.lang.management.ManagementFactory; import java.util.LinkedHashMap; import java.util.Map;

public class TestParseObject {

public static void main(String[] args) {
    int count = 10;
    for (int i = 0; i < count; i++) {
        parseAddress(new DemoBean("test", "cn"));
    }
}

public static void parseAddress(DemoBean form){
    // 获取ClassLoadingMXBean实例
    ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
    // 获取已加载类的数量
    String s = JSON.toJSONString(form);
    int loadedClassCount0 = classLoadingMXBean.getLoadedClassCount();
    Map paramMap = JSON.parseObject(toUnderLineJSONString(form), LinkedHashMap.class);
    // 获取已加载类的数量
    int loadedClassCount1 = classLoadingMXBean.getLoadedClassCount();
    System.out.println("第一次解析增加数量:" + (loadedClassCount1 - loadedClassCount0));

    int loadedClassCount2 = classLoadingMXBean.getLoadedClassCount();
    JSON.parseObject(s, DemoBean.class, JSONReader.Feature.SupportSmartMatch);
    int loadedClassCount3 = classLoadingMXBean.getLoadedClassCount();
    System.out.println("第二次解析增加数量:" + (loadedClassCount3 - loadedClassCount2));

}

public static String toUnderLineJSONString(Object data){
    ObjectWriterProvider objectWriterProvider = new ObjectWriterProvider(PropertyNamingStrategy.SnakeCase);
    JSONWriter.Context context = new JSONWriter.Context(objectWriterProvider);
    return JSON.toJSONString(data,context);
}

}

package com.mtt.javabase.json.fastjsonv2.mem;

import lombok.Data;

import java.io.Serializable;

@Data public class DemoBean implements Serializable {

private static final long serialVersionUID = 3684004407642373704L;

private String address;

private String type1;

private String type2;

private String type3;

private String type4;

public DemoBean() {
}

public DemoBean(String address, String type1) {
    this.address = address;
    this.type1 = type1;
}

} ,第一种情况,加载类的数量会一直增加

mttstonell avatar Dec 20 '23 09:12 mttstonell

现在的信息无法诊断问题,需要你自己诊断装载了哪些类?使用fastjson2的方式也发下出来,方便大家诊断

在JSON.toJSONString中添加JSONWriter.Context,好像就会导致最近的一个JSON.parseObject出现一个新增class load

mttstonell avatar Dec 20 '23 09:12 mttstonell

ObjectWriterProvider 这个类要做单例

wenshao avatar Dec 23 '23 10:12 wenshao

ObjectWriterProvider 这个类要做单例

OK

Swordsman007 avatar Dec 25 '23 01:12 Swordsman007