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

看了這篇你還不懂JVM 中的類加載機制?

云計算 虛擬化
驗證是連接階段的第一個步驟,驗證的目的是為了確保`.class`文件中的字節流所包含的信息是符合當前虛擬機的要求,并且不會危害到虛擬機自身的安全的。

[[326861]]

開門見山

首先引入一道面試題

 

看了這篇你還不懂JVM 中的類加載機制?

 

  • 錯誤答案:count1=1;count2=1
  • 正確答案:count1=1;count2=0

為神馬?為神馬?這要從java的類加載時機說起。

本來是準備把分析結果寫在最下面的但是怕大家沒有耐心看到最后我這邊先大概分析下,如果看不懂下面的分析。真心建議大家能看到最后,文章不算長。

  1. `Single single = Single.getInstance();`調用了類的`Single`調用了類的靜態方法,觸發類的初始化
  2. 類加載的時候在準備過程中為類的靜態變量分配內存并初始化默認值 `single=null count1=0,count2=0`
  3. 類初始化化,為類的靜態變量賦值和執行靜態代碼快。`single`賦值為`new Single()`調用類的構造方法
  4. 調用類的構造方法后`count=1;count2=1`
  5. 繼續為`count1`與`count2`賦值,此時`count1`沒有賦值操作,所有`count1`為1,但是`count2`執行賦值操作就變為0

類的加載時機

類從被加載到虛擬機內存中開始,直到卸載出內存為止,它的整個生命周期包括了:加載、驗證、準備、解析、初始化、使用和卸載這7個階段。其中,驗證、準備和解析這三個部分統稱為連接(linking)。

 

看了這篇你還不懂JVM 中的類加載機制?

 

其中加載、驗證、準備、初始化和卸載五個步驟的順序都是確定的,解析階段在某些情況下有可能發生在初始化之后,這是為了支持 Java 語言的運行期綁定的特性。

