JVM的垃圾回收策略

一会前、概念

這里說的GC回收好乐,指的是 Java 堆的地方,我們知道了程序計算器瓦宜,虛擬機棧和本地方法棧都是隨線程開啟蔚万,隨線程關閉的,因此這幾塊區(qū)域的內存分配和回收都具備確定性临庇。而Java 堆和方法區(qū)則不一樣反璃,一個接口中的多個實現(xiàn)類需要的內存可能不一樣,一個方法中的多個分支需要的內存也可能不一樣假夺,只有程序在運行時版扩,才知道創(chuàng)建了哪些對象,這部分內存的分配和回收都是動態(tài)的侄泽,垃圾收集器所關注的就是這部分內存礁芦。

而 GC 關注的也就3個點

1、哪些對象需要回收

2悼尾、什么時候回收

3柿扣、如何回收

二、哪些對象需要回收

怎么判斷對象是“存活” 的闺魏,還是已經"死亡"呢未状?主要有以下方法:

2.1 引用計算算法

給對象添加一個引用計算器,每當有一個地方引用它析桥,則加1司草,當引用失效艰垂,則減1;任何時刻計算器為0的對象就是不可能再被使用的埋虹。但它很難解決對象之間相互循環(huán)引用的問題猜憎,所以主流的Java虛擬機都沒有采用這種算法。

2.2 可達性分析算法

通過一系列的 “GC Roots” 的對象作為起始點搔课,從這些起始點開始向下搜索胰柑,搜索走過的路徑被稱為引用鏈(Reference Chain),當一個對象到GC Roots 沒有任何引用鏈項鏈爬泥,即GC Roots 不可達柬讨,則證明此對象是不可用的,如下圖(java 虛擬機第二版)

image

在 Java 虛擬機中袍啡,可作為 **GC Roots **的對象包含以下幾種

1踩官、虛擬機棧(棧幀中的本地變量表)中引用的對象

2、方法區(qū)中的類靜態(tài)屬性引用的對象

3境输、方法區(qū)中常量引用的對象

4卖鲤、本地方法棧中 JNI (Native方法)引用的對象

HotSpot的可達性分析

HotSpot 虛擬機在實現(xiàn)上面的算法的時候,必須要經過更嚴格的考量,才能保證虛擬機高效運行.比如,在上面的可達性分析中,就存在執(zhí)行效率的問題:

1.從 GC Roots 節(jié)點找引用鏈,可是現(xiàn)在很多應用的引用比較復雜,比如方法區(qū)就有數(shù)百兆,如果要逐個檢查這里面的引用,必然消耗 很多的時間.

2.為了保證整個分析期間整個執(zhí)行系統(tǒng)被凍結,而不產生新的引用,會導致java 執(zhí)行線程停頓(stop the world).

為了解決上面的兩個問題:

1、準確式GC 枚舉根節(jié)點,使用一組**OopMap **的數(shù)據(jù)結構來存放對象引用,這個數(shù)據(jù)結構在類加載完成的時候,就已經計算出來了,GC在掃描 的時候就可以得知這些信息,從而降低 GC Roots 時間以及減少停頓時間.

**2畴嘶、安全點 ** **OopMap 中的引用關系可能會變化.或者 OopMap 的指令太多,反而需要更多的空間.此時解決方案是,OopMap 會根據(jù)虛擬機 選定的安全點(safepoint,可以簡單理解為執(zhí)行到哪一行),在這個安全點內去生成指令的 OopMap.在 GC 的時候,驅使所有的線程都"跑 "到最近的安全點,STW **才發(fā)生,應用才停頓.

3、安全區(qū)域 對于掛起的線程來說,比如處于 sleep 或者 blocked 狀態(tài)的,是不能"跑"到安全點的,那么此時解決方案就是,增大安全域(Safe Region).如果線程已經達到安全域,做一個標記,GC 就不需要管這些線程.

引用判斷

無論是引用計數(shù)算法集晚,還是可達性分析算法窗悯,對象是否存貨都跟 “引用” (reference)有關,在JDK1.2 之后偷拔,引用可分為以下4個

強引用:直接 new 蒋院,如 new Object(); 只要這類強引用還在,對象就不會回收

軟引用:(SoftReference類)用來描述一些還有用但非必需的對象莲绰;當將來發(fā)生內存溢出之前欺旧,系統(tǒng)會把這些有軟引用的對象列入回收范圍中進行二次回收,如果這次回收還沒有足夠的內存蛤签,則內存溢出報異常辞友;

