1. 程式人生 > >認識java虛擬機器(2)

認識java虛擬機器(2)

物件的建立:需要類的載入。物件建立圖:

<init>方法是程式碼塊(構造方法)

new類名和呼叫物件方法是可見的,

物件的記憶體分配。

堆是不連續的儲存空間,堆記憶體是規整的,用過的放一邊,沒用過的放在一邊。分配記憶體是指標移動的過程。

1.指標碰撞的記憶體分配方式:(java堆規整)

2.空閒列表:(java堆不規整)

1是使用的在一邊,沒有使用的在另一邊,如果是使用的和沒有使用的交錯在一起的情況,它會建立一張空閒列表,空閒的記憶體區域都在這張表裡,java堆的規整與否是由回收策略決定的

它會造成執行緒不安全問題(多執行緒一起發起多個請求,向空閒列表裡申請記憶體,便會造成記憶體混亂問題)

 

   1.執行緒同步(加鎖解鎖)

   2.

物件的結構:

header(物件頭)

     1.自身執行時資料【mark word】(雜湊值,GC分代年齡(為後面垃圾回收的各大演算法服務),鎖狀態標識,偏向時間戳,執行緒持有的鎖。。。。。。。。。)

更多詳情可以看:http://www.cnblogs.com/duanxz/p/4967042.html 

public class Object{
     public final native Class<?> getClass();
}

      2.型別指標(指向物件 “元資料” 的指標)

     

instanceData(資料例項)

         long, double放在一起

       short/char放在一起(相同大小會放在一起)

padding (對齊填充,物件大小必須要8個位元組)

 

 

 

物件訪問定位:

垃圾回收:

判定物件為垃圾的演算法

1.引用計數法:

在物件中新增一個引用計數器,當有地方引用到這個物件的時候,引用計數器的值就+1,當引用失敗的時候,計數器的值就-1

-verbose:gc(簡單列印垃圾回收的日誌資訊)

-XX:+PrintGCDetails (詳細列印gc垃圾回收日誌資訊)

public class Main {
	private Object instance;
    public Main() {
    	//手動開闢20兆的空間
    	//1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B(位元組byte)=8b(位元bit)
    	//1MB(Mebibyte,兆位元組,百萬位元組,簡稱“兆”)=1024KB(千位元組)= 2^20 byte=1024*1024 byte
    	byte [] m=new byte[20*1024*1024];
    }
	public static void main(String[] args) {
		Main m1=new Main();
		Main m2=new Main();
		m1.instance=m2;
		m2.instance=m1;
		m1=null;
		//銷燬物件1
		m2=null;
		//銷燬物件2
		System.gc();
		//手動呼叫垃圾回收器
	}

}

2.可達性分析演算法

從GCRoots節點出發,沿著引用鏈遍歷物件,為被遍歷的,便被判定為 垃圾(即物件沒有任何的引用指向它,就會被標記為垃圾物件

可作為GCRoots的物件

         1.1虛擬機器棧(這裡指虛擬機器棧中的區域性變量表)

         1.2方法區的類屬型所引用的物件

         1.3方法區中常量所引用的物件

         1.4本地方法棧中引用的物件

回收垃圾:

1.標記-清除演算法:

效率問題

空間問題

標記出要回收的物件

 複製演算法;

1.執行緒共享區:堆 (細分為:

         新生代(

                  1.1 Eden  中文為伊甸園,建立一個物件,就會被扔到這裡,新建立的就會在這裡無憂無慮的生活,但也是死神垃圾回收器最喜歡光顧的地方

                    1.2 Survivor 存活區

                    1.3 Tenured Gen  養老區)

--------------------------------------------------------------------------------------------------------------------------

      引用一段比喻:

JVM區域總體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(程式碼快取區)、Perm Gen(永久代)、Jvm Stack(java虛擬機器棧)、Local Method Statck(本地方法棧)。

JVM記憶體區域劃分 <wbr>EDEN <wbr>SPACE、SURVIVOR <wbr>SPACE、TENURED <wbr>GEN

HotSpot虛擬機器GC演算法採用分代收集演算法:

1、一個人(物件)出來(new 出來)後會在Eden Space(伊甸園)無憂無慮的生活,直到GC到來打破了他們平靜的生活。GC會逐一問清楚每個物件的情況,有沒有錢(此物件的引用)啊,因為GC想賺錢呀,有錢的才可以敲詐嘛。然後富人就會進入Survivor Space(倖存者區),窮人的就直接kill掉。

2、並不是進入Survivor Space(倖存者區)後就保證人身是安全的,但至少可以活段時間。GC會定期(可以自定義)會對這些人進行敲詐,億萬富翁每次都給錢,GC很滿意,就讓其進入了Genured Gen(養老區)。萬元戶經不住幾次敲詐就沒錢了,GC看沒有啥價值啦,就直接kill掉了。

3、進入到養老區的人基本就可以保證人身安全啦,但是億萬富豪有的也會揮霍成窮光蛋,只要錢沒了,GC還是kill掉。

分割槽的目的:新生區由於物件產生的比較多並且大都是朝生夕滅的,所以直接採用標記-清理演算法。而養老區生命力很強,則採用複製演算法,針對不同情況使用不同演算法。

非heap區域中Perm Gen中放著類、方法的定義,jvm Stack區域放著方法引數、局域變數等的引用,方法執行順序按照棧的先入後出方式。

--------------------------------------------------------------------------------------------------------------------------

)  方法區

2.執行緒獨享:棧  本地方法棧   程式計數器

複製演算法圖:

優化後的

標記整理清除演算法(用於老年代的垃圾回收) 

分代收集演算法:

記憶體分新生代和老年代,對於新生代,垃圾回收率較高的,會採用複製演算法,對於老年代,記憶體回收率較低的,會採用標記清除演算法。

 

 

 

 

 

垃圾收集器之Serial收集器(適用於客戶端):

最基本,發展最悠久

單執行緒垃圾收集器

 PraNew多執行緒收集器

Parallel Scavenge 收集器(適用於高併發情況)

採用複製演算法(新生代收集器)

多執行緒收集器

達到可控制的 吞吐量(cpu用於執行使用者程式碼的時間與cpu消耗的總時間的比值)

吞吐量=(執行使用者程式碼時間)/(執行使用者程式碼時間+垃圾回收所佔的時間)

-XX:MaxGFPauseMillis垃圾收集器停頓時間

-XX:CGTimeRatio吞吐量大小 

 

CMS收集器Concurrent Mark Sweep(高併發標記清除,用於老年代)

併發收集器(邊扔邊打掃)

並行縮短等待時間

併發可以提高速度

 工作過程

優點:併發收集,低停頓

缺點:佔用大量cpu資源, 無法處理浮動垃圾(打掃過一遍的垃圾你又給扔了) ,出現Concurrent Mode Failure (併發清理的回收垃圾池的記憶體區域分配過小),空間碎片 (由標記清除演算法導致)

 

G1收集器(收集器界的老大,面向服務端)

優勢:並行與併發,分代收集,空間整合,可預測的停頓

步驟:初始,併發,最終標記,篩選回收