侧边栏壁纸
博主头像
Terry

『LESSON 5』

  • 累计撰写 90 篇文章
  • 累计创建 21 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

工作日志-orika错误使用引起OOM

Terry
2022-02-12 / 0 评论 / 0 点赞 / 344 阅读 / 709 字 / 正在检测是否收录...

简述

生产环境一个项目出现了频繁重启,运维兄弟反馈过来是项目OOM了。通过Grafana上观察,随着时间推移,Metaspace趋势上升状态。这就奇怪了,一般情况下Metaspace不会一直增长。

原因分析

一般Metaspace增长原因是类加载导致的,比方说反射类加载,动态代理等。加载的类越多Metaspace占用的内存也就越大,所以Metaspace OOM可以从类加载问题进行分析。
添加-XX:+TraceClassLoading -XX:+TraceClassUnloadingVM配置后,观察日志中输出类加载以及卸载的信息,发现ma.glasnost.orika.generated.包下的类不停加载,所以分析为是orika框架错误使用导致的。

代码分析

public class BeanUtils {

    public static <S, D> D copyProperties(S source, Class<D> target) {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        return mapperFactory.getMapperFacade().map(source, target);
    }

    public static <S, D> List<D> copyProperties(List<S> source, Class<D> target) {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        return mapperFactory.getMapperFacade().mapAsList(source, target);
    }

}

很简单的一段代码,作用就是对象的copy,使用了orika框架。查看orika官网指导的例子orika使用例子也没发现什么问题。
添加jvm配置-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m,循环调用copyProperties方法,结果如下:
image.png
jvisualvm观察到的结果:
image.png
很明显得出结论,orika框架错误使用,导致UserAccountDTO类不停加载,最终导致了Metaspace OOM。
查看orika源码,发现使用了Javassist对字节码进行增强。orika原理是类映射会生成字节码文件,字节码文件是存到Metaspace中的。因为频繁new DefaultMapperFactory()(每次new都会使用新类名),导致每次new都会生成字节码文件(即使是同两个类进行转换)。所以我们需要对代码进行修复,把DefaultMapperFactory声明为静态成员变量,每次进行转换的时候都是使用同一个DefaultMapperFactory对象(里面会缓存映射类之间的关系),就不会导致Metaspace OOM了。

代码修复

public class BeanUtils {

    private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    public static <S, D> D copyProperties(S source, Class<D> target) {
        return mapperFactory.getMapperFacade().map(source, target);
    }

    public static <S, D> List<D> copyProperties(List<S> source, Class<D> target) {
        return mapperFactory.getMapperFacade().mapAsList(source, target);
    }

}

总结

本次出现的OOM问题是orika的错误使用导致Metaspace OOM,orika官网也没有细节告诉我们每次调用都new一下回导致OOM。所以我们在开发过程中使用别人的框架,除了要看框架文档使用,还要注意下自己使用过程中可能出现的问题。

0

评论区