欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JVM內存模型以及垃圾收集策略解析 - 信心,恒心,野心,愛(ài)心兼具者,可謂準成功人士! -...

JVM內存模型以及垃圾收集策略解析

文章分類(lèi):Java編程

首先祝大家春節愉快,幾個(gè)月前研究了一下JVM的內存模型,整理學(xué)習心得,共享出來(lái)和大家一起學(xué)習討論進(jìn)步。

 

一 JVM內存模型

1.1 Java

Java棧是與每一個(gè)線(xiàn)程關(guān)聯(lián)的,JVM在創(chuàng )建每一個(gè)線(xiàn)程的時(shí)候,會(huì )分配一定的??臻g給線(xiàn)程。它主要用來(lái)存儲線(xiàn)程執行過(guò)程中的局部變量,方法的返回值,以及方法調用上下文。??臻g隨著(zhù)線(xiàn)程的終止而釋放。

StackOverflowError:如果在線(xiàn)程執行的過(guò)程中,??臻g不夠用,那么JVM就會(huì )拋出此異常,這種情況一般是死遞歸造成的。

1.2 

Java中堆是由所有的線(xiàn)程共享的一塊內存區域,堆用來(lái)保存各種JAVA對象,比如數組,線(xiàn)程對象等。

1.2.1 Generation

JVM堆一般又可以分為以下三部分:

Ø Perm

Perm代主要保存class,method,filed對象,這部門(mén)的空間一般不會(huì )溢出,除非一次性加載了很多的類(lèi),不過(guò)在涉及到熱部署的應用服務(wù)器的時(shí)候,有時(shí)候會(huì )遇到java.lang.OutOfMemoryError : PermGen space 的錯誤,造成這個(gè)錯誤的很大原因就有可能是每次都重新部署,但是重新部署后,類(lèi)的class沒(méi)有被卸載掉,這樣就造成了大量的class對象保存在了perm中,這種情況下,一般重新啟動(dòng)應用服務(wù)器可以解決問(wèn)題。

Ø Tenured

Tenured區主要保存生命周期長(cháng)的對象,一般是一些老的對象,當一些對象在Young復制轉移一定的次數以后,對象就會(huì )被轉移到Tenured區,一般如果系統中用了application級別的緩存,緩存中的對象往往會(huì )被轉移到這一區間。

Ø Young

Young區被劃分為三部分,Eden區和兩個(gè)大小嚴格相同的Survivor區,其中Survivor區間中,某一時(shí)刻只有其中一個(gè)是被使用的,另外一個(gè)留做垃圾收集時(shí)復制對象用,在Young區間變滿(mǎn)的時(shí)候,minor GC就會(huì )將存活的對象移到空閑的Survivor區間中,根據JVM的策略,在經(jīng)過(guò)幾次垃圾收集后,任然存活于Survivor的對象將被移動(dòng)到Tenured區間。

1.2.2 Sizing the Generations

JVM提供了相應的參數來(lái)對內存大小進(jìn)行配置。

正如上面描述,JVM中堆被分為了3個(gè)大的區間,同時(shí)JVM也提供了一些選項對Young,Tenured的大小進(jìn)行控制。

Ø Total Heap 

-Xms :指定了JVM初始啟動(dòng)以后初始化內存

-Xmx:指定JVM堆得最大內存,在JVM啟動(dòng)以后,會(huì )分配-Xmx參數指定大小的內存給JVM,但是不一定全部使用,JVM會(huì )根據-Xms參數來(lái)調節真正用于JVM的內存

-Xmx -Xms之差就是三個(gè)Virtual空間的大小

Ø Young Generation

-XX:NewRatio=8意味著(zhù)tenured 和 young的比值81,這樣eden+2*survivor=1/9

堆內存

-XX:SurvivorRatio=32意味著(zhù)eden和一個(gè)survivor的比值是321,這樣一個(gè)Survivor就占Young區的1/34.

-Xmn 參數設置了年輕代的大小

Ø Perm Generation

-XX:PermSize=16M -XX:MaxPermSize=64M

