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

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

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

当我debug 跟进init方法以后发现,ReferenceConfig的成员变量initialized(boolean类型),没有初始化,值变成了true? 纳尼。。。
在学习java的基础知识的时候,咱们就知道若是boolean类型若是不初始化变量,运行的时候默认初始为true。为何变量initialized没有赋值的状况,值是true呢?
java

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

初步怀疑

初步怀疑是debug模式和run模式下初始化的值是不一样的,而后上google去搜索一下是否是存在这个问题,惋惜没有任何的收获;同时在初始化的时候,直接把initialized初始化为false,防止缺省值初始成true。
可是问题依旧,放弃了这条思路!!!
而后开始怀疑是IDEA编辑器是否是在断点处有setvalue的状况,就把IDEA所有缓存清空并重启了(File->Invalidate....),debug后问题依然!!!github

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

实在没什么思路了,想着先去增长一些日志输出,办法虽然很土,可是可能会有线索。在initialized=true 这行代码以后加一行输出
System.out.println("init initialized="+initialized);

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

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

这说明当我断点在ReferenceConfig.get()方法里时候,有线程执行了init()方法致使initialized的值被修改为了true(dubbo代码只有一处修改ReferenceConfig.initialized值的地方,就在init里面)
因此只要找出哪一个线程在我断点的时候,执行了init方法就好了api

日志输出又立大功

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

继续debug运行,获得结果出乎意外
编辑器

从日志输出能够看出来,在ReferenceConfig构造函数的地方,调用了父类AbstractConfig.toString方法,而在AbstractConfig的toString方法里面反射间接调用了ReferenceConfig.init()方法
这下算是找到谁在我断点的时候调用了ReferenceConfig.init()方法,就是toString()方法。
可是谁调用了toString()方法呢?函数

真想大白

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

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

总结

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

附送dubbo ReferenceConfig源码连接

相关文章
相关标签/搜索