1. 程式人生 > >Java之美[從菜鳥到高手演變]之JVM記憶體管理及垃圾回收

Java之美[從菜鳥到高手演變]之JVM記憶體管理及垃圾回收

很多Java面試的時候,都會問到有關Java垃圾回收的問題,提到垃圾回收肯定要涉及到JVM記憶體管理機制,Java語言的執行效率一直被C、C++程式設計師所嘲笑,其實,事實就是這樣,Java在執行效率方面確實很低,一方面,Java語言採用面向物件思想,這也決定了其必然是開發效率高,執行效率低。另一方面,Java語言對程式設計師做了一個美好的承諾:程式設計師無需去管理記憶體,因為JVM有垃圾回收(GC),會去自動進行垃圾回收。

其實不然:

1、垃圾回收並不會按照程式設計師的要求,隨時進行GC。

2、垃圾回收並不會及時的清理記憶體,儘管有時程式需要額外的記憶體。

3、程式設計師不能對垃圾回收進行控制。

因為上面這些事實,以致我們在寫程式的時候,只能根據垃圾回收的規律,合理安排記憶體,這就要求我們必須徹底瞭解JVM的記憶體管理機制,這樣才能隨心所欲,將程式控制於鼓掌之中!本章系Java之美[從菜鳥到高手演變]系列

之JVM記憶體管理及垃圾回收,學完本章知識,讀者對JVM就會有基本的瞭解。

本部落格永久更新,如有轉載,

請說明出處:http://blog.csdn.net/zhangerqing

如有問題,請聯絡本人: egg

郵箱:[email protected]

微博:http://weibo.com/xtfggef

一、JVM記憶體的構

Java虛擬機器會將記憶體分為幾個不同的管理區,這些區域各自有各自的用途,根據不同的特點,承擔不同的任務以及在垃圾回收時運用不同的演算法。總體分為下面幾個部分:

程式計數器(Program Counter Register)、JVM虛擬機器棧(JVM Stacks)、本地方法棧(Native Method Stacks)、堆(Heap)、方法區(Method Area)

如下圖:

1、程式計數器(Program Counter Register)

這是一塊比較小的記憶體,不在Ram上,而是直接劃分在CPU上的,程式設計師無法直接操作它,它的作用是:JVM在解釋位元組碼檔案(.class)時,儲存當前執行緒所執行的位元組碼的行號,只是一種概念模型,各種JVM所採用的方式不同,位元組碼直譯器工作時,就是通過改變程式計數器的值來選取下一條要執行的指令,分支、迴圈、跳轉、等基礎功能都是依賴此技術區完成的。還有一種情況,就是我們常說的Java多執行緒方面的,多執行緒就是通過現程輪流切換而達到的,同一時刻,一個核心只能執行一個指令,所以,對於每一個程式來說,必須有一個計數器來記錄程式的執行進度,這樣,當現程恢復執行的時候,才能從正確的地方開始,所以,每個執行緒都必須有一個獨立的程式計數器,這類計數器為執行緒私有的記憶體。如果一個執行緒正在執行一個Java方法,則計數器記錄的是位元組碼的指令的地址,如果執行的一個Native方法,則計數器的記錄為空,此記憶體區是唯一一個在Java規範中沒有任何OutOfMemoryError情況的區域。

2、JVM虛擬機器棧(JVM Stacks)

JVM虛擬機器棧就是我們常說的堆疊的棧(我們常常把記憶體粗略分為堆和棧),和程式計數器一樣,也是執行緒私有的,生命週期和執行緒一樣,每個方法被執行的時候會產生一個棧幀,用於儲存區域性變量表、動態連結、運算元、方法出口等資訊。方法的執行過程就是棧幀在JVM中出棧和入棧的過程。區域性變量表中存放的是各種基本資料型別,如boolean、byte、char、等8種,及引用型別(存放的是指向各個物件的記憶體地址),因此,它有一個特點:記憶體空間可以在編譯期間就確定,執行期不在改變。這個記憶體區域會有兩種可能的Java異常:StackOverFlowError和OutOfMemoryError。

