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呢?

更奇怪的是,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);

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

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

这说明当我断点在ReferenceConfig.get()方法里时候,有线程执行了init()方法导致initialized的值被修改成了true(dubbo代码只有一处修改ReferenceConfig.initialized值的地方,就在init里面)
所以只要找出哪个线程在我断点的时候,执行了init方法就行了
日志输出又立大功
继续在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源码链接
dubbo debug过程中一个有趣的问题的更多相关文章
- Debug过程中的mock (及display窗口的使用)
转载:http://m.blog.csdn.net/blog/u012516903/18004965 在debug的时候,有3个地方可以进行mock测试 测试代码如下: 1.使用display窗口 W ...
- 如何在Eclipse和Tomcat的Debug过程中启用热部署
参考的地址是 http://blog.redfin.com/devblog/2009/09/how_to_set_up_hot_code_replacement_with_tomcat_and_ecl ...
- xargs命令的使用过程中一个小领悟:管道与xargs的差别
对xargs的使用总是比较模糊,大概的理解为:通道中,上一个命令的标准输出逐行作为下一个命令的参数 例如 find /var/temp* | xargs rm -r 功效:找出/var/中所有temp ...
- vue生命周期updated的触发时机之debug过程中发现的firefox问题
现象描述: 断点位置1 谷歌debug的过程: 火狐debug的过程: 只要在改变数据之后有断点停顿,就会先去执行updated函数 断点位置2 此时火狐和谷歌是一样的效果,但是执行顺序是不一致的 谷 ...
- 【UEFI】---记录一次debug过程中的调试经验
最近在调试一次SMBIOS的动态更新以及I2c设备的配置读取时,遇到了很多问题,特此总结: 1. 第一个是调试一个I2c设备的时候,遇到了一个很奇怪的问题,也由此问题总结了下SMBUS模块的知识,如下 ...
- IDEA Debug过程中使用Drop Frame或Reset Frame实现操作回退
大家在Debug程序的时候,是否遇到过因为"下一步"按太快,而导致跳过了想要深入分析的那段代码?是不是很想要有"回到上一步"这样的操作呢? 在IDEA中就提供了 ...
- 解析 Java 反射题中一个有趣的坑
public class Test { public void age(int age) { System.out.println("int age="+age); } publi ...
- c++ 内存分配中一个有趣的小问题
以下代码测试环境:vs2019 执行这么一段代码,看看会发生什么. int main() { ] = { }; arr[] = ; } 毫无疑问,会报错,因为访问越界了. 再看看另一段代码 ] = { ...
- connect & send 在三次握手过程中的有趣问题
一.问题回顾 面试的时候被问到的问题,原问题是: 1:写一下socket网络编程服务端和客户端常用的函数. 2:如果服务端在listen之后没有accept,那客户端的connect会返回吗?为什么? ...
随机推荐
- Android Screen Monito
1.下载 Android Screen Monitor http://code.google.com/p/android-screen-monitor/ (1) 下載 ASM_2_40.zip 并解压 ...
- asp.net core 五 SignalR 负载均衡
SignalR : Web中的实时功能实现,所谓实时功能,就是所连接的客户端变的可用时,服务端能实时的推送内容到客户端,而不是被动的等待客户端的请求.Asp.net SignalR 源码 ...
- ZOJ3946:Highway Project(最短路变形)
本文转载自:http://www.javaxxz.com/thread-359442-1-1.html Edward, the emperor of the Marjar Empire, wants ...
- 复习ACCESS注入
0x00前言:在学校看完了ACCESS注入.但当时并没有电脑,所以做好了笔记 回到家自己搭建了一个有ACCESS注入的站进行练习,虽然这可能没有什么用处 毕竟现在大多的网站都有waf或安全狗.而且AC ...
- shell 文本操作命令
vi 编辑器中有三种状态模式 [vi 文件名(或路径+文件名)] 1.命令模式 2.输入模式 3.末行模式 三种模式间的相互转换 vi编辑器的启动与退出 直接进入编辑环境 $ vi 进入编辑环境并打 ...
- 笔记:Struts2 文件上传和下载
为了上传文件必须将表单的method设置为POST,将 enctype 设置为 muiltipart/form-data,只有设置为这种情况下,浏览器才会把用户选择文件的二进制数据发送给服务器. 上传 ...
- Logback.xml 给变量指定默认值
随着通用日志组件转入 Slf4j,logback 也变成了默认的日志实现,像 log4j 一样,logback.xml 中也可以使用系统属性或环境变量,如 ${catalina.home}.在 log ...
- 【Python】 SSH连接的paramiko
paramiko *paramiko需要PyCrypto模块的支持 paramiko支持通过SSH协议进行一些操作,比如远程执行命令,上下传文件等等 用法: ① 远程命令 ssh = paramiko ...
- docker教程
Docker 包括三个基本概念 镜像(Image) 容器(Container) 仏库(Repository) 理解了返三个概念,就理解了 Docker 的整个生命周期. Docker 镜像 Docke ...
- java 中的IO
什么是文件文件可认为是相关记录或放在一起的数据集合 通过流来读写文件流是指一连串流动的字符,是以先进先出方式发送信息的通道输入输出流是相对计算机的内存来说的 字节流是八位通用字节流,字符流是16位Un ...