国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

高級應用——Java動態的程序設計

2019-11-18 12:01:20
字體:
來源:轉載
供稿:網友

  類和類的裝載
  
  我們來看一下類以及它們被JVM裝載的時候做了些什么?
  
  在這個新的有關動態的java編程特征的系列文章中,將會看到在正在執行的Java應用程序的背后發生了些什么。企業級Java專家Dennis Sosnoski給出了Java二進制格式和發生在JVM內部的類中的事情。遵循這條路線,他介紹正在裝載的類所影響的范圍(從正在運行的一簡單的Java應用程序所必須的大量的類到在J2EE和類似的復雜的框架結構中類裝載器沖突所可能導致的問題)。
  
  這篇文章揭示了Java動態編程這組主題所包含的一系列的新的知識。這些主題包括從Java二進制類文件格式的結構到使用反射訪問運行時的元數據,以及所有的在運行時編輯和構造新的類的方法。貫穿這個材料的全部基本路線是Java平臺的編程思想,是比用其它直接編譯成本地代碼的語言更加動態的工作。假如你理解了這些動態的特征,你就可用Java語言做一些用其它的主流的編程語言所不能做的事情。
  
  在這篇文章中。我介紹了位于Java平臺的動態特征之下的一些基本概念。這些概念圍繞用于描述Java類的二進制格式,包括類被裝載進JVM(Java虛擬機)時所發生的事情。這篇文件不僅為理解這個系列主題的其它文章提供基礎,同時也演示了一些非常實際的在Java平臺上工作的開發人員所關心的事情。
  
  一個類的二進制形式
  
  用Java語言的開發人員通常不必關心通過編譯器運行他們的源代碼時所發生的一些細節問題。在這個系列主題中。我會介紹許多有關從源代碼到可執行的程序這個過程的背后細節,因此,我們先來看一下編譯器所產生的二進制類。
  
  二進制類的格式實際上是被JVM(Java虛擬機)規范定義的。正常的類的描述是一個編譯器利用Java語言的源代碼生成的,并且通常被保存在一以.class為擴展名的文件中。但是這些特征都不是本質的。其它的一些編程語言已經被開發使用Java的二進制類的格式,并且,因為一些目的,新的類的描述被創建并且被直接裝載進一個正在執行的JVM中。但是JVM所關心的,重要的不是這些源代碼或它是怎樣被存儲的,而是這個格式自身。
  
  因此,先來這種類格式看上去象什么呢?下面(List 1.)列出了一個非常短的類的源代碼,緊跟著是用編譯器輸出的這個類文件的一部分十六進制的顯示:
  
  List 1.Hello.java的源代碼和(部分)二進制表示
  public class Hello
  {
  public static void main(String[] args) {
  System.out.  }
  }
  
  0000: cafe babe 0000 002e 001a 0a00 0600 0c09 ................
  0010: 000d 000e 0800 0f0a 0010 0011 0700 1207 ................
  0020: 0013 0100 063c 696e 6974 3e01 0003 2829 .....<init>...()
  0030: 5601 0004 436f 6465 0100 046d 6169 6e01 V...Code...main.
  0040: 0016 285b 4c6a 6176 612f 6c61 6e67 2f53 ..([Ljava/lang/S
  0050: 7472 696e 673b 2956 0c00 0700 0807 0014 tring;)V........
  0060: 0c00 1500 1601 000d 4865 6c6c 6f2c 2057 ........Hello, W
  0070: 6f72 6c64 2107 0017 0c00 1800 1901 0005 orld!...........
  0080: 4865 6c6c 6f01 0010 6a61 7661 2f6c 616e Hello...java/lan
  0090: 672f 4f62 6a65 6374 0100 106a 6176 612f g/Object...java/
  00a0: 6c61 6e67 2f53 7973 7465 6d01 0003 6f75 lang/System...ou
  ...
  
  二進制的內部
  
  List1中所顯示的二進制類的表示的第一件事情是標識Java二進制類的格式的“café babe”簽名,這個簽名只是一種確認實際請求的Java類的格式的一個實例的數據塊的簡易方法。每個Java的二進制類,即使在不同的文件系統上,也需要用這四個字節開始。
  
  數據的其它部分不是很有趣。跟在簽名后面是一對類格式的版本號(在這個例子中,用1.4.1javac編譯生成的時候,會產生次版本為0、主版本為46------十六進制的形式是0x2e的版本號),然后是常量池中的條目的計數。跟在條目計數(在這個例子中是26,或0x001a)后面的是實際的常量池數據。這是保存所有類定義所使用的常量的地方。它包括類和方法的名字、簽名以及字符串(這些字符串是你能夠認可的在十六制的存放處的正確性的文本解釋)、以及連同在一起的各種二進制值。
  
  在常量池中項目是可變長度的,每個項目的第一個字節標識了項目的類型和它應該怎樣被解碼。我不打算對這些內容做具體介紹,假如你有愛好以實際的JVM規范開始,這里有許多有用參考。要害點是常量池包含了所有的對其它類和這個類所使用的方法的引用,還有這個類自身以及它的方法的實際定義。盡管平均值可能會少一些,但是常量池的大小很輕易的超過二進制類的在小的一半或更多。
  
  跟在常量池后面是幾個引用常量池條目的項目,它們是類本身,它的超類以及接口。這些項目的后面是有關字段和方法的信息,這些信息是做為復合結構來描述自己的。對于方法的可執行代碼以代碼屬性(code attributes)的形式被包含在方法的定義中。這種代碼是JVM的指令形式,通常叫做字節碼(bytecode),這是下一節的主題之一。
  
  在Java類的格式中屬性(Attributes)用來做為幾種定義的用途,包括已經提到的字節碼(bytecode),用于字段的常量值,異常處理,以及調試信息。但是,屬性(Attributes)不只有這些可能的用途。從一開始,JVM規范要求JVMs(Java虛擬機)忽略未知類型的屬性。這種要求對于屬性的使用提供了靈活性,使得它在將來能夠服務于其它的用途,例如提供與用戶類一起工作的框架所需要的元信息------這是一種Java源于C#語言所廣泛使用的方法。不幸的是,no hook have yet been provided for making of this flexibility at the user level.
  
  字節碼和堆棧
  
  組成類文件的可執行部分的字節碼是適應特定類型計算機(JVM)是的實際的機器碼,這所以叫做虛擬機是因為它是用軟件來設計實現的,而不是硬件。每個運行在JVM上的應用程序都是建立在這種機器的一種實現。
  
  虛擬機實際上相當的簡單,它使用堆棧結構,這就意味著它們在被使用之前指令操作要被裝載進一個內部的堆棧。指令集包括所有的一般的算術運算和邏輯操作,還有有條件和無條轉移,裝載/存儲,調用/返回,堆棧的維護,以及幾種非凡的指令類型。包括立即數的一些指令被直接編碼進指令,另外一些直接從常量池引用值。
  
  雖然虛擬機是簡單的,但執行起來卻不是這樣的,第一代JVM基本上是虛擬機的字節碼的解析器,相對而言,比較簡單,但卻碰到嚴重的性能問題———解析代碼總是要比執行本地代碼花費更長的時間。為了減少這些性能問題,第二代JVM添加了即時(JIT)
翻譯。JIT技術是在Java字節碼第一次執行之前把它編譯成本地代碼,從而為重復執行提供了更好的性能。當前的JVM做的更好,它使用相應的技術來監控程序的執行并且選擇性使使用代碼得到優化。
  
  裝載類
  
  把源代碼編譯成本地代碼的語言(如C和C++)在源代碼被編譯之后通常需要鏈接這樣的步驟。這種鏈接過程把獨立編譯的源文件連同共享類庫的代碼合并到一起,從而形成一個可執行的程序。Java語言是不同的,使用Java語言,編譯器生成的類文件一般情況下單獨保存的,直到它們裝載進一個JVM為止,即使是建立一個JAR文件也不會改變這種情況———JAR文件只是類文件的一個容器。
  
  優于一個分開的步驟,JVM把類裝載進內存的時候,鏈接類成為JVM所要執行的工作的一部分。這樣就可以在初始化裝載的時候增加一些系統開銷,但是也為Java應用程序提供了高級的靈活性。例如,應用程序可以使用直到運行時才知道的實際實現的接口來編寫。這種后期綁定(late binding)的方法來裝配一個應用程序在Java平臺中被廣泛使用,servlets就是一個普通的例子。
  
  對于裝載類的規則在JVM規范的細節中被清楚的說明了。基本原則是類只有在需要的時候才被裝載(或者至少是顯示的裝載,JVM的這種方法在實際裝載過程中有一些靈活性,但是必需保持一個固定的類初始化的順序)。每個被裝載的類可以有其它的它所依靠的類,因此裝載過程是遞歸的。在Listing 2中的類顯示了這種遞歸裝載是怎樣工作的。這個Demo類包含了一個簡單的創建Greeter類的一個實例并且調用這個類的greet方法的main方法。Greeter類的構造器創建了一個Message的實例,然后它在greet方法中使用這個Message實例。
  
  Listing 2用于類裝載演示的源碼
  public class Demo
  {
  public static void main(String[] args) {
  System.out.println("**beginning execution**");
  Greeter greeter = new Greeter();
  System.out.println("**created Greeter**");
  greeter.greet();
  }
  }
  
  public class Greeter
  {
  private static Message s_message = new Message("Hello, World!");
  
  public void greet() {
  s_message.print(System.out);
  }
  }
  
  public class Message
  {
  private String m_text;
  
  public Message(String text) {
  m_text = text;
  }
  
  public void print(java.io.PrintStream ps) {
  ps.println(m_text);
  }
  }
  
  設置java命令的命令行參數為-verbose:class,這樣就可打印類裝載過程的軌跡。Listing 3顯示了使用這個參數的來運行Listing 2時的部分輸出:
  [Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
  [Opened /us

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 潍坊市| 湖北省| 休宁县| 全椒县| 长垣县| 肥城市| 英超| 惠安县| 林芝县| 西城区| 井陉县| 浪卡子县| 阿拉善盟| 太仓市| 泰来县| 通州市| 锦屏县| 潜江市| 措勤县| 内黄县| 盐边县| 湘潭县| 拉孜县| 交口县| 赣榆县| 乌兰察布市| 万荣县| 翁牛特旗| 探索| 拜城县| 波密县| 松溪县| 天峻县| 桃江县| 汽车| 黎城县| 潍坊市| 闵行区| 昌都县| 邢台市| 兴文县|