cglib 代理类自己equals自己 返回false问题

问题:

通过debug发现result.removeAll的时候 删不了

public boolean equals(Object obj) {
            return obj instanceof OspSpringBoot2Initializer.OspBean && this.bean.equals(((OspSpringBoot2Initializer.OspBean)obj).bean);
        }

this.bean.equals(((OspSpringBoot2Initializer.OspBean)obj).bean 这里返回了false

明明地址一致,那为什么返回了false?

定位问题:

进一步定位。

通过debug定位到: 最终调用java.lang.Object#equals方法的时候,this和obj的引用不一致所以返回false
通过栈帧可以看到:
调用了cglib增强类的equals方法
通过arthas jad 命令反编译出cglib类的代码

public final boolean equals(Object object) {
        boolean[] arrbl = SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.$jacocoInit();
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor != null) {
            arrbl[3] = true;
        } else {
            SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
            arrbl[4] = true;
        }
        if (methodInterceptor != null) {
            boolean bl;
            Object object2 = methodInterceptor.intercept((Object)this, CGLIB$equals$0$Method, new Object[]{object}, CGLIB$equals$0$Proxy);
            if (object2 == null) {
                bl = false;
                arrbl[5] = true;
            } else {
                bl = (Boolean)object2;
                arrbl[6] = true;
            }
            arrbl[7] = true;
            return bl;
        }
        arrbl[8] = true;
        return super.equals(object);
    }

这里结果依赖于methodInterceptor.intercept((Object)this, CGLIB$equals$0$Method, new Object[]{object}, CGLIB$equals$0$Proxy);

我们继续看下intercept 这个方法

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			if (method.getDeclaringClass() == Object.class) {
				return method.invoke(this, args);
			}
			//.. 省略 不会走这里的
		}


发现是通过反射调用java.lang.Object#equals方法,此时是this.equals(args[0]) 发现地址不一致 结果返回false。

所以bug就定位到

method.invoke(this, args);

解决:

正确写法应该是:

methodProxy.invokeSuper(o, args);

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			if (method.getDeclaringClass() == Object.class) {
				return methodProxy.invokeSuper(o, args);
			}
			//.. 省略 不会走这里的
		}

修改过后

在调用java.lang.Object#equals时

传入了o 和 args[0] ,它们两个地址相同,所以返回true

我们继续看下栈帧:

现在有调用CGLIB$equals$0:-1, SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91

final boolean CGLIB$equals$0(Object object) {
        boolean[] arrbl = SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.$jacocoInit();
        arrbl[2] = true;
        return super.equals(object);
    }



也就是 现在的调用是:o == args[0] → true

以前的调用是:this == args[0] → false

posted @   Eiffelzero  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示