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.直接指針