弱引用:(WakeReference類) 被弱引用的對象只能生存到下一次垃圾收集發(fā)生之前,當垃圾收集器開始工作時震肮,無論內存是否足夠称龙,都會對這些對象進行回收。

虛引用(幽靈引用/幻影引用):(PhantomReference類) 一個虛引用的對象戳晌,它的唯一目的就是能在這個對象被收集器回收時收到一個系統(tǒng)通知鲫尊,即一個對象是否有虛引用,完全不會對其生存時間構成影響沦偎。

三疫向、什么時候回收

對象的自我拯救

在可達性分析算法不可達的對象咳蔚,也不一定"非死不可’,它會經歷兩次標記搔驼,一是當不可達 GC Roots 時谈火,標記一次并篩選,篩選的條件是該對象是否有必要執(zhí)行 finalize 方法匙奴。當對象沒有覆蓋 finalize 方法堆巧,或者已經執(zhí)行過 finalize 方法時,則認為此對象會被回收泼菌。如下圖

image

這里的執(zhí)行谍肤,是指虛擬機會觸發(fā)這個 finalize 方法,但并不會等待它結束哗伯,這是因為 finalize 方法執(zhí)行緩慢荒揣,可能會導致 F-Queue其他對象處于等待,甚至是崩潰焊刹。

如果在執(zhí)行 finalize 時系任,對象重新和其他對象關聯(lián)上了,則成功拯救了自己

注意:任何一個對象的 finalize() 只會被系統(tǒng)調用一次虐块,下次不會再執(zhí)行俩滥。

3.2 回收方法區(qū)

上面都是對 Java 堆進行回收,雖說 Java 堆 可以回收70%~95%的空間贺奠,但方法區(qū)同樣可以回收一些資源霜旧,方法區(qū)主要回收兩個部分廢棄常量和無用的類。

廢棄常量:

當前系統(tǒng)沒有任何一個 String 對象引用這個 “abc” 的常量池儡率,也沒有其他地方引用了這個字面量挂据,這時可以判斷這個常量是可以廢棄回收的;其他常量池中的接口儿普,字段的符號引用也以此類似

無用的類:

無用類的回收崎逃,需要滿足三個條件

1、是該類所有的實例都已經被回收眉孩,也就是Java堆中不存在實例

2个绍、加載該類的 ClassLoader 已經被回收

3、對應的 java.lang.class 對象沒有再任何地方被引用浪汪,也無法通過反射拿到該類

當然障贸,這里跟Java堆一樣,也只是 "可以回收"了吟宦,是否對類進行回收篮洁,可以對虛擬機的參數(shù)進行設置,這里就不細講了殃姓。

四袁波、如何回收

4.1 標記-清除算法

這里的標記指的是對象進過前面第三章我們介紹的那樣瓦阐,已經可以判定就是可以回收的意思;這個算法首先標記處所有需要回收的對象篷牌,在標記完成之后統(tǒng)一回收所有被標記的對象睡蟋。

看似美好,實則不然枷颊,主要有以下兩個缺點:

效率問題:標記和清除兩個效率都不高

空間問題:標記清除后戳杀,會產生大量空間碎片,在大對象需要分配空間時夭苗,找不到內存信卡,從而又觸發(fā) GC 操作。

標記和清除的執(zhí)行過程如下圖:

image

4.2 復制算法

復制算法可以分為等比例的和8:2兩種

4.2.1 1:1 比例

基于 標記-清除算法的效率問題题造,復制算法出現(xiàn)的傍菇。

這種算法是把內存分為相等的兩塊,一塊用來存儲對象界赔,當GC操作后丢习,把還存留的對象移動到未存對象的那塊內存區(qū)域,再把使用過的內存清掉淮悼。這樣每次都對整個半?yún)^(qū)進行內存回收咐低,就不用擔心內存碎片的問題了。執(zhí)行過程如下圖:

image

從執(zhí)行過程來看袜腥,要消耗到一半的內存见擦,怎么想都是浪費的,在對象多時瞧挤,會頻繁觸發(fā)GC。

4.2.2 8:1 比例

在說明這些回收機制之前儡湾,先說說 新生代和老年代的問題特恬。那么這個分代算法是怎么回事呢?

首先先要理解徐钠,新生代和老年代都是一個內存空間癌刽,由參數(shù)配置,只是可以根據(jù)算法尝丐,決定對象是在新生代還是在老年代的內存區(qū)域O园荨!爹袁!

