成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

談java中類的加載、鏈接和初始化

開發 后端
本文介紹的是java中的類的類的加載、鏈接和初始化等相關的問題,希望對你有幫助,一起來看吧!

Java字節代碼的表現形式是字節數組(byte[]), 而Java類在JVM中的表現形式是java. lang. Class類的對象。 一個Java類從字節代碼到能夠在JVM中被運用, 需要經過加載、鏈接和初始化這三個步驟。

這三個步驟中, 對開發人員直接可見的是Java類的加載, 通過運用Java類加載器(class loader)可以在運行時辰靜態的加載一個Java類;而鏈接和初始化則是在運用Java類之前會發生的舉措。 本文會詳細引見Java類的加載、鏈接和初始化的進程。

Java類的加載

Java類的加載是由類加載器來完成的。 普通來說, 類加載器分成兩類:啟動類加載器(bootstrap)和用戶自定義的類加載器(user-defined)。 兩者的區別在于啟動類加載器是由JVM的原生代碼實現的, 而用戶自定義的類加載器都繼承自Java中的java. lang. ClassLoader類。 在用戶自定義類加載器的部分, 普通JVM都會提供一些根本實現。 應用順序的開發人員也可以依據需要編寫自己的類加載器。 JVM中最常運用的是零碎類加載器(system), 它用來啟動Java應用順序的加載。 通過java. lang. ClassLoader的getSystemClassLoader()方法可以獲取到該類加載器對象。 

類加載器需要完成的最終功能是定義一個Java類, 即把Java字節代碼轉換成JVM中的java. lang. Class類的對象。 但是類加載的進程并不是這么簡單。 Java類加載器有兩個比較重要的特征:層次組織構造和代理形式。 層次組織構造指的是每個類加載器都有一個父類加載器, 通過getParent()方法可以獲取到。 類加載器通過這種父親-后代的方式組織在一起, 構成樹狀層次構造。 代理形式則指的是一個類加載器既可以自己完成Java類的定義任務, 也可以代理給其它的類加載器來完成。

由于代理形式的存在, 啟動一個類的加載進程的類加載器和最終定義這個類的類加載器能夠并不是一個。 前者稱為初始類加載器, 然后者稱為定義類加載器。 兩者的關聯在于:一個Java類的定義類加載器是該類所導入的其它Java類的初始類加載器。 比方類A通過import導入了類 B, 那么由類A的定義類加載器負責啟動類B的加載進程。

普通的類加載器在嘗試自己去加載某個Java類之前, 會首先代理給其父類加載器。 當父類加載器找不到的時候, 才會嘗試自己加載。 這個邏輯是封裝在java. lang. ClassLoader類的loadClass()方法中的。 普通來說, 父類優先的戰略就足夠好了。 在某些狀況下, 能夠需要采取相反的戰略, 即先嘗試自己加載, 找不到的時候再代理給父類加載器。

這種做法在Java的Web容器中比較常見, 也是Servlet規范推薦的做法。 比方, Apache Tomcat為每個Web應用都提供一個獨立的類加載器, 運用的就是自己優先加載的戰略。 IBM WebSphere Application Server則允許Web應用選擇類加載器運用的戰略。

類加載器的一個重要用途是在JVM中為相同名稱的Java類創立隔離空間。 在JVM中, 判斷兩個類是否相同, 不僅是依據該類的二進制名稱, 還需要依據兩個類的定義類加載器。 只有兩者完全一樣, 才認為兩個類的是相同的。 因此, 即便是異樣的Java字節代碼, 被兩個不同的類加載器定義之后, 所失掉的Java類也是不同的。 假如試圖在兩個類的對象之間停止賦值操作, 會拋出java. lang. ClassCastException。

這個特性為異樣名稱的Java類在JVM中共存創造了條件。 在實際的應用中, 能夠會要求同一名稱的Java類的不同版本在JVM中可以同時存在。 通過類加載器就可以滿足這種需求。 這種技術在OSGi中失掉了廣泛的應用。

Java類的鏈接

