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源碼鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM