中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java虛擬機

發布時間:2020-07-24 04:14:52 來源:網絡 閱讀:570 作者:afeiye 欄目:編程語言

內存分配以及回收

Java虛擬機運行時數據區,分為以下幾個模塊,包含所有線程共有的數據區和線程單獨享有的數據區。
Java虛擬機

  1. 程序計數器:字節碼行號,通過這個計數器來選取下一條需要執行的指令,線程獨有。
  2. 虛擬機棧:線程私有。方法在執行時會創建一個棧幀,用于存儲局部變量表等。局部變量表中存放了編譯器可知的基本數據類型、對象引用、returnAddress(指向了一條字節碼指令的地址)
  3. 本地方法棧:與虛擬機棧類似,只不過這個地方是為native方法服務。
  4. 堆:線程共用。存放對象實例。
  5. 方法區:線程共用。存儲已經被虛擬機加載的類信息、常量、靜態變量等。
  6. 運行時常量池:用于存放編譯期生成的字面量和符合引用。字面量就是我們所說的常量概念,如文本字符串、被聲明為final的常量值等。符號引用是一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可,一般包括下面三類常量:類和接口的全限定名、字段的名稱和描述符、方法的名稱和描述符。

Java虛擬機
JVM通過根搜索算法來判定對象是否可以回收,一般對于不能從根(GC Roots)搜索到的對象是可以被回收的。
能夠被作為GC Roots對象有:虛擬機棧本地變量表中引用的對象(也就是正在調用的方法中引用的);方法區中靜態屬性或常量引用的對象;本地方法棧引用的對象。


可以被回收的對象并不一定絕對被回收,JVM先做一次標記和篩選,把那些覆蓋了finalize方法的對象篩選出來然后觸發finalize方法,如果在finalize方法中對象復活,則不回收,否則回收,且finalize方法僅會被觸發一次。


垃圾回收算法

  1. 標記-清除:把標記為待回收的對象空間清除,容易造成大量空間碎片;
  2. 復制算法:將內存分為三個區域,一個較大的eden區和兩個較小的survivor區。每次GC都把存活的對象挪到其中一個servivor區,然后把eden全部清除。只對每次GC時存活對象較少時比較有效,適用于新生代;
  3. 標記-整理:把標記后存活的對象向一個方向移動,然后清除其它空間。比較適合老年代。

內存分配與回收策略

  1. 對象默認優先分配在新生代;
  2. 大對象直接分配到老年代;
  3. 長期存活的對象轉移到老年代:虛擬機給每個對象定義一個對象年齡,沒發生一次minor GC,年齡就增加一次,超過默認值之后就會進入到老年代。
  4. 動態對象年齡判定:對象不一定是必須到了默認年齡才能進入老年代,如果一個eden區中所有相同年齡的對象大小綜合超過eden一半的空間,那么大于等于這個年齡的對象也會進入老年代。

類文件結構

class文件是二進制組成的,class有兩種數據類型:無符號數和表。
無符號數是基礎數據類型,其中u1表示1個字節、u2表示2個字節(一個字節8個bit,而4個bit可以表示1個16進制的數,也就是說1個字節可以用2個16進制數表示);
表是由多個無符號數或其它表構成的。
Java虛擬機

  1. magic是4個字節,也就是8個16進制數,固定為CAFEBABE;后面分別是兩個版本號。
  2. 常量池:跟著版本號之后的就是常量池(字面量和符號引用)。由于無法確認一個類中常量池有多少常量,所有先有一個值來標志有多少個,然后再是常量具體信息。
  3. 訪問標志:常量池之后跟著的是2個字節的訪問標志。需要被標志的內容包括:是否public、是否final、是否abstract、是類或接口
  4. 訪問標志之后是類索引(用于確定該類的全限定名)、父類索引(用于確定父類的全限定名)、接口所有集合(實現的接口可能不止一個)
  5. 字段表集合:描述接口或類中聲明的變量,包含類變量和實例變量。
  6. 方法表集合:描述類或接口中聲明的fangfa。
  7. 屬性表結合:
    code屬性:java方法體中的代碼經javac編譯后會存儲在code屬性中(接口中方法或抽象方法沒有code屬性)
    Exceptions屬性:列舉出方法throws后面拋出的異常;
    其它各屬性不再一一列舉。

類加載機制

Java虛擬機
類加載的時機
主動引用的幾種情況才會加載(前提是此類沒有被加載過)

  1. new一個對象、引用類的static變量(final變量除外)、調用類的static方法;
  2. 對類進行反射調用時;
  3. 初始化一個類時,如果父類沒有被初始化,則先初始化父類;
  4. 虛擬機啟動時,初始化包含main方法的那個類