一塊內存可以分為3個區(qū)域远荠,一個 **Eden **和兩個 **Survivor **區(qū),當對象在 Eden 創(chuàng)建失息,并經理了第一次 GC 之后仍然存活譬淳,并且能被 survivor 區(qū)容納的話档址,將移到 survivor 區(qū);對象在Survivor 區(qū)中“熬過”一次邻梆,年齡增加1守伸,當增加到 15 歲(默認,這個閾值可以通過 -XX:MaxTenuringThreshold 設置)浦妄,就會晉升成老年代的對象尼摹。

從這里來看,可以得到兩個結論

新生代:對象少剂娄,垃圾多

老年代:對象多蠢涝,垃圾少 (畢竟經歷了10幾次GC的老油條)

由于上面的 1:1 的鋪張浪費,基本主流的 Java 虛擬機都是采用 一個 Eden 和 兩個 Survivor 空間宜咒。因為新生代的對象 98% 都是"朝生夕死"的惠赫,每次都是用 Eden 和 一塊 Survivor 空間;

每次GC之后,還存活在 Eden 和 Survivor 空間的對象會被移動到另外一塊Survivor上故黑,并清掉 Eden 和剛才用過的 Survivor 空間儿咱。當Survivor 空間不夠用時诊笤,還得依賴其他內存(這里指老年代)定铜,進行分配擔保。即存活下來的內存不夠放新生代上鹏浅,只有移動到老年代的內存空間上诗轻。

舉個簡單例子:假如虛擬機中設置了新生代的內存大小為10M钳宪,老年代的也為10M,Eden 和 Survivor 為 8:1 的關系扳炬,那么Eden就只有8M吏颖,Survivor 為1M;下面創(chuàng)建4個對象

image

執(zhí)行 test() 恨樟,當要分配 b4 對象時半醉,會執(zhí)行一次 Minor GC,原因是 Eden 才 6M劝术,被b1,b2,b3填充之后缩多,已經沒有數(shù)據(jù)去填充 b4了,就會觸發(fā) GC养晋,而b4沒辦法衬吆,只有移動到老年代的內存區(qū)域了。

那我們可以得到绳泉,** 對象存活率較高的情況下逊抡,效率較低;如果不想浪費 50% 的控件零酪,就需要額外的控件進行分配擔保秦忿,也就是內存跑到老年代去了麦射,那這個對象沒進行GC就跑到老年代去了,那肯定是很占內存的**

所以就有了 標記-整理算法

4.3 標記-整理算法

標記整理算法灯谣,是針對老年代的潜秋。它與標記-清除算法一樣,但不是對相對進行清除胎许,而是移動到另一端峻呛,分兩個步驟

1、標記那些被引用的對象

2辜窑、將被標記的對象移動按順序移動到一端钩述,然后清除掉可回收的對象

image

4.4、分代收集算法

在商業(yè)的虛擬機中穆碎,都采用 分代收集算法牙勘,根據(jù)對象存活周期將內存劃分為幾塊,即新生代和老年代所禀;

在新生代中方面,每次都有大量對象死去,只有少量活著色徘,就選用復制算法恭金;而老年代的對象存活率比較高,沒有額外空間對它進行分配擔保褂策,就必須使用 “標記-整理”或者“標記-清理” 進行回收横腿。

虛擬機是如何管理新生代和老年代

虛擬機一般是這樣管理新生代和老年代的:

1.當一個對象被創(chuàng)建的時候(new)首先會在年輕代的 Eden區(qū)被創(chuàng)建,直到當GC 的時候斤寂,根據(jù)可達性算法耿焊,看一個對象是否消亡,沒有消亡的對象會被放入新生代的 Survivor 區(qū)遍搞,消亡的直接被Minor GC(次要的,普通的 GC) Kill 掉.

2.進入到Survivor 區(qū)的對象也不是安全的罗侯,當下一次 Minor GC 來的時候還是會檢查 Enden 和 Survivor 存放對象區(qū)域中對象是 否存活,存活放入另外一塊 Survivor 區(qū)域.

3.當 2 個 Survivor 區(qū)切換幾次以后尾抑,會直接進入老年代歇父,當然進入到老年代也不是安全的蒂培,當老年代內存空間不足的時候再愈,會觸發(fā)Major GC(主要的,全局的 GC),已經消亡的依然還是被 Kill 掉.

五、垃圾收集器

按系統(tǒng)線程分:

