DANCE WITH JAVA

          開發出高質量的系統

          常用鏈接

          統計

          積分與排名

          好友之家

          最新評論

          一個有趣的現象

             無意間發現了一個有趣的現象。下邊是重現整個現象的過程。
          1,編寫一個接口
          package iface;
          public interface MyInt {

          }

          把這個接口做成一個jar包iface.jar
          2,編寫一個類
          package mylib;

          import iface.MyInt;

          public class MyJar {
              
          public static boolean isMyInterface(){
                  
          return null==getMyInt();
              }

              
          public static MyInt getMyInt(){
                  
          return null;
              }

          }

          同樣把這個類做成一個jar文件mylib.jar
          3,新建一個工程,加入兩個jar包。然后寫一個測試類
          import mylib.MyJar;

          public class Test {
              
          public static void main(String[] args) {
                  System.out.println(MyJar.isMyInterface());
                  System.out.println(MyJar.getMyInt());
              }

          }

          4,運行得到結果:
          true
          null
          到這里一切正常,下邊開始不同的地方。
          5,把iface.jar從工程中移走,這時測試類出現編譯錯誤,這是因為MyJar.getMyInt()要返回一個MyInt類型的對象,而MyInt接口不存在。
          刪掉測試類的第二個println 變成這樣
          import mylib.MyJar;

          public class Test {
              
          public static void main(String[] args) {
                  System.out.println(MyJar.isMyInterface());
              }

          }

          重新編譯,通過。運行得到結果 :
          true
          8,分析:移走接口后導致測試類第二行println()中的代碼Myjar.getMyInt()編譯不過去,不能之行,是因為找不到MyInt接口
          但第一行能編譯,且能執行,而第一行的代碼在內部其實是調用第二行的,但依然能執行成功。
          這就說同樣的函數:MyJar.getMyInt()外部調用不能執行,通過一個函數轉一下就能執行,呵呵,挺有趣。
          感覺應該是虛擬機的實現機制方面的原因。詳細情形還沒有確認。

          posted on 2007-07-05 01:00 dreamstone 閱讀(1774) 評論(14)  編輯  收藏 所屬分類: jdk相關

          評論

          # re: 一個有趣的現象[未登錄] 2007-07-05 09:15 劉明

          估計可能在null==getMyInt();這里的時候,getMyInt()不存在,直接為null吧?大概,需要測試一下。  回復  更多評論   

          # re: 一個有趣的現象 2007-07-05 09:38 dennis

          沒必要打包成jar都有這個現象,將MyInt.class刪除也一樣。
          MyInt從來沒有被連接過(link),僅僅是被嘗試裝載(load),而裝載MyInt類但是沒有使用是不會拋出NoClassDefFoundError的。  回復  更多評論   

          # re: 一個有趣的現象[未登錄] 2007-07-05 09:45 劉明

          將iface.jar移走后,如果不重新編譯的話,程序依然能夠運行,true null,(我直接用的類,沒打包)。其實當你把iface.jar移走后沒有重新編譯,如果重新編譯就能看到會報錯的(找不到MyJar)。你使用的應該是舊的class文件。

          我估計可能getMyInt()都沒有執行,找不到就為null了。

          要知道具體原因可能需要打開class文件具體查看一下了。  回復  更多評論   

          # re: 一個有趣的現象 2007-07-05 09:56 dennis

          getMyInt()是肯定有執行,不信你可以在getMyInt加個
          System.out.println("getMyInt()");
          看看,原因俺已經說明了,更深入地請看《深入Java虛擬機》,常量池中的MyInt雖然被裝載(裝載失敗),但沒有使用,沒有被連接、解析并初始化,可以簡單地把它當成一個符號罷了  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 09:56 BeanSoft

          懶惰加載, 優化過的代碼, JVM 會走捷徑.  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 11:25 李敏

          我沒有打包,而是直接運行的。現在說說我的看法。


          1 編譯好的字節碼中可能儲存了信息。具體的我也說不出來... !--
          2 當你 javac Test的時候,它先是自動搜索當前有無編譯好的字節碼,如果沒有話,才會重新編譯,所以它會從之前的字節碼中讀出信息來參與編譯。

          可以用一個方法來測試,就是在當前的classpath下,刪除掉MyJar.class,MyInt.java更換一個package的時候,就會發現,無法通過編譯!

          呵呵,不知道我的想法對你有沒有幫助!
            回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 12:37 dreamstone

          @dennis
          打包只是為了模擬一個需求。怎么能說沒被使用呢
          isMyInterface()是調用了getMyInt()的。
          執行isMyInterface()沒問題,
          執行getMyInt()有問題。這個怎么解釋,呵呵  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 12:39 dreamstone

          @劉明
          你可以測試一下,是可以重新編譯的。至少在eclipse是可以的。
          你可以直接刪掉.class文件,讓他重新編譯出來  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 12:40 dreamstone

          @dennis
          相對比較贊同這個觀點,不過為什么調用getMyInt()會出錯呢。根本編譯不了。呵呵。  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 12:42 dreamstone

          @BeanSoft
          好像不是,我取了字節碼看,還是有這個接口的。不過考慮可能是load失敗,但是判斷null==A的時候,根本不管是個什么什么東西,只要知道它不是null就直接得出結論。因為null的==是比較特殊的。不過這也是猜測,沒有有力的證明  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 12:46 dreamstone

          @李敏
          恩,我明白你的意思。不過我說的特殊點在這里:
          c是test b是isMyInterface() a是getMyInt()
          c調用b b調用a能成功
          c直接調用a不能成功。
          而且都是putlic static 的函數,  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 13:04 dreamstone

          另外提供一個信息,同樣的代碼和執行方式
          在ibm aix上使用ibm sdk得到的結果是不一樣的,就是執行isMyInterface() 也出錯,呵呵。這個才是起因。  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 17:03 dennis

          load失敗拋出錯誤的時間,不同jdk實現不同,有的是一失敗就馬上給出NoClassDefFoundError,有的是延遲到使用該類的時候再報錯。為什么不能調用getMyInt?編譯不能通過啊,編譯過程中編譯器會查找所有出現的符號是否存在。  回復  更多評論   

          # re: 一個有趣的現象 2007-07-06 17:04 dennis

          這個問題,你再看下《深入java虛擬機》連接和初始化那個章節就明了了  回復  更多評論   

          主站蜘蛛池模板: 石首市| 漳浦县| 理塘县| 小金县| 林西县| 大荔县| 湘阴县| 曲阳县| 儋州市| 察哈| 平顺县| 吴旗县| 永仁县| 任丘市| 杭锦后旗| 台湾省| 陇西县| 阜康市| 华池县| 五莲县| 红河县| 获嘉县| 石城县| 和平区| 黎平县| 修文县| 汶上县| 军事| 襄樊市| 辽中县| 黎平县| 洪泽县| 眉山市| 扎兰屯市| 资兴市| 兴隆县| 鄂托克旗| 焦作市| 婺源县| 神农架林区| 保定市|