被動引用不會觸發初始化

  1. 調用父類靜態方法,不會初始化子類;
  2. 通過數組定義引用類,不會觸發初始化;
  3. 引用靜態常量不會觸發。

加載過程

  1. 通過一個類全限定名獲取定義此類的二進制字節流(一般是class文件)
  2. 將二進制字節流轉化為方法區中的運行時數據結構
  3. 在內存(堆)中生成這個類的Class類的對象,作為方法區這個類的各個數據的訪問入口

連接過程

  1. 驗證階段:文件格式驗證(是否符合Class文件規范)、元數據驗證(是否符合java語法規范)、字節碼驗證(確保語義是符合邏輯的)、符合引用驗證。
  2. 準備階段:正式為類變量分配內存并設置初始值。
    有兩點需要注意:
    一,此處只為類變量分配內存(static修飾的),不包含實例變量;
    二,設置的初始值是這個類型的0值,不是實際值(但被final修飾的賦的就是實際值)
  3. 解析階段:將符合引用替換為直接引用

初始化過程
初始化過程主要是執行類構造器<cinit>方法

  1. <cinit>方法主要是手機所有類變量的賦值動作,和靜態語句塊(staic {});
  2. 虛擬機會保證<cinit>方法在父類中先調用,這樣說明父類的static語句塊要比子類的static變量賦值操作先執行,以下代碼中,字段B的值將會是2Java虛擬機
  3. 這也說明了一個問題:new一個對象時,靜態變量賦值和靜態語句塊會在類的構造方法前執行。

類加載器

  1. 比較兩個類對象是否相等,只有加載兩個類加載器的完全一樣,才有意義;
  2. 如果一個類加載器收到一個類加載請求,它首先會請求委派給父類加載器完成,父類無法完成時,子類加載器才進行加載。

虛擬機字節碼執行引擎

Java虛擬機
運行時棧幀結構

  1. 局部變量表:存放方法參數和局部變量。每個變量以slot為單位,slot可以復用Java虛擬機注意,如果沒有int a = 0這一行代碼,placeholder是不會被回收的,因為如果不加這行代碼,就沒有任何對局部變量表的讀寫操作,這個slot就不會被占用。
  2. 操作數棧:方法執行過程中,會有各種字節碼出棧入棧
  3. 動態鏈接:一部分符合引用在類加載時轉化為直接引用,這是靜態機械;而一部分則是運行時轉化為直接應用,這叫動態鏈接

方法調用和分派

  1. 所有的方法在Class文件中都是一個符合引用,而一部分方法在類加載時就直接解析為直接引用。這種方法必須是“編譯時已知,運行時不可變”,就是靜態方法和私有方法兩大類
  2. 靜態分派:依賴靜態類型來定位方法執行版本稱為靜態分派,典型應用是重載。Java虛擬機
    Human是靜態類型,后面的Man和Women則是實際類型。
    靜態類型在編譯器可知,而動態類型則是在運行時才能知道。
  3. 動態分派:運行期間根據實際類型來確定方法執行版本,典型應用是覆蓋。Java虛擬機
    結果是
    Java虛擬機

內存模型及線程安全

Java虛擬機
JMM規定所有內存都存儲于主內存中,每條線程還有自己的工作內存。
變量的讀取、賦值操作必須在工作內存中進行。
內存直接的交互操作,主要有以下8種操作:
Java虛擬機
Java虛擬機
8種操作需要滿足以下規則
Java虛擬機


volatile關鍵字

  1. volatile關鍵字保證了變量的所有線程的可見性,但并非是線程安全的。
    兩種情況下是線程不安全的:
    一,變量依賴于自身(比如i++之類的)
    二,變量依賴于其它變量(比如i=a+3)
  2. volatile禁止語義重排序
  3. volatile的具體實現
    Java虛擬機
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

龙川县| 南部县| 无为县| 汤阴县| 仙桃市| 汝南县| 平定县| 紫云| 江北区| 灵璧县| 雷波县| 武冈市| 原平市| 义马市| 固阳县| 白城市| 措勤县| 酉阳| 伊宁县| 太仆寺旗| 苏尼特右旗| 禹城市| 札达县| 吉木萨尔县| 石台县| 呼伦贝尔市| 涿州市| 明星| 北宁市| 吴堡县| 梅州市| 方城县| 陵水| 洪湖市| 巍山| 天等县| 集贤县| 墨江| 安庆市| 涿州市| 始兴县|