java暢談2

今天主要看了JVM書中的第二章java內存區域和編程思想一書中的內部類。接下來談談自己的理解。


   先說說JVM吧。話說是一個運行平臺。在編譯器編譯產生的class文件會在JVM中被加載和解釋執行的。JVM有許多種早期的是SUN classic VM之後出現hotspot和BEA公司的JRockit、還有IBM的J9。他們都是JVM,但是我們現在接觸的是Hotspot,他是SUN公司的,不過現在是Oracle公司的了。
  1、 接下來講講java的內存動態分配和垃圾回收機制。這兩個特點是java區別c++的最大的原因。java的內存 區域分成了幾部分的數據區:方法區、堆、虛擬機棧、本地方法棧、程序計數器。
程序計數器:首先是線程隔離的。他可以看作是線程所執行的字節碼行號的指示器。字節碼解釋器會根據計數器來選取將要執行的語句。注意他是線程隔離的,每條線程都有自己的程序計數器。各個線程的計數器是互不影響的。這個區域是唯一沒有任何規定會出現OutMemoryError的區域。


虛擬機棧:也是線程隔離的。就是我們平常經常說的棧。主要用來存儲局部變量表、操作數棧、動態鏈接、方法出口等。局部變量表存放了編譯期出現的基本數據類型、對象引用(在hotspot中對象的引用就是堆中對象實例的絕對地址的值)。


本地方法棧:是線程隔離的,主要是爲了使用本地方法服務的。在hotspot中將本地方法棧和虛擬機棧是合二爲一的。


堆:首先是線程共享的。主要就是存放對象實例的。所有的對象實例和數組都在堆上分配的。同時堆也是垃圾收集機制管理的主要區域。


方法區:是線程共享的。在hotspot虛擬機中方法區也屬於堆的一部分。主要用於存儲已被虛擬機加載的類信息、常量、靜態變量即時編譯器編譯後的代碼。
運行常量池:是方法區的一部分。用於存放編譯期生成的各種字面量和符號的引用。
    2、Hotspot虛擬機對象
當虛擬機遇到new指令的時候,首先檢查能不能在常量池中找到該類的符號引用。順便檢查是否已被加載、解析和初始化過。如果沒有就進行相應的類加載。接下來虛擬機爲新對象分配內存。一般會由兩種分配方式:指針碰撞和空閒列表。通常採用的是空閒列表法。
對象在內存中的佈局分爲3塊區域:對象頭、實例數據和對齊填充。
對象頭:包含兩部分。一是存儲對象自身運行時的數據。另一部分是類型指針即對象指向它的類元數據的指針。虛擬機通過這個指針來確定這個對象是那個類的實例。
實例數據:代碼中所定義的各種類型的字段。無論是從父類繼承的,還是子類定義的都需要記錄下來。
對齊填充:僅僅是起佔位符的作用。由於hotspot VM要求對象的起始地址必須是8字節的整數倍。因此當對象實例數據沒有對齊時就需要通過對齊填充來補全。


  3、這一點很重要是java中不存在引用傳遞,只有值傳遞。在java程序中通過棧上的reference數據來操作堆上的具體對象。reference是一個指向對象的引用。hotspot在對象的訪問方式上使用的是直接地址。即reference數據存儲的就是堆中對象的絕對地址的值。
目前主流的訪問方式是:直接地址法和句柄訪問法。hotspot採用的是直接地址法。
發佈了45 篇原創文章 · 獲贊 31 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章