串行收集:串行收集使用單線程處理所有垃圾回收工作, 因為無需多線程交互护戳,實現(xiàn)容易翎冲,而且效率比較高。但是媳荒,其局限性也比 較明顯抗悍,即無法使用多處理器的優(yōu)勢驹饺,所以此收集適合單處理器機器。當然缴渊,此收集器也可以用在小數(shù)據(jù)量(100M左右)情況下的 多處理器機器上赏壹。

并行收集:并行收集使用多線程處理垃圾回收工作,因而速度快衔沼,效率高蝌借。而且理論上CPU 數(shù)目越多,越能體現(xiàn)出并行收集器的 優(yōu)勢指蚁。

并發(fā)收集:相對于串行收集和并行收集而言菩佑,前面兩個在進行垃圾回收工作時,需要暫停整個運行環(huán)境(STW)凝化,而只有垃圾回收程序在運行稍坯,因此,系統(tǒng)在垃圾回收時會有明顯的暫停搓劫,而且暫停時間會因為堆越大而越長瞧哟。

7種垃圾收集器

如果說收集算法是內存回收的方法論,那么垃圾收集器就是內存回收的具體實現(xiàn).java 虛擬機規(guī)范中沒有對垃圾收集器應該如何實 現(xiàn)做任何規(guī)定,因此,不同的廠商可能會有很大的差別.

新生代:Serial, ParNew, Parallel Scaveage,G1

年老代:CMS, Serial Old, Parallel Old, G1

image

Serial/Serial Old 收集器

串行收集器是最古老,最穩(wěn)定以及效率高的收集器糟把,可能會產生較長的停頓绢涡,只使用一個線程去回收。新生代遣疯、老年代使用串行回收雄可;新生代復制算法老年代標記-整理缠犀;垃圾收集的過程中會Stop The World(服務暫停)

參數(shù)控制:-XX:+UseSerialGC 串行收集器 + Serial Old

image

ParNew 收集器

ParNew 收集器其實就是 Serial 收集器的多線程版本.用戶線程需要等待(STW).

參數(shù)控制:-XX:+UseParNewGC ParNew 收集器 + Serial Old

-XX:ParallelGCThreads 限制線程數(shù)量

image

Parallel/Parallel Old 收集器

Parallel Scavenge 收集器類似 ParNew 收集器数苫,Parallel 收集器更關注系統(tǒng)的吞吐量”嬉海可以通過參數(shù)來打開自適應調節(jié)策略虐急,

虛擬機會根據(jù)當前系統(tǒng)的運行情況收集性能監(jiān)控信息,動態(tài)調整這些參數(shù)以提供最合適的停頓時間或最大的吞吐量滔迈;也可以通過參數(shù)

控制 GC 的時間不大于多少毫秒或者比例止吁;新生代復制算法、老年代標記-壓縮

參數(shù)控制:-XX:+UseParallelGC 年輕代使用 Parallel 收集器 + 老年代串行(Serial Old)

Parallel Old 是 Parallel Scavenge 收集器的老年代版本燎悍,使用多線程和“標記-整理”算法敬惦。這個收集器是在 JDK 1.6 中才開始提供.

參數(shù)控制: -XX:+UseParallelOldGC 年輕代使用 Parallel 收集器 + 老年代并行(ParallelOld)

注意:此時用戶線程處于等待狀態(tài)(STW).

image

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。目前很大一部分的 Java 應用都集中

在互聯(lián)網(wǎng)站或 B/S 系統(tǒng)的服務端上谈山,這類應用尤其重視服務的響應速度俄删,希望系統(tǒng)停頓時間最短,以給用戶帶來較好的體驗。

從名字(包含“Mark Sweep”)上就可以看出 CMS 收集器是基于“標記-清除”算法實現(xiàn)的畴椰,它的運作過程相對于前面幾種收

集器來說要更復雜一些臊诊,整個過程分為 4 個步驟,包括:

初始標記(CMS initial mark)

并發(fā)標記(CMS concurrent mark)

重新標記(CMS remark)

并發(fā)清除(CMS concurrent sweep)

其中初始標記斜脂、重新標記這兩個步驟仍然需要“Stop The World”抓艳。初始標記僅僅只是標記一下 GC Roots 能直接關聯(lián)到的對象,速度很快帚戳,并發(fā)標記階段就是進行 GC Roots Tracing 的過程壶硅,而重新標記階段則是為了修正并發(fā)標記期間,因用戶程序繼續(xù)運作而導致標記產生變動的那一部分對象的標記記錄销斟,這個階段的停頓時間一般會比初始標記階段稍長一些庐椒,但遠比并發(fā)標記的時間短。

