dubbo debug过程中一个有趣的问题

时间:2022-11-15 16:31:39

最近在debug dubbo代码过程中遇到的很有趣的问题

我们都知道dubbo ReferenceBean是消费者的spring bean包装,为了查一个consumer端的问题,在ReferenceBean的父类ReferenceConfig的 T get()方法(140行)打上了一个断点。

dubbo debug过程中一个有趣的问题

当我debug 跟进init方法之后发现,ReferenceConfig的成员变量initialized(boolean类型),没有初始化,值变成了true? 纳尼。。。

在学习java的基础知识的时候,我们就知道如果boolean类型如果不初始化变量,运行的时候默认初始为true。为什么变量initialized没有赋值的情况,值是true呢?

dubbo debug过程中一个有趣的问题

更奇怪的是,debug模式下,因为initialized=true consumer的桩代码(proxy)没有生成,所以在业务层调用的时候跑出了NPE;但是在run模式下是对的。

初步怀疑

初步怀疑是debug模式和run模式下初始化的值是不同的,然后上google去搜索一下是不是存在这个问题,可惜没有任何的收获;同时在初始化的时候,直接把initialized初始化为false,防止缺省值初始成true。

但是问题依旧,放弃了这条思路!!!

然后开始怀疑是IDEA编辑器是不是在断点处有setvalue的情况,就把IDEA全部缓存清空并重启了(File->Invalidate....),debug后问题依然!!!

修改dubbo的源代码加日志输出

实在没什么思路了,想着先去增加一些日志输出,办法虽然很土,但是可能会有线索。在initialized=true 这行代码之后加一行输出

System.out.println("init initialized="+initialized);

dubbo debug过程中一个有趣的问题

同时断点还在ReferenceConfig.get()方法里面

dubbo debug过程中一个有趣的问题

当运行到断点出,观察console的输出,果然有输出!!!!

dubbo debug过程中一个有趣的问题

这说明当我断点在ReferenceConfig.get()方法里时候,有线程执行了init()方法导致initialized的值被修改成了true(dubbo代码只有一处修改ReferenceConfig.initialized值的地方,就在init里面)

所以只要找出哪个线程在我断点的时候,执行了init方法就行了

日志输出又立大功

继续在init方法里面加日志输出,以下日志能显示出哪个堆栈调用了init方法

dubbo debug过程中一个有趣的问题

继续debug运行,得到结果出乎意外

dubbo debug过程中一个有趣的问题

从日志输出可以看出来,在ReferenceConfig构造函数的地方,调用了父类AbstractConfig.toString方法,而在AbstractConfig的toString方法里面反射间接调用了ReferenceConfig.init()方法

这下算是找到谁在我断点的时候调用了ReferenceConfig.init()方法,就是toString()方法。

但是谁调用了toString()方法呢?

真想大白

首先可以排除程序在构造函数里面调用AbstractConfig.toString方法,还有一种可能就是IDEA 为了显示触发了这个类实例的toString方法。有了这个假设思路,写了一个demo验证一下

dubbo debug过程中一个有趣的问题

果不其然console里面输出了invoke toString()

总结

IDEA 这类编辑器带debug功能为了断点处能显示一个类的实例,就会反射调用实例的toString!!!!

真是一个有趣的发现!!!!

附送dubbo ReferenceConfig源码链接