Java類的鏈接指的是將Java類的二進制代碼合并到JVM的運行狀態之中的進程。 在鏈接之前, 這個類必需被成功加載。 類的鏈接包括驗證、準備和解析等幾個步驟。 驗證是用來確保Java類的二進制表示在構造上是完全正確的。 假如驗證進程出現錯誤的話, 會拋出java. lang. VerifyError錯誤。 準備進程則是創立Java類中的靜態域, 并將這些域的值設為默許值。 準備進程并不會執行代碼。

在一個Java類中會包含對其它類或接口的形式援用, 包括它的父類、所實現的接口、方法的形式參數和前往值的Java類等。 解析的進程就是確保這些被援用的類能被正確的找到。 解析的進程能夠會導致其它的Java類被加載。

不同的JVM實現能夠選擇不同的解析戰略。 一種做法是在鏈接的時候, 就遞歸的把所有依賴的形式援用都停止解析。 而另外的做規律能夠是只在一個形式援用真正需要的時候才停止解析。 也就是說假如一個Java類只是被援用了, 但是并沒有被真正用到, 那么這個類有能夠就不會被解析。 思索上面的代碼:

  1. public class LinkTest . . . {  
  2. public static void main(String[] args) . . . {  
  3. ToBeLinked toBeLinked = null;  
  4. System. out. println(Test link. );  
  5. }  

類 LinkTest援用了類ToBeLinked, 但是并沒有真正運用它, 只是聲明了一個變量, 并沒有創立該類的實例或是訪問其中的靜態域。 在 Oracle的JDK 6中, 假如把編譯好的ToBeLinked的Java字節代碼刪除之后, 再運行LinkTest, 順序不會拋出錯誤。 這是由于ToBeLinked類沒有被真正用到, 而Oracle的JDK 6所采用的鏈接戰略使得ToBeLinked類不會被加載, 因此也不會發現ToBeLinked的Java字節代碼實際上是不存在的。 假如把代碼改成ToBeLinked toBeLinked = new ToBeLinked();之后, 再按照相同的方法運行, 就會拋出異常了。 由于這個時候ToBeLinked這個類被真正運用到了, 會需要加載這個類。

Java類的初始化

當一個Java類第一次被真正運用到的時候, JVM會停止該類的初始化操作。 初始化進程的主要操作是執行靜態代碼塊和初始化靜態域。 在一個類被初始化之前, 它的直接父類也需要被初始化。 但是, 一個接口的初始化, 不會引起其父接口的初始化。 在初始化的時候, 會按照源代碼中從上到下的順序依次執行靜態代碼塊和初始化靜態域。 思索上面的代碼:

  1. public class StaticTest . . . {  
  2. public static int X = 10;  
  3. public static void main(String[] args) . . . {  
  4. System. out. println(Y); //輸入60  
  5. }  
  6. static . . . {  
  7. X = 30;  
  8. }  
  9. public static int Y = X * 2;  

在上面的代碼中, 在初始化的時候, 靜態域的初始化和靜態代碼塊的執行會從上到下依次執行。 因此變量X的值首先初始化成10, 后來又被賦值成30;而變量Y的值則被初始化成60。

Java類和接口的初始化只有在特定的機遇才會發生, 這些機遇包括:

創立一個Java類的實例。 如:MyClass obj = new MyClass()

調用一個Java類中的靜態方法。 如:MyClass. sayHello()

在頂層Java類中執行assert語句。 

通過Java反射API也能夠形成類和接口的初始化。 需要注意的是, 當訪問一個Java類或接口中的靜態域的時候, 只有真正聲明這個域的類或接口才會被初始化。 思索上面的代碼:

  1. class B . . . {  
  2. static int value = 100;  
  3. static . . . {  
  4. System. out. println(Class B is initialized. ); //輸入  
  5. }  
  6. }  
  7. class A extends B . . . {  
  8. static . . . {  
  9. System. out. println(Class A is initialized. ); //不會輸入  
  10. }  
  11. }  
  12. public class InitTest . . . {  
  13. public static void main(String[] args) . . . {  

創立自己的類加載器

在 Java應用開發進程中, 能夠會需要創立應用自己的類加載器。 典型的場景包括實現特定的Java字節代碼查找方式、對字節代碼停止加密/解密以及實現同名 Java類的隔離等。 創立自己的類加載器并不是一件復雜的事情, 只需要繼承自java. lang. ClassLoader類并覆寫對應的方法即可。 java. lang. ClassLoader中提供的方法有不少, 上面引見幾個創立類加載器時需要思索的:

  • defineClass():這個方法用來完成從Java字節代碼的字節數組到java. lang. Class的轉換。 這個方法是不能被覆寫的, 普通是用原生代碼來實現的。
  • findLoadedClass():這個方法用來依據名稱查找已經加載過的Java類。 一個類加載器不會重復加載同一名稱的類。
  • findClass():這個方法用來依據名稱查找并加載Java類。
  • loadClass():這個方法用來依據名稱加載Java類。
  • resolveClass():這個方法用來鏈接一個Java類。

這里比較 容易混淆的是findClass()方法和loadClass()方法的作用。 前面提到過, 在Java類的鏈接進程中, 會需要對Java類停止解析, 而解析能夠會導致以后Java類所援用的其它Java類被加載。 在這個時候, JVM就是通過調用以后類的定義類加載器的loadClass()方法來加載其它類的。 findClass()方規律是應用創立的類加載器的擴展點。 應用自己的類加載器應該覆寫findClass()方法來添加自定義的類加載邏輯。 loadClass()方法的默許實現會負責調用findClass()方法。 

前面提到, 類加載器的代理形式默許運用的是父類優先的戰略。 這個戰略的實現是封裝在loadClass()方法中的。 假如希望修改此戰略, 就需要覆寫loadClass()方法。 

上面的代碼給出了自定義的類加載的常見實現形式:

  1. public class MyClassLoader extends ClassLoader . . . {  
  2. protected Class findClass(String name) throws ClassNotFoundException . . . {  
  3. byte[] b = null//查找或生成Java類的字節代碼  
  4. return defineClass(name, b, 0, b. length);  
  5. }  

希望通過以上關于java中類的加載、鏈接和初始化三方面的介紹,能夠給你帶來幫助。

責任編輯:于鐵 來源: 互聯網
相關推薦

2020-11-02 07:02:10

加載鏈接初始化

2024-03-08 08:26:25

類的加載Class文件Java

2024-03-12 07:44:53

JVM雙親委托機制類加載器

2012-02-28 10:04:09

Java

2012-05-23 12:46:53

JavaJava類

2019-11-04 13:50:36

Java數組編程語言

2012-04-09 13:43:12

Java

2013-03-04 11:10:03

JavaJVM

2011-06-17 15:29:44

C#對象初始化器集合初始化器

2011-06-09 14:13:06

C++JAVA缺省初始化

2023-12-18 09:26:12

C++switchif

2022-03-30 08:19:12

JavaGroovy

2022-03-21 09:50:50

JavaGroovy映射Map

2012-03-13 13:38:42

Java

2021-04-01 10:01:55

JavaStringJava基礎

2023-10-06 20:57:52

C++聚合成員

2023-11-12 23:08:17

C++初始化

2022-01-04 19:33:03

Java構造器調用

2016-11-11 00:33:25

雙重檢查鎖定延遲初始化線程

2011-03-17 09:58:43

Java虛擬機JVM
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99精品亚洲国产精品久久不卡 | 欧美视频三区 | 一级片在线免费播放 | 欧美精品福利 | 国产精品久久久久久久久大全 | 天天天操操操 | 午夜激情视频 | 亚洲女优在线播放 | 日本精品视频在线 | 激情五月婷婷综合 | 日韩免费高清视频 | 免费午夜电影 | 91视在线国内在线播放酒店 | 伊人网站 | 成人在线免费观看视频 | 精精国产xxxx视频在线播放 | 国产欧美综合在线 | 91精品一区二区三区久久久久 | 久久一二 | 国产精品不卡一区 | 久久亚洲欧美日韩精品专区 | 国产精品视频网站 | 国产日韩欧美在线观看 | 国产精品久久精品 | 黄色片网站国产 | 欧美一级二级三级视频 | 国产在线不卡 | 成人久久久| 精品一区二区三区在线观看 | 国产视频中文字幕 | 日韩欧美一区二区三区免费观看 | 国偷自产av一区二区三区 | 国产99久久久国产精品 | 国产一区不卡在线观看 | 日韩中文字幕网 | 午夜合集 | 国产一区二区三区久久久久久久久 | 国产精品区一区二区三 | 成人三级在线观看 | 日韩av在线免费 | 综合色婷婷|