由于整個過程中耗時最長的并發(fā)標記和并發(fā)清除過程中蚂踊,收集器線程都可以與用戶線程一起工作约谈,所以總體上來說,CMS 收集器的內存回收過程是與用戶線程一起并發(fā)地執(zhí)行犁钟。是一個老年代收集器(新生代使用 ParNew)

優(yōu)點:并發(fā)收集棱诱、低停頓

缺點:使用標記--清除算法,產生大量空間碎片、并發(fā)階段會降低吞吐量, 對 CPU 資源敏感. 無法收集浮動垃圾,需要預留一部分內存在 GC 的時候供程序運作,如果預留空間不足,可能會出現(xiàn)”Concurrent Mode Failure”失敗而導致觸發(fā)一次 Full GC.

參數(shù)控制:

-XX:+UseConcMarkSweepGC 使用 CMS 收集器

-XX:+ UseCMSCompactAtFullCollection Full GC 后涝动,進行一次碎片整理迈勋;整理過程是獨占的,會引起停頓時間變長

-XX:+CMSFullGCsBeforeCompaction 設置進行幾次 Full GC 后醋粟,進行一次碎片整理

-XX:ParallelCMSThreads 設定 CMS 的線程數(shù)量(一般情況約等于可用 CPU 數(shù)量)

image

G1 收集器

G1 是目前技術發(fā)展的最前沿成果之一靡菇,HotSpot 開發(fā)團隊賦予它的使命是未來可以替換掉 JDK1.5 中發(fā)布的 CMS 收集器。與CMS 收集器相比 G1 收集器有以下特點:

1. 空間整合米愿,G1 收集器采用標記整理算法厦凤,不會產生內存空間碎片。分配大對象時不會因為無法找到連續(xù)空間而提前觸發(fā)下一次 GC育苟。

2. 可預測停頓较鼓,這是 G1 的另一大優(yōu)勢,降低停頓時間是 G1 和 CMS 的共同關注點违柏,但 G1 除了追求低停頓外博烂,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為 M 毫秒的時間片段內漱竖,消耗在垃圾收集上的時間不得超過 N 毫秒禽篱,這幾乎已經是實時 Java(RTSJ)的垃圾收集器的特征了。

上面提到的垃圾收集器闲孤,收集的范圍都是整個新生代或者老年代谆级,而 G1 不再是這樣。使用 G1 收集器時讼积,Java 堆的內存布局與其他收集器有很大差別肥照,它將整個 Java 堆劃分為多個大小相等的獨立區(qū)域(Region),雖然還保留有新生代和老年代的概念勤众,但新生代和老年代不再是物理隔閡了舆绎,它們都是一部分(可以不連續(xù))Region 的集合。

優(yōu)點:并行與并發(fā)们颜、分代收集吕朵、空間整合、可預測停頓窥突。

步驟:

初始標記(Initial Marking)

并發(fā)標記(Concurrent Marking)

最終標記(Final Marking)

篩選回收(Live Data Counting and Evacuation)

image

六努溃、理解GC日志

閱讀 GC 日志是處理 java 虛擬機內存問題的基本技能,它只是一些人為確定的規(guī)則,沒有太多的技術含量.

在現(xiàn)實應用中,比較常見的組合使用大概就四種:

年輕代和老年代均使用 Serial GC阻问。

年輕代和老年代均使用 Parallel GC梧税。

年輕代使用 ParNew GC,老年代使用 CMS 收集器称近。

不進行年輕代和老年代區(qū)分第队,使用 G1 收集器。

七刨秆、內存分配與回收策略

1凳谦、 大對象直接進入老年代

從上面可以看,假如一個 2MB 的數(shù)據(jù)衡未,這個短命的大對象在新生去上朝生夕死尸执,很容易觸發(fā) GC ,所以可以通過設置PretenureSize 設置 閾值缓醋,對象大于這個參數(shù)剔交,直接進去老年代

2、 長期存活的對象將進入老年代

一塊內存可以分為3個區(qū)域改衩,一個 Eden 和兩個 Survivor 區(qū)岖常,當對象在 Eden 創(chuàng)建,并經理了第一次 GC 之后仍然存活葫督,并且能被 survivor 區(qū)容納的話竭鞍,將移到 survivor 區(qū);對象在Survivor 區(qū)中“熬過”一次橄镜,年齡增加1偎快,當增加到 15 歲(默認,這個閾值可以通過 -XX:MaxTenuringThreshold 設置)洽胶,就會晉升成老年代的對象晒夹。