3、本地方法棧(Native Method Stacks)

從名字即可看出,本地方法棧就是用來處理Java中的本地方法的,Java類的祖先類Object中有眾多Native方法,如hashCode()、wait()等,他們的執行很多時候是藉助於作業系統,但是JVM需要對他們做一些規範,來處理他們的執行過程。此區域,可以有不同的實現方法,向我們常用的Sun的JVM就是本地方法棧和JVM虛擬機器棧是同一個。

4、堆(Heap)

堆記憶體是記憶體中最重要的一塊,也是最有必要進行深究的一部分。因為Java效能的優化,主要就是針對這部分記憶體的。所有的物件例項及陣列都是在堆上面分配的(隨著JIT技術的逐漸成熟,這句話視乎有些絕對,不過至少目前還基本是這樣的),可通過-Xmx和-Xms來控制堆的大小。JIT技術的發展產生了新的技術,如棧上分配和標量替換,也許在不久的幾年裡,即時編譯會誕生及成熟,那個時候,“所有的物件例項及陣列都是在堆上面分配的”這句話就應該稍微改改了。堆記憶體是垃圾回收的主要區域,所以在下文垃圾回收板塊會重點介紹,此處只做概念方面的解釋。在32位系統上最大為2G,64位系統上無限制。可通過-Xms和-Xmx控制,-Xms為JVM啟動時申請的最小Heap記憶體,-Xmx為JVM可申請的最大Heap記憶體。

5、方法區(Method Area)

 方法區是所有執行緒共享的記憶體區域,用於儲存已經被JVM載入的類資訊、常量、靜態變數等資料,一般來說,方法區屬於持久代(關於持久代,會在GC部分詳細介紹,除了持久代,還有新生代和舊生代),也難怪Java規範將方法區描述為堆的一個邏輯部分,但是它不是堆。方法區的垃圾回收比較棘手,就算是Sun的HotSpot VM在這方面也沒有做得多麼完美。此處引入方法區中一個重要的概念:執行時常量池。主要用於存放在編譯過程中產生的字面量(字面量簡單理解就是常量)和引用。一般情況,常量的記憶體分配在編譯期間就能確定,但不一定全是,有一些可能就是執行時也可將常量放入常量池中,如String類中有個Native方法intern()<關於intern()的詳細說明,請看另一篇文章:http://blog.csdn.net/zhangerqing/article/details/8093919>

此處補充一個在JVM記憶體管理之外的一個記憶體區:直接記憶體。在JDK1.4中新加入類NIO類,引入了一種基於通道與緩衝區的I/O方式,它可以使用Native函式庫直接分配堆外記憶體,即我們所說的直接記憶體,這樣在某些場景中會提高程式的效能。

二、垃圾回收

有句話說的好:Java和C++之間有一堵有記憶體分配和垃圾回收技術圍成的牆,牆外的人想進去,牆裡的人想出去!這句話的意思,請讀者自己去琢磨。總的來說,C、C++程式設計師有時苦於記憶體洩露,記憶體管理是件令人頭痛的事兒,但是Java程式設計師呢,又羨慕C++程式設計師,自己可以控制一切,這樣就不會在記憶體管理方面顯得束手無策,的卻如此,作為Java程式設計師我們很難去控制JVM的記憶體回收,只能根據它的原理去適應,儘量提高程式的效能。下面開始講解Java垃圾回收,即Garbage Collection,GC。從以下四個方面進行:

1、為什麼要進行垃圾回收?

隨著程式的執行,記憶體中存在的例項物件、變數等資訊佔據的記憶體越來越多,如果不及時進行垃圾回收,必然會帶來程式效能的下降,甚至會因為可用記憶體不足造成一些不必要的系統異常。

2、哪些“垃圾”需要回收?

在我們上面介紹的五大區中,有三個是不需要進行垃圾回收的:程式計數器、JVM棧、本地方法棧。因為它們的生命週期是和執行緒同步的,隨著執行緒的銷燬,它們佔用的記憶體會自動釋放,所以只有方法區和堆需要進行GC。具體到哪些物件的話,簡單概況一句話:如果某個物件已經不存在任何引用,那麼它可以被回收。通俗解釋一下就是說,如果一個物件,已經沒有什麼作用了,就可以被當廢棄物被回收了。

