I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0
               昨天在公司寫了一段代碼,很簡單,就是測試Thread的dumpStack方法的使用。因?yàn)門hread的dumpStack方法不是很常用,但它對于如果想看看誰在運(yùn)行時(shí)調(diào)用方法還是非常有幫助的。回到正題,看輸出結(jié)果:
          java.lang.Exception: Stack trace
           at java.lang.Thread.dumpStack(Unknown Source)
           at Common.getInfo(TestDumpStack.java:21)
           at TestDumpStack.main(TestDumpStack.java:7)
              大家可以看到在輸出的第二行,顯示的是at java.lang.Thread.dumpStack(Unknown Source)。為什么自己寫的代碼就顯示出了源碼文件的名字及所在行數(shù),而jdk的類庫就顯示出了Unknown Source?
              相信很多人在調(diào)試代碼,用log工具打印堆棧異常信息,查看代碼所在行的相關(guān)調(diào)試信息時(shí),經(jīng)常會(huì)遇到Unknown Source這個(gè)頭痛的問題。那么這個(gè)東西到底如何而來?
              A.Unknown Source從哪來?

               Unknown Source,顧名思義,就是未知的源文件。因?yàn)槲覀冏罱K解釋運(yùn)行的是class文件,所以出現(xiàn)這個(gè)問題的原因很簡單,就是class文件中沒有源文件的相關(guān)調(diào)試信息。那為什么class文件會(huì)沒有調(diào)試信息呢?答案更簡單,當(dāng)然是我們在用javac命令進(jìn)行編譯的時(shí)候沒有指定調(diào)試信息唄。因?yàn)楝F(xiàn)在很多人都習(xí)慣用eclipse等一些現(xiàn)成的ide進(jìn)行編寫代碼,所以很少人熟悉jdk自己的javac,java,jdb等一些命令的詳細(xì)參數(shù)(jdk的一些命令和eclipse自帶的一些命令可能不同)。哈哈,不過如果你經(jīng)常在linux下玩java的話,命令肯定會(huì)非常熟悉。那么讓我們看看javac的一些重要參數(shù):
              -g-Generate all debugging information, including local variables. By default, only line number and source file information is generated.在class文件中生成所有調(diào)試信息,包括局部變量的信息。默認(rèn)的話,只寫入源碼的行號(hào)和源文件信息。
              -g:none-Do not generate any debugging information.不生成任何調(diào)試信息。
              -g:(lines,vars,source)-只生成部分調(diào)試信息(源碼行號(hào),變量,源文件信息)。那我們在分別介紹下lines,vars,source的含義。
                   lines:將源文件中的行號(hào)信息寫到Class文件中,此屬性用于在Class文件中生成方法字節(jié)碼流偏移量和源代碼行號(hào)之間的映射關(guān)系。如果我們不指定此屬性的話,我們將在堆棧異常信息中看不到打印的行號(hào)。
                   vars:Local variable屬性建立了方法的棧幀中局部變量部分內(nèi)容與源代碼中局部變量名稱和描述符之間的映射關(guān)系。有了這個(gè)屬性,調(diào)試時(shí),我們才可以看到變量的值。
                   source:編譯時(shí)指定了這個(gè)屬性,會(huì)把源文件的屬性信息如源文件名稱寫入class文件。
               說了這么多,初學(xué)者可能會(huì)迷糊,為什么編譯要指定這些調(diào)試信息呢?哈哈,如果編譯不指定這些調(diào)試信息的話,你怎么調(diào)試呢?如果你不指定行號(hào)信息的話,你在ide中都無法插入斷點(diǎn)。這些調(diào)試信息在我們調(diào)試程序的時(shí)候非常重要。不過這些編譯選項(xiàng)通常在ide中如eclipse中早已默認(rèn)了。有的人可能還不相信,打開eclipse,依次打開菜單選項(xiàng):Window->Preferences->Java->Compiler,可以看到頁面的下方有一個(gè)Classfile Generation,默認(rèn)是四個(gè)選項(xiàng)都選的。
              那這個(gè)Unknown Source到底是編譯的時(shí)候沒有指定哪一項(xiàng)呢?經(jīng)過測試,我發(fā)現(xiàn)是javac編譯的時(shí)候沒有沒有指定source選項(xiàng),必定出Unknown Source這個(gè)問題。
               PS1:linux下,很多人用ant進(jìn)行javac任務(wù)編譯,查看堆棧異常時(shí)也經(jīng)常會(huì)遇到Unknown Source的問題。ant編譯時(shí),默認(rèn)相當(dāng)于指定-g:none,及不生成任何調(diào)試信息的。所以如果要看到日志分析中的源碼和行號(hào)信息時(shí),要更改build.xml中的dubug屬性。
              PS2:我覺得看看Log4j的日志操作類源碼包會(huì)對這個(gè)理解更有幫助。

              B.剛開始的代碼引子中,為什么自己寫的代碼會(huì)有堆棧異常的代碼行數(shù)顯示,而jdk的類庫(rt.jar-Runtime Java Archive)代碼會(huì)出現(xiàn)Unknown Source?
              答案很簡單,因?yàn)槲覀冎苯佑玫氖莏dk直接編譯好的class文件。而rt.jar源碼編譯打包的時(shí)候,是沒有將調(diào)試信息放入class文件的。所以才會(huì)顯示Unknown Source。其實(shí),道理很簡單,sun的類庫正常的情況下肯定不會(huì)有bug的,之前肯定都是調(diào)試過很多遍的,所以沒有必要再加入調(diào)試信息,你只負(fù)責(zé)用就行了。所以,出現(xiàn)Unknown Source很正常。
               PS:其實(shí),我覺得這和軟件的開發(fā)版本差不多。版本一般都有dubug版本和release版本。debug版本就是包含調(diào)試信息的。不過正式發(fā)行后,肯定不包含調(diào)試信息的。因?yàn)槿绻{(diào)試信息的話,可能版本占用空間會(huì)很大,而且根本就無需調(diào)試信息。

              C.如果我們非要對jdk的類庫如rt.jar進(jìn)行跟蹤調(diào)試怎么辦?
               因?yàn)閞t.jar編譯打包的時(shí)候,是不包含調(diào)試信息的。如果你只是想看看調(diào)用的過程,你只需要在eclipse中rt.jar下的Source attachment指定jdk安裝目錄的src.zip即可。不過如果你想跟蹤jdk類庫的變量值的時(shí)候,這樣就不行了。除非,只有一種辦法,你重新編譯一下src.zip,指定好編譯參數(shù),然后用新編譯好的rt.jar覆蓋掉原來的rt.jar。這樣就完全ok了。

              D.如果我們想debug其他沒有源代碼的class文件呢?
               其實(shí),也不難,利用jad等反編譯工具編譯出源碼后,在進(jìn)行調(diào)試。不過前提是該class文件有調(diào)試信息。

               PS:在網(wǎng)上看到了一些打印堆棧異常信息的代碼,發(fā)現(xiàn)有的竟然打印出了jdk源碼的所在行數(shù)。如
          at java.lang.Thread.dumpStack(Thread.java:1206)等。我覺得很好奇,原因可能是重新編譯了jdk的源碼或者可能用的不同的ide或者不同版本的jdk吧。這個(gè)尚需考證。如果有懂的童鞋,可以和我交流

              終于寫完了。可能有很多地方需要改正,希望不吝指教。看了看時(shí)間,是凌晨1:46分。不早了,該睡了。天亮說晚安。
          posted on 2011-02-27 01:54 landon 閱讀(39478) 評(píng)論(1)  編輯  收藏 所屬分類: Program

          FeedBack:
          # re: Unknown Source的出現(xiàn)及解決
          2015-03-16 19:26 | he
          看不懂解決方法是甚麼啊  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 福鼎市| 长宁区| 东乌| 大安市| 中西区| 三穗县| 淮南市| 醴陵市| 新河县| 沭阳县| 宜黄县| 贵港市| 乡宁县| 富裕县| 大丰市| 正镶白旗| 宜阳县| 治县。| 内乡县| 韶关市| 上饶市| 徐水县| 平塘县| 平阴县| 禄劝| 忻城县| 襄汾县| 镇远县| 汾阳市| 济源市| 高安市| 南郑县| 鄂尔多斯市| 巨鹿县| 盐城市| 宜阳县| 正阳县| 云阳县| 道孚县| 雅江县| 甘孜县|