深入理解java虛擬機讀書筆記(二)

java和C++在內存動態分配和垃圾收集技術方面明顯的區別

一、概述

    對於C、C++從事人員來說,在內存管理領域,他們既是擁有最高權利的皇帝,又是從事最基礎工作的勞動人民,即擁有每一個對象的所有權,有負責着每一個對象生命開始到終結的維護責任

    對於java程序員來說,在虛擬機自動內存管理機制的幫助下,,不再需要爲每一個new操作去寫配對的delete/free代碼,不容易出現內存泄漏和溢出方面的問題,但也正是因爲把內存的控制權交給java虛擬機,所以一旦出現內存泄漏和溢出,如果不瞭解虛擬機如何使用內存的,那麼將很難排除錯誤

二、運行時數據區域

    1.程序計數器

    (1)一塊較小的內存空間,可以看作是當前線程所執行的字節碼的行號指示器,是線程私有的內存,生命週期和線程相同

    (2)在任意時刻,一個處理器只能處理一個線程的指令

   (3)如果線程正在執行的是一個java方法,這個計數器記錄的是當前線程執行的字節碼指令的地址,如果正在執行的是native方法,這個計數器值則爲空,

   (4)程序計數器是唯一一個在虛擬機規範中沒有任何OutOfMemoryError情況的區域

    2.java虛擬機棧

    (1)虛擬機棧描述的是java方法執行的內存模型,也是線程私有的,其生命週期和線程相同

    (2)每個方法執行的同時會建立一個棧幀用於存放局部變量表、操作數棧、動態鏈接和方法接口等信息,每一個方法從調用直至執行完成的過程,就對應着一個棧幀從虛擬機棧中入棧和出棧的過程

    (3)局部變量表存放了編譯器可知的各種數據類型、對象引用和returnAddress類型(指向了一條字節碼指令的地址)

    (4)64位長度的long和double類型會佔用兩個局部變量空間,其餘數據類型只佔用一個

    (5)局部變量表所需的內存空間在編譯期間完成分配,,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的,運行期間不會改變局部變量表的大小

    (6)存在兩種異常:StackOverFlowError 線程請求的棧的深度大於虛擬機所允許的深度;OutOfMemoryError 如果虛擬機棧可以擴展,同時在擴展的時候無法申請到足夠的內存

    3.本地方法棧

    (1)本地方法棧和虛擬機棧發揮的作用相似,只不過虛擬機棧爲虛擬機執行的java方法服務,而本地方法棧爲虛擬機使用到的本地方法服務

    (2)同虛擬機棧相同,本地方法棧也會拋出兩種異常

    4.java堆

    (1)對於大多數應用來說,java堆是java虛擬機管理的內存中最大的一塊,線程共享,虛擬機啓動的時候創建

    (2)內存區域的目的是存放對象實例,幾乎所有的對象實例都在這裏分配內存(所有對象實例和數組都要在堆上分配)

    (3)java堆是垃圾收集器管理的主要區域,,因此有時候被叫做GC堆,java堆可以分爲新生代和老年代

    (4)java堆中可能劃分出多個線程私有的分配緩衝區,,目的是更好的回收內存和更快的分配內存

    (5)Java堆可以處於物理不連續的內存空間中,只要邏輯連續就可以,在實現時既可以實現成固定大小的,也可以是可擴展的

    (6)堆中沒有內存完成分配,並且堆也無法擴展,會出現OutOfMemoryError

    5.方法區

    (1)各個線程共享的內存區域,用於存儲已被虛擬機加載了的類信息,常量,靜態變量以及即時編譯器編譯後的代碼等,

    (2)可以和java堆一樣不需要連續的內存和可以選擇固定大小和可擴展,還可以選擇不實現垃圾回收

    (3)當方法區無法滿足內存分配需求時,會出現OutOfMemoryError

    6.運行時常量池

    (1)方法區的一部分,運行時常量區相對於class文件常量區的一個重要特徵是具備動態性,運行期間也可以將新的變量放入池內

    (2)存在OutOfMemoryErro

    7.直接內存

    (1)直接內存並不是java虛擬機運行時數據區的一部分也不是Java虛擬機規範當中定義的內存區域,

    (2)他可以通過Native函數庫直接分配堆外內存,然後通過一個存放在java堆中的DirectByteBuffer對象做爲這塊內存的引用進行操作

三、對象的創建

    (1)虛擬機遇到一個New指令

    (2)首先檢查指令參數是否能在常量池中定位到一個類的符號引用

    (3)檢查這個符號引用對應的類是否已被加載、解析、初始化過

    (4)若沒有加載過,則需要加載

    (5)爲新生對象分配內存空間(指針碰撞||空閒列表)(所使用的垃圾收集器有沒有壓縮整理功能決定)

    (6)線程安全保證(對分配內存空間動作進行同步處理||把內存分配動作按照線程分配在不同的空間進行)

    (7)把分配到的內存空間初始化爲0

    (8)調用init方法

四、對象的內存佈局

    (1)對象頭:一部分用於存儲對象自身的運行時數據,另一部分是類型指針

    (2)實例數據:真正存儲的有效數據

    (3)對齊填補:自動內存管理系統要求對象的大小必須是8字節的整數倍,而對象頭剛好是8字節的整數倍,所以當實例對象沒有對齊時需要對齊填充補齊

五、對象訪問定位

    1.使用句柄:reference中存放的是穩定的句柄地址,當對象被移動時,只會改變句柄中的實例數據指針

    2.直接指針

    

發佈了30 篇原創文章 · 獲贊 1 · 訪問量 8389
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章