3、什麼時候進行垃圾回收?

根據一個經典的引用計數演算法,每個物件新增一個引用計數器,每被引用一次,計數器加1,失去引用,計數器減1,當計數器在一段時間內保持為0時,該物件就認為是可以被回收得了。但是,這個演算法有明顯的缺陷:當兩個物件相互引用,但是二者已經沒有作用時,按照常規,應該對其進行垃圾回收,但是其相互引用,又不符合垃圾回收的條件,因此無法完美處理這塊記憶體清理,因此Sun的JVM並沒有採用引用計數演算法來進行垃圾回收。而是採用一個叫:根搜尋演算法,如下圖:

基本思想就是:從一個叫GC Roots的物件開始,向下搜尋,如果一個物件不能到達GC Roots物件的時候,說明它已經不再被引用,即可被進行垃圾回收(此處 暫且這樣理解,其實事實還有一些不同,當一個物件不再被引用時,並沒有完全“死亡”,如果類重寫了finalize()方法,且沒有被系統呼叫過,那麼系統會呼叫一次finalize()方法,以完成最後的工作,在這期間,如果可以將物件重新與任何一個和GC Roots有引用的物件相關聯,則該物件可以“重生”,如果不可以,那麼就說明徹底可以被回收了),如上圖中的Object5、Object6、Object7,雖然它們3個依然可能相互引用,但是總體來說,它們已經沒有作用了,這樣就解決了引用計數演算法無法解決的問題。

補充引用的概念JDK 1.2之後,對引用進行了擴充,引入了強、軟、若、虛四種引用,被標記為這四種引用的物件,在GC時分別有不同的意義:

    a> 強引用(Strong Reference).就是為剛被new出來的物件所加的引用,它的特點就是,永遠不會被回收。

    b> 軟引用(Soft Reference).宣告為軟引用的類,是可被回收的物件,如果JVM記憶體並不緊張,這類物件可以不被回收,如果記憶體緊張,則會被回收。此處有一個問題,既然被引用為軟引用的物件可以回收,為什麼不去回收呢?其實我們知道,Java中是存在快取機制的,就拿字面量快取來說,有些時候,快取的物件就是當前可有可無的,只是留在記憶體中如果還有需要,則不需要重新分配記憶體即可使用,因此,這些物件即可被引用為軟引用,方便使用,提高程式效能。

    c> 弱引用(Weak Reference).弱引用的物件就是一定需要進行垃圾回收的,不管記憶體是否緊張,當進行GC時,標記為弱引用的物件一定會被清理回收。

    d> 虛引用(Phantom Reference).虛引用弱的可以忽略不計,JVM完全不會在乎虛引用,其唯一作用就是做一些跟蹤記錄,輔助finalize函式的使用。

最後總結,什麼樣的類需要回收呢?無用的類,何為無用的類?需滿足如下要求:

   1> 該類的所有例項物件都已經被回收。

   2> 載入該類的ClassLoader已經被回收。

   3> 該類對應的反射類java.lang.Class物件沒有被任何地方引用。

4、如何進行垃圾回收?

本塊內容以介紹垃圾回收演算法為主,因為我們前面有介紹,記憶體主要被分為三塊,新生代、舊生代、持久代。三代的特點不同,造就了他們所用的GC演算法不同,新生代適合那些生命週期較短,頻繁建立及銷燬的物件,舊生代適合生命週期相對較長的物件,持久代在Sun HotSpot中就是指方法區(有些JVM中根本就沒有持久代這中說法)。首先介紹下新生代、舊生代、持久代的概念及特點:

新生代:New Generation或者Young Generation。上面大致分為Eden區和Survivor區,Survivor區又分為大小相同的兩部分:FromSpace 和ToSpace。新建的物件都是用新生代分配記憶體,Eden空間不足的時候,會把存活的物件轉移到Survivor中,新生代的大小可以由-Xmn來控制,也可以用-XX:SurvivorRatio來控制Eden和Survivor的比例.
舊生代:Old Generation。用於存放新生代中經過多次垃圾回收仍然存活的物件,例如快取物件。舊生代佔用大小為-Xmx值減去-Xmn對應的值。