何時開始類的初始化

  1. 創建類的實例
  2. 訪問類的靜態變量(除常量【被final修辭的靜態變量】原因:常量一種特殊的變量,因為編譯器把他們當作值(value)而不是域(field)來對待。如果你的代碼中用到了常變量(`constant variable`),編譯器并不會生成字節碼來從對象中載入域的值,而是直接把這個值插入到字節碼中。這是一種很有用的優化,但是如果你需要改變final域的值那么每一塊用到那個域的代碼都需要重新編譯。
  3. 訪問類的靜態方法
  4. 反射如(`Class.forName("my.xyz.Test")`)
  5. 當初始化一個類時,發現其父類還未初始化,則先出發父類的初始化
  6. 虛擬機啟動時,定義了main()方法的那個類先初始化
  • 主動引用:上面這些種行為稱為對一個類的的主動引用,會觸發類的初始化
  • 被動引用:除上面五種主動引用之外,其他引用類的方式都不會觸發類的初始化,稱為類的被動引用

接口的加載過程與類的加載過程稍有不同。接口中不能使用`static{}`塊。當一個接口在初始化時,并不要求其父接口全部都完成了初始化,只有真正在使用到父接口時(例如引用接口中定義的常量)才會初始化。

被動引用例子

示例一

對于靜態字段,只有直接定義這個字段的類會被初始化,如果是通過子類引用父類的字段,父類會被初始化,子類不一定會被初始化,子類會不會被初始化 JVM 虛擬機規范并沒有明確規定,取決于虛擬機的具體實現

 

看了這篇你還不懂JVM 中的類加載機制?

 

上面代碼運行之后輸出結果如下所示

  1. SuperClass init! 
  2. The value is 24 

示例二

 

看了這篇你還不懂JVM 中的類加載機制?

 

上面代碼運行之后,并不會輸出 “SubClass init!“,因為在上面Demo#main()方法中,并沒有初始化SubClass類,而是初始化了一個SubClass[]數組類,SubClass[]數組類代表了一個元素類型為SubClass的一維數組,繼承自Object類,由newarray字節碼創建。

示例三

 

看了這篇你還不懂JVM 中的類加載機制?

 

上面代碼運行之后也并不會輸出”Constant init!“,因為這涉及到一個概念 —- “常量傳播優化”。雖然在代碼中Demo類引用了Constant類中的常量VALUE,但是在編譯階段,會將VALUE的實際值”Hello World!“放到Demo類中的常量池中,Demo類每次使用”Hello World!“常量的時候都會從自己的常量池中去找。Demo類不會持有Constant類的符號引用,所以Constant類也并不會被初始化。

類的加載過程

加載

在加載階段有三個步驟:

  1. 通過一個類的全限定名獲取定義此類的二進制字節流
  2. 將二進制字節流所代表的靜態存儲結構轉換為方法區中的運行時數據結構
  3. 在內存中生成一個代表此類的`java.lang.Class`的對象,作為方法區這些數據的訪問入口

在這個階段,有兩點需要注意:

  1. 并沒有規定從哪里獲取二進制字節流。我們可以從`.class`靜態存儲文件中獲取,也可以從`zip、jar`等包中讀取,可以從數據庫中讀取,也可以從網絡中獲取,甚至我們自己可以在運行時自動生成。
  2. 在內存中實例化一個代表此類的`java.lang.Class`對象之后,并沒有規定此`Class`對象是方法`Java`堆中的,有些虛擬機就會將`Class`對象放到方法區中,比如`HotSpot`。

驗證

驗證是連接階段的第一個步驟,驗證的目的是為了確保`.class`文件中的字節流所包含的信息是符合當前虛擬機的要求,并且不會危害到虛擬機自身的安全的。

`Java`語言本身是相對安全的語言,使用Java編碼是無法做到如訪問數組邊界以外的數據、將一個對象轉型為它并未實現的類型等,如果這樣做了,編譯器將拒絕編譯。但是,`Class`文件并不一定是由`Java`源碼編譯而來,可以使用任何途徑,包括用十六進制編輯器(如`UltraEdit`)直接編寫。如果直接編寫了有害的“代碼”(字節流),而虛擬機在加載該Class時不進行檢查的話,就有可能危害到虛擬機或程序的安全。

  1. 不同的虛擬機,對類驗證的實現可能有所不同,但大致都會完成下面四個階段的驗證:文件格式驗證、元數據驗證、字節碼驗證和符號引用驗證。文件格式驗證,是要驗證字節流是否符合Class文件格式的規范,并且能被當前版本的虛擬機處理。如驗證魔數是否0xCAFEBABE;主、次版本號是否正在當前虛擬機處理范圍之內;常量池的常量中是否有不被支持的常量類型……該驗證階段的主要目的是保證輸入的字節流能正確地解析并存儲于方法區中,經過這個階段的驗證后,字節流才會進入內存的方法區中存儲,所以后面的三個驗證階段都是基于方法區的存儲結構進行的。
  2. 元數據驗證,是對字節碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規范的要求。可能包括的驗證如:這個類是否有父類;這個類的父類是否繼承了不允許被繼承的類;如果這個類不是抽象類,是否實現了其父類或接口中要求實現的所有方法……
  3. 字節碼驗證,主要工作是進行數據流和控制流分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的行為。如果一個類方法體的字節碼沒有通過字節碼驗證,那肯定是有問題的;但如果一個方法體通過了字節碼驗證,也不能說明其一定就是安全的。
  4. 符號引用驗證,發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在“解析階段”中發生。驗證符號引用中通過字符串描述的權限定名是否能找到對應的類;在指定類中是否存在符合方法字段的描述符及簡單名稱所描述的方法和字段;符號引用中的類、字段和方法的訪問性(`private、protected、public、default`)是否可被當前類訪問

驗證階段對于虛擬機的類加載機制來說,不一定是必要的階段。如果所運行的全部代碼確認是安全的,可以使用`-Xverify:none`參數來關閉大部分的類驗證措施,以縮短虛擬機類加載時間。

準備

準備階段是為類的靜態變量分配內存并將其初始化為默認值,這些內存都將在方法區中進行分配。準備階段不分配類中的實例變量的內存,實例變量將會在對象實例化時隨著對象一起分配在Java堆中。

有幾點需要注意:

1.在方法區中分配內存的只有類變量(被`static`修飾的變量),而不包括實例變量,實例變量將會跟隨著對象在 Java 堆中為其分配內存

2.初始化類變量的時候,是將類變量初始化為其類型對應的`0`值,比如有如下類變量,在準備階段完成之后`val`的值是`0`而不是 `123`,為 `val`復制為`123`,是在后面要講的初始化階段之后

  1. //在準備階段value初始值為0 。在初始化階段才會變為123 。 
  2. public static int val=123; 

3. 對于常量,其對應的值會在編譯階段就存儲在字段表的`ConstantValue`屬性當中,所以在準備階段結束之后,常量的值就是`ConstantValue`所指定的值了,比如如下,在準備階段結束之后,`val`的值就是`123`了。

  1. public static final int val = 123; 

解析

解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。

符號引用(Symbolic Reference):符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現的內存布局無關,引用的目標并不一定已經加載到內存中。

直接引用(Direct Reference):直接引用可以是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。直接引用是與虛擬機實現的內存布局相關的,如果有了直接引用,那么引用的目標必定已經在內存中存在。

初始化

類的初始化階段才是真正開始執行類中定義的 Java 程序代碼。初始化說白了就是調用類構造器`()`的過程,在類的構造器中會為類變量初始化定義的值,會執行靜態代碼塊中的內容。下面將介紹幾點和開發者關系較為緊密的注意點

1. 類構造器`()`是由編譯器自動收集類中出現的類變量、靜態代碼塊中的語句合并產生的,收集的順序是在源文件中出現的順序決定的,靜態代碼塊可以訪問出現在靜態代碼塊之前的類變量,出現的靜態代碼塊之后的類變量,只可以賦值,但是不能訪問,比如如下代碼

 

看了這篇你還不懂JVM 中的類加載機制?

 

2. `()`類構造器和`()`實例構造器不同,類構造器不需要顯示的父類的類構造,在子類的類構造器調用之前,會自動的調用父類的類構造器。因此虛擬機中第一個被調用的`()`方法是 `java.lang.Object`的類構造器

3. 由于父類的類構造器優先于子類的類構造器執行,所以父類中的`static{}`代碼塊也優先于子類的`static{}`執行

4. 類構造器`()`對于類來說并不是必需的,如果一個類中沒有類變量,也沒有`static{}`,那這個類不會有類構造器`()`

5. 接口中不能有`static{}`,但是接口中也可以有類變量,所以接口中也可以有類構造器 `{}`,但是接口的類構造器和類的類構造器有所不同,接口在調用類構造器的時候,如果不需要,不用調用父接口的類構造器,除非用到了父接口中的類變量,接口的實現類在初始化的時候也不會調用接口的類構造器

6. 虛擬機會保證一個類的`()`方法在多線程環境中被正確地加鎖、同步,如果多個線程同時去初始化一個類,那么只有一個線程去執行這個類的類構造器`()`,其他線程會被阻塞,直到活動線程執行完類構造器`()`方法

 

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-06-16 00:57:16

JVM加載機制

2021-09-06 07:58:47

鏈表數據結構

2023-10-31 16:00:51

類加載機制Java

2023-08-09 09:03:49

CPU密集型運算

2021-05-06 15:59:27

Linux性能優化

2022-02-18 06:56:18

Wi-Fi路由器局域網

2017-03-08 10:30:43

JVMJava加載機制

2021-04-29 11:18:14

JVM加載機制

2017-09-20 08:07:32

java加載機制

2023-08-02 08:38:27

JVM加載機制

2020-02-24 21:50:24

瓶頸數據庫

2024-12-02 09:01:23

Java虛擬機內存

2024-03-12 07:44:53

JVM雙親委托機制類加載器

2022-10-08 08:34:34

JVM加載機制代碼

2021-12-28 12:01:59

Kafka 消費者機制

2021-05-28 11:54:29

MySQL數據庫主從復制

2019-07-31 15:56:57

Jvm虛擬機Content

2023-05-10 11:07:18

2025-07-01 07:41:37

Java類加載器雙親委派

2021-09-24 08:10:40

Java 語言 Java 基礎
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: av官网在线 | 中国黄色在线视频 | 国产精品1区2区3区 国产在线观看一区 | 精品国产一区二区三区久久久久久 | 国产日韩一区二区三免费高清 | 99精品视频在线观看 | 日本精品一区二区三区在线观看视频 | 成年人在线观看视频 | 正在播放国产精品 | 三级国产三级在线 | 爱草在线 | 日本视频一区二区 | 国产精品久久久久久亚洲调教 | 一区二区不卡 | 午夜精品一区二区三区在线播放 | 香蕉婷婷 | 四虎永久在线精品免费一区二 | 日本中出视频 | 69堂永久69tangcom | 日本精品视频在线 | 久久精品毛片 | 中文字幕免费在线 | 亚洲国产精品区 | 日韩欧美网 | 一区二区在线看 | av网站免费| 亚洲高清成人在线 | 羞羞视频在线观看 | 91av免费版| 亚洲一区二区国产 | 紧缚调教一区二区三区视频 | 欧美成人影院在线 | 91久久国产综合久久91精品网站 | 久久高清精品 | 福利片在线观看 | 日日夜夜视频 | 日本久久福利 | 一级在线| 精品久久久久久久久久久 | 日韩高清一区 | 夜夜撸av|