java - JVM


SUN官方站點介紹JVM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#G1Options

JVM內存結構

Java 虛擬機在執行 Java 程序的過程中會把他所管理的內存劃分爲若干個不同的數據區域。分別是:方法區、堆區、虛擬機棧、本地方法棧、程序計數器。
其中方法區和堆區是線程共享的;
虛擬機棧、本地方法棧和程序計數器是線程隔離的。
除了程序計數器都會產生內存溢出。
在這裏插入圖片描述

方法區

用於存放已被虛擬機加載的類型信息,常量,靜態變量、即時編譯後的代碼等信息。

方法區是線程間共享的,當兩個線程同時需要加載一個類時,只有一個類會請求ClassLoader加載,另一個線程會等待。

靜態代碼塊也在方法區,它在類加載期間運行。
思考:爲什麼全局變量放在靜態代碼塊中?
因爲在整個程序執行過程中,類只加載一次。那麼靜態代碼塊也只執行一次。

堆區

堆是Java 虛擬機所管理的內存中最大的一塊,它是被所有線程共享的區域,是在虛擬機啓動時創建的

堆裏面存放對象和數組實例

我們平常所說的垃圾回收,主要回收的就是堆區(還可能有方法區)。如果垃圾收集算法採用按代收集(目前大都是這樣),這部分還可以細分爲新生代和老年代(默認2:1,可修改)。

其中新生代又可劃分爲Eden區和2個Survivor區,即From Survivor與To Survivor(默認8:1:1,可修改),主要是爲了垃圾回收。所有的線程共享Java堆,在這裏還可以劃分線程私有的緩衝區(Thread Local Allocation Buffer,TLAF)。

堆內存結構如下圖結構:
在這裏插入圖片描述
堆只要求邏輯上是連續的,在物理空間上可以不連續。

虛擬機棧

線程 —> java虛擬機棧;
方法 —>棧幀(棧幀存儲在java虛擬機棧中)

虛擬機棧是線程私有的,生命週期與線程相同。創建線程的時候就會爲這個線程創建一個虛擬機棧。

虛擬機棧表示Java方法執行的內存模型,每調用一個方法,就會生成一個棧幀(Stack Frame)用於存儲方法的局部變量表、操作數棧、方法出口等信息,當這個方法執行完後,就會彈出相應的棧幀。

棧幀分爲以下幾個區域:局部變量表、操作數棧、動態連接、方法出口等。
平時我們所說的變量存在棧中,這句話說的不太嚴謹,應該說局部變量存放在java虛擬機棧的局部變量表中。java的八種基本類型的局部變量的值存放在虛擬機棧的局部變量表中,如果是引用型的變量,則只存儲對象的引用地址。

當用戶請求web服務器,每個請求開啓一個線程負責用戶的響應計算(每個線程分配一個虛擬機棧空間),如果併發量大時,可能會拋出OutOfMemoneyError異常,可以適當的把每個虛擬機棧的大小適當調小一點,減少內存的使用量來提高系統的併發量。當棧空間調小以後,又會引發方法調用深度的的問題。因爲,每個方法都會生成一個棧幀,如果方法調用深度很深就意味着棧裏面存放大量的棧幀,可能會拋出StackOverFlowError異常。

本地方法棧

本地方法棧與虛擬機棧類似,只是是執行本地方法時使用的。

程序計數器

類似於PC寄存器,是一塊較小的內存區域,通過程序計算器中的值尋找要執行的指令的字節碼,由於多線程間切換時要恢復每一個線程的當前執行位置,所有每個線程都有自己的程序計數器。這一區域不會由OutOfMemoryError。當執行java方法時,這裏存儲的執行的指令的地址,如果執行的是本地方法,這裏的值是Undefined。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章