持久代:Permanent Generation。在Sun的JVM中就是方法區的意思,儘管有些JVM大多沒有這一代。主要存放常量及類的一些資訊預設最小值為16MB,最大值為64MB,可通過-XX:PermSize及-XX:MaxPermSize來設定最小值和最大值。

常見的GC演算法:

標記-清除演算法(Mark-Sweep)

最基礎的GC演算法,將需要進行回收的物件做標記,之後掃描,有標記的進行回收,這樣就產生兩個步驟:標記和清除。這個演算法效率不高,而且在清理完成後會產生記憶體碎片,這樣,如果有大物件需要連續的記憶體空間時,還需要進行碎片整理,所以,此演算法需要改進。

複製演算法(Copying)

前面我們談過,新生代記憶體分為了三份,Eden區和2塊Survivor區,一般Sun的JVM會將Eden區和Survivor區的比例調為8:1,保證有一塊Survivor區是空閒的,這樣,在垃圾回收的時候,將不需要進行回收的物件放在空閒的Survivor區,然後將Eden區和第一塊Survivor區進行完全清理,這樣有一個問題,就是如果第二塊Survivor區的空間不夠大怎麼辦?這個時候,就需要當Survivor區不夠用的時候,暫時借持久代的記憶體用一下。此演算法適用於新生代

標記-整理(或叫壓縮)演算法(Mark-Compact)

和標記-清楚演算法前半段一樣,只是在標記了不需要進行回收的物件後,將標記過的物件移動到一起,使得記憶體連續,這樣,只要將標記邊界以外的記憶體清理就行了。此演算法適用於持久代

常見的垃圾收集器: 

根據上面說的諸多演算法,每天JVM都有不同的實現,我們先來看看常見的一些垃圾收集器:


首先介紹三種實際的垃圾回收器:序列GC(SerialGC)、並行回收GC(Parallel Scavenge)和並行GC(ParNew)。

1、Serial GC。是最基本、最古老的收集器,但是現在依然被廣泛使用,是一種單執行緒垃圾回收機制,而且不僅如此,它最大的特點就是在進行垃圾回收的時候,需要將所有正在執行的執行緒暫停(Stop The World),對於有些應用這是難以接受的,但是我們可以這樣想,只要我們能夠做到將它所停頓的時間控制在N個毫秒範圍內,大多數應用我們還是可以接受的,而且事實是它並沒有讓我們失望,幾十毫米的停頓我們作為客戶機(Client)是完全可以接受的,該收集器適用於單CPU、新生代空間較小及對暫停時間要求不是非常高的應用上,是client級別預設的GC方式,可以通過-XX:+UseSerialGC來強制指定。

2、ParNew GC。基本和Serial GC一樣,但本質區別是加入了多執行緒機制,提高了效率,這樣它就可以被用在伺服器端(Server)上,同時它可以與CMS GC配合,所以,更加有理由將它置於Server端。

3、Parallel Scavenge GC。在整個掃描和複製過程採用多執行緒的方式來進行,適用於多CPU、對暫停時間要求較短的應用上,是server級別預設採用的GC方式,可用-XX:+UseParallelGC來強制指定,用-XX:ParallelGCThreads=4來指定執行緒數。以下給出幾組使用組合:


4、CMS (Concurrent Mark Sweep)收集器。該收集器目標就是解決Serial GC 的停頓問題,以達到最短回收時間。常見的B/S架構的應用就適合用這種收集器,因為其高併發、高響應的特點。CMS收集器是基於“標記-清除”演算法實現的,整個收集過程大致分為4個步驟:

初始標記(CMS initial mark)、併發標記(CMS concurrenr mark)、重新標記(CMS remark)、併發清除(CMS concurrent sweep)。

