一、问题是怎么发现的

最近有个新系统开发完成后要上线,由于系统调用量很大,所以先对核心接口进行了一次压力测试,由于核心接口中基本上只有纯内存运算,所以预估核心接口的压测QPS能够达到上千。

压测容器配置:4C8G

先从10个并发开始进行发压,结果cpu一下就飙升到了100%,但是核心接口的qps才200左右。于是观察jvm的垃圾回收发现younggc很频繁,但是fullGC数量为零。

二、排查问题的详细过程

由于刚一开始压测,容器cpu就飙升到了100%,所以需要先定位cpu使用率问题,找出使用cpu最高的几个进程。可以通过top命令查找进程ID,发现正是压测的Java应用进程ID;然后在定位该金晨曦cpu使用率最高的线程,可以通过top -p 进程ID -H 命令显示该进程下的线程使用cpu信息。

top

top -p 进程ID -H

图片中PID列则为十进制显示的线程ID,然后转换为16进制;在通过jstack 系统进程ID | grep 16进制线程ID 命令找到对应的线程信息如下,也就是该线程占用了一半左右的cpu。

jstack 系统进程ID | grep 16进制线程ID

此时定位到了Finalizer线程,但是这个线程又有什么作用呢?

原来这个线程会不停的循环等待java.lang.ref.Finalizer.ReferenceQueue中的新增对象。一旦Finalizer线程发现队列中出现了新的对象,它会弹出该对象,调用它的finalize()方法,将该引用从Finalizer类中移除,因此下次GC再执行的时候,这个Finalizer实例以及它引用的那个对象就可以被垃圾回收掉了。如果这个线程一直在不停的工作,说明Finalizer的队列中有许多等待GC的垃圾对象。此时可以通过另一个命令来查看等待回收的垃圾对象有哪些。

jmap -finalizerinfo 进程ID

Count Class description
-------------------------------------------------------
32221 com.jd.price.deep.exact.entity.coupons.DeepExactCouponVo$$EnhancerByCGLIB$$200e6ee6
14908 com.jd.pricedoor.compute.promotion.MultiplePromotion$$EnhancerByCGLIB$$a59933de
11982 java.util.zip.Deflater
1 java.net.SocksSocketImpl

通过上述结果可以发现有好多的业务对象,通过类名可以看到这些对象都是通过CGLIB动态代理创建的,而且这些动态代理类都默认实现了finalize方法,导致这些对象在进行垃圾回收时必须先要执行finalize方法,所以都积压到了finalizer的队列中。

三、如何解决问题

通过上述排查过程发现,是由于大量的业务对象通过CGLIB创建了动态代理类,而这些代理都是系统处理请求时创建的临时对象,请求完成后,这些临时对象就需要被垃圾回收掉,从而导致Finalizer线程执行频繁抢占了cpu资源。

针对以上分析结果所以有了如下几种解决方案:

1.不要使用CGLIB来给那些需要频繁进行垃圾回收的对象创建动态代理,可以手动创建静态代理类。

2.对象复用,尽量减少临时对象的产生。

作者:京东零售 曹志飞

来源:京东云开发者社区

CGLIB动态代理对象GC问题排查的更多相关文章

  1. Spring框架中的JDK与CGLib动态代理

    JDK和CGLib动态代理区别 JDK动态代理:利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类, 在调用具体方法前调用InvokeHandler ...

  2. jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

    代理模式是一种很常见的模式,本文主要分析cglib动态代理的过程 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.c ...

  3. Java代理:静态代理、JDK动态代理和CGLIB动态代理

    代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式.所谓的代理者是指一个类别可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.存储器中的大对象.文件或其它昂贵或无法复制 ...

  4. CGLib动态代理原理及实现

    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采 ...

  5. 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】

    一.cglib动态代理 1.简介 (1)CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. (2) 用CGlib生成代理类是目标类的子类. (3 ...

  6. JDK动态代理与CGLib动态代理

    1.JDK动态代理 JDK1.3以后java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,动态代理是实现AOP的绝好底层技术. JDK的动态代理主要涉及到java.lang.reflect ...

  7. Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 /** * 业务接 ...

  8. [z]Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 1 2 3 4 5 ...

  9. Atitit 代理CGLIB 动态代理 AspectJ静态代理区别

    Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为 ...

  10. Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC

    一.为什么需要代理模式 假设需实现一个计算的类Math.完成加.减.乘.除功能,如下所示: package com.zhangguo.Spring041.aop01; public class Mat ...

随机推荐

  1. Driver8833电机驱动模块的使用(STM32为主控)

    一.硬件 STM32C8T6.STLINK下载器 Driver8833:TI公司的DRV8833是双桥马达驱动器解决方案,包括有两个H桥驱动器,可驱动两个DC电刷马达,或一个步进马达, 螺线管和其它电 ...

  2. 云原生时代崛起的编程语言Go并发编程实战

    @ 目录 概述 基础理论 并发原语 协程-Goroutine 通道-Channel 多路复用-Select 通道使用 超时-Timeout 非阻塞通道操作 关闭通道 通道迭代 定时器-TimerAnd ...

  3. ai问答:使用 Vue3 组合式API 和 TS 封装 echarts 折线图

    使用这个组件时,只需要传入合适的chartData数组,就可以渲染一个折线图,并且响应数据变化. <template> <div ref="chart" styl ...

  4. 【转】内存清零KILL进程

    #include <Windows.h> #include <Ntsecapi.h> #include <Aclapi.h> #include <tlhelp ...

  5. 2022-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver

    2022-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver ...

  6. 2020-12-08:TIME_WAIT的等待时间为什么是2MSL?

    福哥答案2020-12-08:[答案来自此链接:](http://bbs.xiangxueketang.cn/question/646)这里假设主动关闭方为A,被动关闭方为B,TIME_WAIT状态是 ...

  7. 【C++】requires关键字简介

    requires 是 C++20 中引入的一个新关键字,用于在函数模板或类模板中声明所需的一组语义要求,它可以用来限制模板参数,类似于 typename 和 class 关键字. requires关键 ...

  8. simplejwt配置大全

    # simplejwt配置大全SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), # 设置token有效时间 'REFRESH_ ...

  9. .NET周报 【5月第2期 2023-05-14】

    国内文章 XUnit数据共享与并行测试 https://www.cnblogs.com/podolski/p/17388602.html 在单元或者集成测试的过程中,需要测试的用例非常多,如果测试是一 ...

  10. unity添加Mysql的dll以及发布的问题

    最近在做一个unity项目中,要读取数据库,还是MySql的数据库.遇到了很多问题,写出来供大家参考一下. 关于unity引用第三方的Mysql.data.dll的问题: 这个地方有一个难点,正常的C ...