從這里來看,可以得到兩個結論

新生代:對象少,垃圾多

老年代:對象多丐怯,垃圾少 (畢竟經歷了10幾次GC的老油條)

3喷好、 動態(tài)對象年齡判斷

上面說到默認年齡為 15 才進入老年代,其實并不然读跷,只要Survivor 中的對象總和大于Survivor 空間的一半梗搅,年齡大于或等于該年齡的對象就可以直接進入老年代。如下:

image

當運行 test() 效览,發(fā)現(xiàn) Survivor 依舊為0无切,b1和b2進入進入老年代,因為它們是同齡的丐枉。

4哆键、 空間分配擔保

在發(fā)生GC前,虛擬機會先檢查老年代的可用連續(xù)空間是否大于新生代的所有對象瘦锹,如果成立洼哎,則發(fā)生 GC 是安全的。如果不成立沼本,則會看是否允許擔保失敗噩峦,如果不允許,則進行 Full GC抽兆;如果允許识补,則會繼續(xù)檢查老年代的可用連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于辫红,則進行 Minor GC凭涂,如果小于,則進行 Full GC 贴妻,但如果某次 Minor GC 后存活的對象大于平均值切油,會導致?lián)J。≈竺停矔M行Full GC澎胡。

引用(本文章只供本人學習以及學習的記錄,如有侵權娩鹉,請聯(lián)系我刪除)

類加載過程

深入Java虛擬機之 -- 類加載機制

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末攻谁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子弯予,更是在濱河造成了極大的恐慌戚宦,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锈嫩,死亡現(xiàn)場離奇詭異受楼,居然都是意外死亡垦搬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門艳汽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猴贰,“玉大人,你說我怎么就攤上這事骚灸。” “怎么了慌植?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵甚牲,是天一觀的道長。 經常有香客問我蝶柿,道長丈钙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任交汤,我火速辦了婚禮雏赦,結果婚禮上,老公的妹妹穿的比我還像新娘芙扎。我一直安慰自己星岗,他們只是感情好,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布戒洼。 她就那樣靜靜地躺著俏橘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圈浇。 梳的紋絲不亂的頭發(fā)上寥掐,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機與錄音磷蜀,去河邊找鬼召耘。 笑死,一個胖子當著我的面吹牛褐隆,可吹牛的內容都是我干的污它。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼庶弃,長吁一口氣:“原來是場噩夢啊……” “哼轨蛤!你這毒婦竟也來了?” 一聲冷哼從身側響起虫埂,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤祥山,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后掉伏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缝呕,經...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡澳窑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了供常。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摊聋。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栈暇,靈堂內的尸體忽然破棺而出麻裁,到底是詐尸還是另有隱情,我是刑警寧澤源祈,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布煎源,位于F島的核電站,受9級特大地震影響香缺,放射性物質發(fā)生泄漏手销。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一图张、第九天 我趴在偏房一處隱蔽的房頂上張望锋拖。 院中可真熱鬧,春花似錦祸轮、人聲如沸兽埃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讲仰。三九已至,卻和暖如春痪蝇,著一層夾襖步出監(jiān)牢的瞬間鄙陡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工躏啰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趁矾,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓给僵,卻偏偏與公主長得像毫捣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子帝际,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容

  • 本文將分析JVM的垃圾回收策略蔓同,哪些內存需要回收和如何回收的問題。 哪些內存需要回收 垃圾收集器在對堆進行回收前蹲诀,...
    匠丶閱讀 711評論 0 6
  • JVM通過垃圾收集器(GC)進行垃圾回收斑粱。GC的工作主要分成兩步:1.標記可清除對象。2.清除這些可清除對象脯爪。 標...
    zvl閱讀 220評論 1 0
  • 一则北、jvm堆內存的分代劃分在基于分代的內存回收策略中矿微,堆空間通常都被劃分為3個代,年輕代尚揣,年老代(或者tenure...
    錯位的季節(jié)閱讀 341評論 0 0
  • 1. 了解下 Java 中內存區(qū)域的劃分 Java 虛擬機在執(zhí)行 Java 程序的過程中涌矢,會把它所管理的內存劃分為...
    13kmsteady閱讀 395評論 0 4
  • java內存區(qū)域劃分 Java與C++之間有一堵由內存動態(tài)分配和垃圾收集技術所圍成的“高墻”,墻外面的人想進去快骗,墻...
    suxm閱讀 609評論 0 1