其中初始標記、重新標記這兩個步驟任然需要停頓其他使用者執行緒。初始標記僅僅只是標記出GC ROOTS能直接關聯到的物件,速度很快,併發標記階段是進行GC ROOTS 根搜尋演算法階段,會判定物件是否存活。而重新標記階段則是為了修正併發標記期間,因使用者程式繼續執行而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。由於整個過程中耗時最長的併發標記和併發清除過程中,收集器執行緒都可以與使用者執行緒一起工作,所以整體來說,CMS收集器的記憶體回收過程是與使用者執行緒一起併發執行的。

CMS收集器的優點:併發收集、低停頓,但是CMS還遠遠達不到完美。

CMS收集器主要有三個顯著缺點

a>.CMS收集器對CPU資源非常敏感。在併發階段,雖然不會導致使用者執行緒停頓,但是會佔用CPU資源而導致引用程式變慢,總吞吐量下降。CMS預設啟動的回收執行緒數是:(CPU數量+3) / 4。

b>.CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure“,失敗後而導致另一次Full GC的產生。由於CMS併發清理階段使用者執行緒還在執行,伴隨程式的執行自熱會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之後,CMS無法在本次收集中處理它們,只好留待下一次GC時將其清理掉。這一部分垃圾稱為“浮動垃圾”。也是由於在垃圾收集階段使用者執行緒還需要執行,即需要預留足夠的記憶體空間給使用者執行緒使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分記憶體空間提供併發收集時的程式運作使用。在預設設定下,CMS收集器在老年代使用了68%的空間時就會被啟用,也可以通過引數-XX:CMSInitiatingOccupancyFraction的值來提供觸發百分比,以降低記憶體回收次數提高效能。要是CMS執行期間預留的記憶體無法滿足程式其他執行緒需要,就會出現“Concurrent Mode Failure”失敗,這時候虛擬機器將啟動後備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。所以說引數-XX:CMSInitiatingOccupancyFraction設定的過高將會很容易導致“Concurrent Mode Failure”失敗,效能反而降低。

c>.最後一個缺點,CMS是基於“標記-清除”演算法實現的收集器,使用“標記-清除”演算法收集後,會產生大量碎片。空間碎片太多時,將會給物件分配帶來很多麻煩,比如說大物件,記憶體空間找不到連續的空間來分配不得不提前觸發一次Full GC。為了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關引數,用於在Full GC之後增加一個碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction引數設定執行多少次不壓縮的Full GC之後,跟著來一次碎片整理過程。

5、G1收集器。相比CMS收集器有不少改進,首先基於標記-整理演算法,不會產生記憶體碎片問題,其次,可以比較精確的控制停頓,此處不再詳細介紹。

6、Serial Old。Serial Old是Serial收集器的老年代版本,它同樣使用一個單執行緒執行收集,使用“標記-整理”演算法。主要使用在Client模式下的虛擬機器。

7、Parallel Old。Parallel Old是Parallel Scavenge收集器的老年代版本,使用多執行緒和“標記-整理”演算法。

8、RTSJ垃圾收集器,用於Java實時程式設計,後續會補充介紹。

三、Java程式效能優化

gc()的呼叫

呼叫gc 方法暗示著Java 虛擬機器做了一些努力來回收未用物件,以便能夠快速地重用這些物件當前佔用的記憶體。當控制權從方法呼叫中返回時,虛擬機器已經盡最大努力從所有丟棄的物件中回收了空間,呼叫System.gc() 等效於呼叫Runtime.getRuntime().gc()。

finalize()的呼叫及重寫

gc 只能清除在堆上分配的記憶體(純java語言的所有物件都在堆上使用new分配記憶體),而不能清除棧上分配的記憶體(當使用JNI技術時,可能會在棧上分配記憶體,例如java呼叫c程式,而該c程式使用malloc分配記憶體時)。因此,如果某些物件被分配了棧上的記憶體區域,那gc就管不著了,對棧上的物件進行記憶體回收就要靠finalize()。舉個例子來說,當java 呼叫非java方法時(這種方法可能是c或是c++的),在非java程式碼內部也許呼叫了c的malloc()函式來分配記憶體,而且除非呼叫那個了 free() 否則不會釋放記憶體(因為free()是c的函式),這個時候要進行釋放記憶體的工作,gc是不起作用的,因而需要在finalize()內部的一個固有方法呼叫free()。

