1. 程式人生 > >java中的對象內存分配和訪問

java中的對象內存分配和訪問

裏的 指針 區域 線程安全 緩沖區 ref 只需要 部分 直接

對象的創建

java中對象遇到new命令會在堆上分配內存,有2種方式分配內存,如果gc回收具有壓縮選項,那麽就采用指針碰撞。

指針碰撞,如果內存是規整的,已經被使用的在一邊,未使用的在一邊,中間用指針分割,如果需要創建對象,就移動指針,移動的大小和創建的對象大小一致。

另一種是采用"空閑列表",gc回收不具有壓縮選項,虛擬機會維護一個"空閑列表",記錄哪些內存是可用的,需要創建對象,就在列表中尋找哪些內存可以用來創建對象。

由於對象的創建在虛擬機中是十分頻繁的,所以存在線程不安全的情況。為了避免發生這種事情,有2種方式保證創建對象的線程安全。一種是分配內存的操作是同步的,這樣就保證了同一時刻只進行一個對象的內存分配。另一種是分配內存的操作按線程劃分在不同區間內。虛擬機開始時會給每個線程分配本地線程緩沖區域,如果一個線程需要更大的內存,就會在該線程內分配內存。

對象在內存中的分配

對象在內存中分為3個部分,對象頭,實例數據和對其填充。

對象頭包含2個部分,對象運行時數據和類型指針。如果是數組,還會有一個部分包含數組的長度。

實例數據就是實例化對象裏的數據。

對其填充,虛擬機要求java對象的開始地址必須是8字節的整數倍,就是大小是8字節的整數倍(深入理解jvm裏描述的)。對象頭是8字節的,如果實例數據部分不滿足8字節的整數倍,那麽對其填充的作用就是補齊,形成整數倍。

對象在內存中的訪問定位

java對象會在棧上存在指向對象的指針。指向對象的方式有2種。一種是通過句柄,另一種是直接指針。

采用句柄指向對象,首先棧中的reference會指向句柄池,句柄池內包含指向實例對象的指針和類型對象指針。這種方式的好處是,實例對象的地址改變只需要更新句柄池中的對象內容即可。

直接指針,顧名思義,就是直接指向堆中和方法區中的實例對象和類型對象了。這種方式的好處就是速度很快,不需要通過中間方式尋找對象。

java中的對象內存分配和訪問