Thread Stack

-XX:Xss=128K

 

1.3 堆棧分離的好處

 

呵呵,其它的先不說(shuō)了,就來(lái)說(shuō)說(shuō)面向對象的設計吧,當然除了面向對象的設計帶來(lái)的維護性,復用性和擴展性方面的好處外,我們看看面向對象如何巧妙的利用了堆棧分離。如果從JAVA內存模型的角度去理解面向對象的設計,我們就會(huì )發(fā)現對象它完美的表示了堆和棧,對象的數據放在堆中,而我們編寫(xiě)的那些方法一般都是運行在棧中,因此面向對象的設計是一種非常完美的設計方式,它完美的統一了數據存儲和運行。

 

二 JAVA垃圾收集器

2.1 垃圾收集簡(jiǎn)史

垃圾收集提供了內存管理的機制,使得應用程序不需要在關(guān)注內存如何釋放,內存用完后,垃圾收集會(huì )進(jìn)行收集,這樣就減輕了因為人為的管理內存而造成的錯誤,比如在C++語(yǔ)言里,出現內存泄露時(shí)很常見(jiàn)的。

Java語(yǔ)言是目前使用最多的依賴(lài)于垃圾收集器的語(yǔ)言,但是垃圾收集器策略從20世紀60年代就已經(jīng)流行起來(lái)了,比如Smalltalk,Eiffel等編程語(yǔ)言也集成了垃圾收集器的機制。

2.2 常見(jiàn)的垃圾收集策略

所有的垃圾收集算法都面臨同一個(gè)問(wèn)題,那就是找出應用程序不可到達的內存塊,將其釋放,這里面得不可到達主要是指應用程序已經(jīng)沒(méi)有內存塊的引用了,而在JAVA中,某個(gè)對象對應用程序是可到達的是指:這個(gè)對象被根(根主要是指類(lèi)的靜態(tài)變量,或者活躍在所有線(xiàn)程棧的對象的引用)引用或者對象被另一個(gè)可到達的對象引用。

2.2.1 Reference Counting(引用計數)

 引用計數是最簡(jiǎn)單直接的一種方式,這種方式在每一個(gè)對象中增加一個(gè)引用的計數,這個(gè)計數代表當前程序有多少個(gè)引用引用了此對象,如果此對象的引用計數變?yōu)?span style="FONT-FAMILY: Times New Roman">0,那么此對象就可以作為垃圾收集器的目標對象來(lái)收集。

優(yōu)點(diǎn):

簡(jiǎn)單,直接,不需要暫停整個(gè)應用

缺點(diǎn):

1.需要編譯器的配合,編譯器要生成特殊的指令來(lái)進(jìn)行引用計數的操作,比如每次將對象賦值給新的引用,或者者對象的引用超出了作用域等。

2.不能處理循環(huán)引用的問(wèn)題

2.2.2 跟蹤收集器

跟蹤收集器首先要暫停整個(gè)應用程序,然后開(kāi)始從根對象掃描整個(gè)堆,判斷掃描的對象是否有對象引用,這里面有三個(gè)問(wèn)題需要搞清楚:

1.如果每次掃描整個(gè)堆,那么勢必讓GC的時(shí)間變長(cháng),從而影響了應用本身的執行。因此在JVM里面采用了分代收集,在新生代收集的時(shí)候minor gc只需要掃描新生代,而不需要掃描老生代。

2.JVM采用了分代收集以后,minor gc只掃描新生代,但是minor gc怎么判斷是否有老生代的對象引用了新生代的對象,JVM采用了卡片標記的策略,卡片標記將老生代分成了一塊一塊的,劃分以后的每一個(gè)塊就叫做一個(gè)卡片,JVM采用卡表維護了每一個(gè)塊的狀態(tài),當JAVA程序運行的時(shí)候,如果發(fā)現老生代對象引用或者釋放了新生代對象的引用,那么就JVM就將卡表的狀態(tài)設置為臟狀態(tài),這樣每次minor gc的時(shí)候就會(huì )只掃描被標記為臟狀態(tài)的卡片,而不需要掃描整個(gè)堆。具體如下圖:

3.GC在收集一個(gè)對象的時(shí)候會(huì )判斷是否有引用指向對象,在JAVA中的引用主要有四種:Strong reference,Soft reference,Weak reference,Phantom reference.

Ø Strong Reference 

強引用是JAVA中默認采用的一種方式,我們平時(shí)創(chuàng )建的引用都屬于強引用。如果一個(gè)對象沒(méi)有強引用,那么對象就會(huì )被回收。

public void testStrongReference(){

Object referent = new Object();

Object strongReference = referent;

referent = null;

System.gc();

assertNotNull(strongReference);

}

 

    

Ø Soft Reference

軟引用的對象在GC的時(shí)候不會(huì )被回收,只有當內存不夠用的時(shí)候才會(huì )真正的回收,因此軟引用適合緩存的場(chǎng)合,這樣使得緩存中的對象可以盡量的再內存中待長(cháng)久一點(diǎn)。

Public void testSoftReference(){

String  str =  "test";

SoftReference<String> softreference = new SoftReference<String>(str);

str=null;

System.gc();

assertNotNull(softreference.get());

}

 

Ø Weak reference

弱引用有利于對象更快的被回收,假如一個(gè)對象沒(méi)有強引用只有弱引用,那么在GC后,這個(gè)對象肯定會(huì )被回收。

Public void testWeakReference(){

String  str =  "test";

WeakReference<String> weakReference = new WeakReference<String>(str);

str=null;

System.gc();

assertNull(weakReference.get());

}

 

Ø Phantom reference 

2.2.2.1 Mark-Sweep Collector(標記-清除收集器)

標記清除收集器最早由Lisp的發(fā)明人于1960年提出,標記清除收集器停止所有的工作,從根掃描每個(gè)活躍的對象,然后標記掃描過(guò)的對象,標記完成以后,清除那些沒(méi)有被標記的對象。

優(yōu)點(diǎn):

解決循環(huán)引用的問(wèn)題

不需要編譯器的配合,從而就不執行額外的指令

缺點(diǎn):

1.每個(gè)活躍的對象都要進(jìn)行掃描,收集暫停的時(shí)間比較長(cháng)。

2.2.2.2 Copying Collector(復制收集器)

復制收集器將內存分為兩塊一樣大小空間,某一個(gè)時(shí)刻,只有一個(gè)空間處于活躍的狀態(tài),當活躍的空間滿(mǎn)的時(shí)候,GC就會(huì )將活躍的對象復制到未使用的空間中去,原來(lái)不活躍的空間就變?yōu)榱嘶钴S的空間。

復制收集器具體過(guò)程可以參考下圖:

優(yōu)點(diǎn):

只掃描可以到達的對象,不需要掃描所有的對象,從而減少了應用暫停的時(shí)間

缺點(diǎn):

1.需要額外的空間消耗,某一個(gè)時(shí)刻,總是有一塊內存處于未使用狀態(tài)

2.復制對象需要一定的開(kāi)銷(xiāo)

2.2.2.3 Mark-Compact Collector(標記-整理收集器)

標記整理收集器汲取了標記清除和復制收集器的優(yōu)點(diǎn),它分兩個(gè)階段執行,在第一個(gè)階段,首先掃描所有活躍的對象,并標記所有活躍的對象,第二個(gè)階段首先清除未標記的對象,然后將活躍的的對象復制到堆得底部。標記整理收集器的過(guò)程示意圖請參考下圖:

 

Mark-compact策略極大的減少了內存碎片,并且不需要像Copy Collector一樣需要兩倍的空間。

2.3 JVM的垃圾收集策略

   GC的執行時(shí)要耗費一定的CPU資源和時(shí)間的,因此在JDK1.2以后,JVM引入了分代收集的策略,其中對新生代采用"Mark-Compact"策略,而對老生代采用了“Mark-Sweep"的策略。其中新生代的垃圾收集器命名為“minor gc”,老生代的GC命名為"Full Gc 或者Major GC".其中用System.gc()強制執行的是Full Gc.