優秀的程式設計習慣

(1)避免在迴圈體中建立物件,即使該物件佔用記憶體空間不大。
(2)儘量及時使物件符合垃圾回收標準。
(3)不要採用過深的繼承層次。
(4)訪問本地變數優於訪問類中的變數。

本版塊會不斷更新!

四、常見問題

1、記憶體溢位

就是你要求分配的java虛擬機器記憶體超出了系統能給你的,系統不能滿足需求,於是產生溢位。
2、記憶體洩漏

是指你向系統申請分配記憶體進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊記憶體你自己也不能再訪問,該塊已分配出來的記憶體也無法再使用,隨著伺服器記憶體的不斷消耗,而無法使用的記憶體越來越多,系統也不能再次將它分配給需要的程式,產生洩露。一直下去,程式也逐漸無記憶體使用,就會溢位。

本章內容以理論為主,後續我會不斷地增加一些實際的操作,如驗證垃圾回收效果、或者記憶體監測什麼的,同時也希望讀者會不斷給出指導、建議,如有任何問題,請聯絡:egg:

郵箱:[email protected]

微博:weibo.com/xtfggef

The End

相關推薦

Java[高手演變]JVM記憶體管理垃圾回收

很多Java面試的時候,都會問到有關Java垃圾回收的問題,提到垃圾回收肯定要涉及到JVM記憶體管理機制,Java語言的執行效率一直被C、C++程式設計師所嘲笑,其實,事實就是這樣,Java在執行效率方面確實很低,一方面,Java語言採用面向物件思想,這也決定了其必然是開發效

Java[高手演變]字符串

tween gin new 有關 菜鳥 article user 再看 use 一、String 1、String簡介 初始化: 一般由String聲明的字符串,長度是不可變的,這也是它與StringBuffer和StringBuilder最直觀的一個區別。一般初始化方式:

Java[高手演變]集合類【吐血推薦!講得太好了!!!】

source: http://blog.csdn.net/zhangerqing/article/details/8122075 最近在找工作,目前還沒有定下來,拿到了一個公司的offer,不過被當白菜了,正在商量薪資方面的事情。隨著百度面試的失敗,夢想再次破滅

Java[高手演變]spring框架初識

初識輕量級Java開源框架 --- Spring作者:eggspring是一個輕量級Java框架,其核心思想就是DI(Dependency Injection,即依賴注入)和IoC(Inversion of Control,即控制反轉),因為其開源、低侵入性,現在已經席捲了很大一部分市場,其最大競爭對手乃是J

Java[高手演變]設計模式

轉自:http://blog.csdn.net/zhangerqing/article/details/8194653     設計模式(Design Patterns)                                   ——可複

Java[高手演變]Java

轉載自:http://blog.csdn.net/zhangerqing/article/details/8731044 Java面試複習提綱 作者:egg 郵箱:[email protected] 微博:http://weibo.com/xtfggef 部落格:http

Java[高手演變]資料結構基礎、線性表、棧和佇列、陣列和字串

Java面試寶典之資料結構基礎 —— 線性表篇作者:egg郵箱:[email protected]這部分內容作為計算機專業最基礎的知識,幾乎被所有企業選中用來作考題,因此,本章我們從本章開始,我們將從基礎方面對資料結構進行講解,內容主要是線性表,包括棧、佇列、陣列、

Java[高手演變]系列博文閱讀導航

