從基本結構到Java 7新特性(6)

發表于:2013-01-05來源:ImportNew作者:朱偉杰點擊數: 標簽:java
javap輸出的內容太長,我這里只是提出了整個輸出的一部分。整個的輸出展示了constant_pool里的不同信息,以及方法的內容。 關于方法的65565字節大小的限制

  javap輸出的內容太長,我這里只是提出了整個輸出的一部分。整個的輸出展示了constant_pool里的不同信息,以及方法的內容。

  關于方法的65565字節大小的限制是和method_info struct相關的。method_info結構包含Code,LineNumberTable,以及LocalViriable attribute幾個屬性,這個在“javap -verbose"的輸出里可以看到。Code屬性里的LineNumberTable,LocalVariableTable以及exception_table的長度都是用一個固定的2字節來表示的。因此,方法的大小是不能超過LineNumberTable,LocalVariableTable以及exception_table的長度的,它們都是65535字節。

  許多人都在抱怨方法的大小限制,而且在JVM規范里還說名了”這個長度以后有可能會是可擴展的“。不過,到現在為止,還沒有為這個限制做出任何動作。從JVM規范里的把class文件里的內容直接拷貝到方法區這個特點來看,要想在保持后向兼容性的同時來擴展方法區的大小是非常困難的。

  如果因為Java編譯器的錯誤而導致class文件的錯誤,會怎么樣呢?或者,因為網絡傳輸的錯誤導致拷貝的class文件的損壞呢?

  為了預防這種場景,Java的類裝載器通過一個嚴格而且慎密的過程來校驗class文件。在JVM規范里詳細地講解了這方面的內容。

  注意

  我們怎樣能夠判斷JVM正確地執行了class文件校驗的所有過程呢?我們怎么來判斷不同提供商的不同JVM實現是符合JVM規范的呢?為了能夠驗證以上兩點,Oracle提供了一個測試工具TCK(Technology Compatibility Kit)。這個TCK工具通過執行成千上萬的測試用例來驗證一個JVM是否符合規范,這些測試里面包含了各種非法的class文件。只有通過了TCK的測試的JVM才能稱作JVM。

  和TCK相似,有一個組織JCP(Java Community Process;http://jcp.org)負責Java規范以及新的Java技術規范。對于JCP而言,如果要完成一項Java規范請求(Java Specification Request, JSR)的話,需要具備規范文檔,可參考的實現以及通過TCK測試。任何人如果想使用一項申請JSR的新技術的話,他要么使用RI提供許可的實現,要么自己實現一個并且保證通過TCK的測試。

  JVM結構

  Java編寫的代碼會按照下圖的流程來執行

  圖 1: Java代碼執行流程.

  類裝載器裝載負責裝載編譯后的字節碼,并加載到運行時數據區(Runtime Data Area),然后執行引擎執行會執行這些字節碼。

  類加載器(Class Loader)

  Java提供了動態的裝載特性;它會在運行時的第一次引用到一個class的時候對它進行裝載和鏈接,而不是在編譯期進行。JVM的類裝載器負責動態裝載。Java類裝載器有如下幾個特點:

  層級結構:Java里的類裝載器被組織成了有父子關系的層級結構。Bootstrap類裝載器是所有裝載器的父親。

  代理模式:基于層級結構,類的裝載可以在裝載器之間進行代理。當裝載器裝載一個類時,首先會檢查它是否在父裝載器中進行裝載了。如果上層的裝載器已經裝載了這個類,這個類會被直接使用。反之,類裝載器會請求裝載這個類。

  可見性限制:一個子裝載器可以查找父裝載器中的類,但是一個父裝載器不能查找子裝載器里的類。

  不允許卸載:類裝載器可以裝載一個類但是不可以卸載它,不過可以刪除當前的類裝載器,然后創建一個新的類裝載器。

  每個類裝載器都有一個自己的命名空間用來保存已裝載的類。當一個類裝載器裝載一個類時,它會通過保存在命名空間里的類全局限定名(Fully Qualified Class Name)進行搜索來檢測這個類是否已經被加載了。如果兩個類的全局限定名是一樣的,但是如果命名空間不一樣的話,那么它們還是不同的類。不同的命名空間表示class被不同的類裝載器裝載。

下圖展示了類裝載器的代理模型。

  圖 2: 類加載器代理模型

  當一個類裝載器(class loader)被請求裝載類時,它首先按照順序在上層裝載器、父裝載器以及自身的裝載器的緩存里檢查這個類是否已經存在。簡單來說,就是在緩存里查看這個類是否已經被自己裝載過了,如果沒有的話,繼續查找父類的緩存,直到在bootstrap類裝載器里也沒有找到的話,它就會自己在文件系統里去查找并且加載這個類。

  啟動類加載器(Bootstrap class loader):這個類裝載器是在JVM啟動的時候創建的。它負責裝載Java API,包含Object對象。和其他的類裝載器不同的地方在于這個裝載器是通過native code來實現的,而不是用Java代碼。

  擴展類加載器(Extension class loader):它裝載除了基本的Java API以外的擴展類。它也負責裝載其他的安全擴展功能。

  系統類加載器(System class loader):如果說bootstrap class loader和extension class loader負責加載的是JVM的組件,那么system class loader負責加載的是應用程序類。它負責加載用戶在$CLASSPATH里指定的類。

  用戶自定義類加載器(User-defined class loader):這是應用程序開發者用直接用代碼實現的類裝載器。

  類似于web應用服務(WAS)之類的框架會用這種結構來對Web應用和企業級應用進行分離。換句話來說,類裝載器的代理模型可以用來保證不同應用之間的相互獨立。WAS類裝載器使用這種層級結構,不同的WAS供應商的裝載器結構有稍許區別。

  如果類裝載器查找到一個沒有裝載的類,它會按照下圖的流程來裝載和鏈接這個類:

  圖 3: 類加載的各個階段

  每個階段的描述如下:

  Loading: 類的信息從文件中獲取并且載入到JVM的內存里。

  Verifying:檢查讀入的結構是否符合Java語言規范以及JVM規范的描述。這是類裝載中最復雜的過程,并且花費的時間也是最長的。并且JVM TCK工具的大部分場景的用例也用來測試在裝載錯誤的類的時候是否會出現錯誤。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97