2.3.1 Serial Collector

Serial Collector是指任何時(shí)刻都只有一個(gè)線(xiàn)程進(jìn)行垃圾收集,這種策略有一個(gè)名字“stop the whole world",它需要停止整個(gè)應用的執行。這種類(lèi)型的收集器適合于單CPU的機器。

Serial Copying Collector

此種GC-XX:UseSerialGC選項配置,它只用于新生代對象的收集。1.5.0以后.

-XX:MaxTenuringThreshold來(lái)設置對象復制的次數。當eden空間不夠的時(shí)候,GC會(huì )將eden的活躍對象和一個(gè)名叫From survivor空間中尚不夠資格放入Old代的對象復制到另外一個(gè)名字叫To Survivor的空間。而此參數就是用來(lái)說(shuō)明到底From survivor中的哪些對象不夠資格,假如這個(gè)參數設置為31,那么也就是說(shuō)只有對象復制31次以后才算是有資格的對象。

這里需要注意幾個(gè)個(gè)問(wèn)題:

Ø  From SurvivorTo survivor的角色是不斷的變化的,同一時(shí)間只有一塊空間處于使用狀態(tài),這個(gè)空間就叫做From Survivor區,當復制一次后角色就發(fā)生了變化。

Ø  如果復制的過(guò)程中發(fā)現To survivor空間已經(jīng)滿(mǎn)了,那么就直接復制到old generation.

Ø  比較大的對象也會(huì )直接復制到Old generation,在開(kāi)發(fā)中,我們應該盡量避免這種情況的發(fā)生。

Serial  Mark-Compact Collector

串行的標記-整理收集器是JDK5 update6之前默認的老生代的垃圾收集器,此收集使得內存碎片最少化,但是它需要暫停的時(shí)間比較長(cháng)

2.3.2 Parallel Collector 

Parallel Collector主要是為了應對多CPU,大數據量的環(huán)境。

Parallel Collector又可以分為以下兩種:

Parallel Copying Collector

此種GC-XX:UseParNewGC參數配置,它主要用于新生代的收集,GC可以配合CMS一起使用。1.4.1以后

Parallel Mark-Compact Collector

此種GC-XX:UseParallelOldGC參數配置,此GC主要用于老生代對象的收集。1.6.0

Parallel scavenging Collector

此種GC-XX:UseParallelGC參數配置,它是對新生代對象的垃圾收集器,但是它不能和CMS配合使用,它適合于比較大新生代的情況,此收集器起始于jdk 1.4.0。它比較適合于對吞吐量高于暫停時(shí)間的場(chǎng)合。

Serial gcParallel gc可以用如下的圖來(lái)表示:

2.3.3 Concurrent Collector

Concurrent Collector通過(guò)并行的方式進(jìn)行垃圾收集,這樣就減少了垃圾收集器收集一次的時(shí)間,這種GC在實(shí)時(shí)性要求高于吞吐量的時(shí)候比較有用。

此種GC可以用參數-XX:UseConcMarkSweepGC配置,此GC主要用于老生代Perm代的收集。

 

參考資料

1 http://developers.sun.com/mobility/midp/articles/garbage/

2 http://developers.sun.com/mobility/midp/articles/garbagecollection2/

3 http://blogs.sun.com/watt/resource/jvm-options-list.html

4 http://java.sun.com/developer/technicalArticles/Programming/turbo/

5 http://www.ibm.com/developerworks/library/j-jtp10283/index.html?S_TACT=105AGX52&S_CMP=cn-a-j

6 http://www.ibm.com/developerworks/library/j-jtp11253/index.html?S_TACT=105AGX52&S_CMP=cn-a-j

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java中的垃圾回收原理
JVM內存管理總結
Java系列筆記(3)
JVM史上最最最完整深入解析!萬(wàn)字長(cháng)文!
java垃圾回收總結(2)
hotspot的垃圾回收策略,設置和調優(yōu)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久