隨著博文越來越多,為部落格新增一個導航很有必要!本部落格將相繼開通Java、CloudFoundry、Linux、Ruby等專欄,都會設立目錄,希望讀者朋友們能更加方便的閱讀!在閱讀的過程中有任何問題,請聯絡:egg。QQ群:169480361(請在本博文下面留言,驗證資訊為

Java[高手演練]Linux篇——壓縮解壓縮命令tar的使用

-z :是否同時具有 gzip 的屬性?亦即是否需要用 gzip 壓縮-j :是否同時具有 bzip2 的屬性?亦即是否需要用 bzip2 壓縮-v :壓縮的過程中顯示檔案!這個常用,但不建議用在背景執行過程-f :使用檔名,請留意,在 f 之後要立即接檔名喔!不要再加引數   例如使用『 tar -zcvf

Java[高手演練]ThreadLocal原理分析

作者:二青簡介早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal為解決多執行緒程式的併發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多執行緒程式。當使用ThreadLocal維護變數時,ThreadLocal為

Java[高手演練]初識Hadoop

初識Hadoop這是一篇轉載的文章,閱讀原文請點選:原文地址Hadoop一直是我想學習的技術,正巧最近專案組要做電子商城,我就開始研究Hadoop,雖然最後鑑定Hadoop不適用我們的專案,但是我會繼續研究下去,技多不壓身。《Hadoop基礎教程》是我讀的第一本Hadoop書

Python[高手]--urllib原始碼分析

    urllib提供了較好的封裝,可以很方便的讀取http,ftp,file等協議資料,本篇只關注http。urllib的底層還是使用httplib模組,相比於httplib,urllib介面更加好

Python[高手]--讀"一道面試題看 HashMap 的儲存方式"的聯想

在 HashMap 中存放的一系列鍵值對,其中鍵為某個我們自定義的型別。放入 HashMap 後,我們在外部把某一個 key 的屬性進行更改,然後我們再用這個 key 從 HashMap 裡取出元素,這時候 HashMap 會返回什麼?如何面試者直接答“這要看自定義型別的ha

Python[高手]--一步一步動手給Python寫擴充套件(愛初體驗)

    一直對Python擴充套件很感興趣,剛好看到了Extending and Embedding the Python Interpreter文件,看的是最低版本(由於工作中用的是2.x, ̄□ ̄),官方文件    我使用的IDE是Code::Blocks 12.11,

Python[高手]--Python垃圾回收機制gc模組詳解

    Python中的垃圾回收是以引用計數為主,標記-清除和分代收集為輔。引用計數最大缺陷就是迴圈引用的問題,所以Python採用了輔助方法。本篇文章並不詳細探討Python的垃圾回收機制的內部實現,而是以gc模組為切入點學習Python的垃圾回收機制,如果想深入可以讀讀

演算法[高手演練]一些個小演算法

1、10000以內的完數/* * 問題描述:求10000以內的完數。 * 完數即:一個數等於它的不同因子的和 * 如6=1+2+3.8!=1+2+4 * xtfggef 2012/5/16 */ #include<iostream> #include<fst

JVM原理(Java代碼編譯和執行的整個過程+JVM內存管理垃圾回收機制)

變化 並行 colspan 同時 簡單的 table 目前 動態 中心 轉載註明出處: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特點主要是指操作系統裝入JVM是通過jdk中Java.ex

java中高級面試題, 虛擬機,JVM調優,垃圾回收,多線程,內存模型

mybatis mys set 內存 集合 實現 runable ringbuf mon 面試問題: 一、Java基礎方面: 1、Java面相對象的思想的理解(主要是多態): http://blog.csdn.net/zhaojw_420/article/details/7

Java虛擬機器 記憶體管理垃圾回收

java和C++之間有一堵由記憶體自動分配與垃圾回收所圍成的高牆,外面的人想進來,裡面的人想出去 主要內容 記憶體分佈 垃圾回收機制 垃圾收集器 Java記憶體分佈 當java虛擬機器執行程式時,會把由虛擬機器管理的記憶體劃分為不同的區域,他們的作用不同,建立和銷燬時間也不同,有的是虛擬

python垃圾回收機制 Java記憶體管理垃圾回收

語言的記憶體管理是語言設計的一個重要方面。它是決定語言效能的重要因素。無論是C語言的手工管理,還是Java的垃圾回收,都成為語言最重要的特徵。這裡以Python語言為例子,說明一門動態型別的、面向物件的語言的記憶體管理方式。 物件的記憶體使用 賦值語句是語言最常見的功能了。但即使是最簡單的賦值語句,也可以