Java 虛擬機(jī)系列二:垃圾收集機(jī)制詳解,動圖幫你理解

Java 虛擬機(jī)系列一:一文搞懂 JVM 架構(gòu)和運行時數(shù)據(jù)區(qū)

Java 虛擬機(jī)系列二:垃圾收集機(jī)制詳解田弥,動圖幫你理解

前言

上篇文章已經(jīng)給大家介紹了 JVM 的架構(gòu)和運行時數(shù)據(jù)區(qū) (內(nèi)存區(qū)域)逞带,本篇文章將給大家介紹 JVM 的重點內(nèi)容——垃圾收集。眾所周知租谈,相比 C / C++ 等語言篮奄,Java 可以省去手動管理內(nèi)存的繁瑣操作,很大程度上解放了 Java 程序員的生產(chǎn)力割去,而這正是得益于 JVM 的垃圾收集機(jī)制和內(nèi)存分配策略窟却。我們平時寫程序時并感知不到這一點,但是如果是在生產(chǎn)環(huán)境中呻逆,JVM 的不同配置對于服務(wù)器性能的影響是非常大的夸赫,所以掌握 JVM 調(diào)優(yōu)是高級 Java 工程師的必備技能。正所謂“基礎(chǔ)不牢咖城,地動山搖”憔足,在這之前我們先來了解一下底層的 JVM 垃圾收集機(jī)制。

既然要介紹垃圾收集機(jī)制酒繁,就要搞清楚以下幾個問題:

  1. 哪些內(nèi)存區(qū)域需要進(jìn)行垃圾收集滓彰?
  2. 如何判斷對象是否可回收?
  3. 新的對象是如何進(jìn)行內(nèi)存分配的州袒?
  4. 如何進(jìn)行垃圾收集揭绑?

本文將按以下行文結(jié)構(gòu)展開,對上述問題一一解答郎哭。

  1. 需要進(jìn)行垃圾收集的內(nèi)存區(qū)域他匪;
  2. 判斷對象是否可回收的方法;
  3. 主流的垃圾收集算法介紹夸研;
  4. JVM 的內(nèi)存分配與垃圾收集機(jī)制邦蜜。

下面開始正文,還是圖文并茂的老配方亥至,走起悼沈。

一贱迟、需要進(jìn)行垃圾收集的內(nèi)存區(qū)域

先來回顧一下 JVM 的運行時數(shù)據(jù)區(qū):

Java 虛擬機(jī)運行時數(shù)據(jù)區(qū)

其中程序計數(shù)器、Java 虛擬機(jī)棧和本地方法棧都是線程私有的絮供,與其對應(yīng)的線程是共生關(guān)系衣吠,隨線程而生,隨線程而滅壤靶,棧中的棧幀也隨著方法的進(jìn)入和退出井然有序地進(jìn)行入棧和出棧操作缚俏。所以這幾個區(qū)域的內(nèi)存分配和回收都是有很大確定性的,在方法結(jié)束或線程結(jié)束時贮乳,內(nèi)存也會隨之釋放忧换,因此也就不需要考慮這幾個區(qū)域的內(nèi)存回收問題了。

而堆和方法區(qū)就不一樣了向拆,Java 的對象幾乎都是在堆上創(chuàng)建出來的包雀,方法區(qū)則存儲了被虛擬機(jī)加載的類型信息、常量亲铡、靜態(tài)變量才写、即時編譯器編譯后的代碼緩存等數(shù)據(jù),方法區(qū)中的運行時常量池則存放了各種字面量與符號引用奖蔓,上述的這些數(shù)據(jù)大部分都是在運行時才能確定的赞草,所以需要進(jìn)行動態(tài)的內(nèi)存管理。

還要說明一點吆鹤,JVM 中的垃圾收集器的最主要的關(guān)注對象是 Java 堆厨疙,因為這里進(jìn)行垃圾收集的“性價比”是最高的,尤其是在新生代 (后文對分代算法進(jìn)行介紹) 中的垃圾收集疑务,一次就可以回收 70% - 99% 的內(nèi)存沾凄。而方法區(qū)由于垃圾收集判定條件,尤其是類型卸載的判定條件相當(dāng)苛刻知允,其回收性價比是非常低的撒蟀,因此有些垃圾收集器就干脆不支持或不完全支持方法區(qū)的垃圾收集,比如 JDK 11 中的 ZGC 收集器就不支持類型卸載温鸽。

二保屯、判斷對象是否可回收的方法

2.1 引用計數(shù)法

引用計數(shù)法的實現(xiàn)很簡單,在對象中添加一個引用計數(shù)器涤垫,每當(dāng)有一個地方引用它時姑尺,計數(shù)器值就加一;當(dāng)引用失效時蝠猬,計數(shù)器值就減一切蟋;任何時刻計數(shù)器為零的對象就是不可能再被使用的。大部分情況下這個方法是可以發(fā)揮作用的榆芦,但是在存在循環(huán)引用的情況下柄粹,引用計數(shù)法就無能為力了喘鸟。比如下面這種情況:

public class Student {
     // friend 字段
    public Student friend = null;
  
    public static void test() {
        Student a = new Student();
        Student b = new Student();
        a.friend = b;
        b.friend = a;
        a = null;
        b = null;
        System.gc();
    }
}

上述代碼創(chuàng)建了 a 和 b 兩個 Student 實例,并把它們各自的 friend 字段賦值為對方镰惦,除此之外,這兩個對象再無任何引用犬绒,然后將它們都賦值為 null旺入,在這種情況下,這兩個對象已經(jīng)不可能再被訪問凯力,但是它們因為互相引用著對方茵瘾,導(dǎo)致它們的引用計數(shù)都不為零,引用計數(shù)算法也就無法回收它們咐鹤。如下圖所示:

循環(huán)引用

但是在 Java 程序中拗秘,a 和 b 是可以被回收的,因為 JVM 并沒有使用引用計數(shù)法判定對象是否可回收祈惶,而是采用了可達(dá)性分析法雕旨。

2.2 可達(dá)性分析法

這個算法的基本思路就是通過一系列稱為“GC Roots”的根對象作為起始節(jié)點集 (GC Root Set),從這些節(jié)點開始捧请,根據(jù)引用關(guān)系向下搜索凡涩,搜索過程所走過的路徑稱為“引用鏈” (Reference Chain),如果某個對象到GC Roots間沒有任何引用鏈相連疹蛉,則說明此對象不再被使用活箕,也就可以被回收了。要進(jìn)行可達(dá)性分析就需要先枚舉根節(jié)點 (GC Roots)可款,在枚舉根節(jié)點過程中育韩,為防止對象的引用關(guān)系發(fā)生變化,需要暫停所有用戶線程 (垃圾收集之外的線程)闺鲸,這種暫停全部用戶線程的行為被稱為 (Stop The World)筋讨。可達(dá)性分析法如下圖所示:

可達(dá)性分析法

圖中綠色的都是位于 GC Root Set 中的 GC Roots摸恍,所有與其有關(guān)聯(lián)的對象都是可達(dá)的版仔,被標(biāo)記為藍(lán)色些举,而所有與其沒有任何關(guān)聯(lián)的對象都是不可達(dá)的娜庇,被標(biāo)記為灰色。即使是不可達(dá)對象颤诀,也并非一定會被回收谜慌,如果該對象同時滿足以下幾個條件然想,那么它仍有“逃生”的可能:

  1. 該對象有重寫的 finalize()方法 (Object 類中的方法);
  2. finalize()方法中將其自身鏈接到了引用鏈上欣范;
  3. JVM 此前沒有調(diào)用過該對象的finalize()方法 (因為 JVM 在收集可回收對象時會調(diào)用且僅調(diào)用一次該對象的finalize()方法)变泄。

不過由于finalize()方法的運行代價高昂令哟,不確定性大,且無法保證各個對象的調(diào)用順序妨蛹,所以并不推薦使用屏富。那么 GC Roots 又是何方神圣呢?在 Java 語言中蛙卤,固定可作為GC Roots的對象包括以下幾種:

  1. 在虛擬機(jī)棧 (棧幀中的本地變量表) 中引用的對象狠半,比如各個線程被調(diào)用的方法堆棧中使用到的參數(shù)、局部變量颤难、臨時變量等神年。
  2. 在方法區(qū)中類靜態(tài)屬性引用的對象,比如Java類的引用類型靜態(tài)變量行嗤。
  3. 在方法區(qū)中常量引用的對象已日,比如字符串常量池(String Table)里的引用。
  4. 在本地方法棧中JNI (即通常所說的Native方法) 引用的對象栅屏。
  5. Java虛擬機(jī)內(nèi)部的引用飘千,如基本數(shù)據(jù)類型對應(yīng)的Class對象,一些常駐的異常對象 (比如
    NullPointExcepiton栈雳、OutOfMemoryError) 等占婉,還有系統(tǒng)類加載器。
  6. 所有被同步鎖 (synchronized關(guān)鍵字) 持有的對象甫恩。
  7. 反映Java虛擬機(jī)內(nèi)部情況的 JM XBean逆济、JVM TI 中注冊的回調(diào)、本地代碼緩存等磺箕。

三奖慌、垃圾收集算法介紹

3.1 標(biāo)記-清除算法

標(biāo)記-清除算法的思想很簡單,顧名思義松靡,該算法的過程分為標(biāo)記和清除兩個階段:首先標(biāo)記出所有需要回收的對象简僧,其中標(biāo)記過程就是使用可達(dá)性分析法判斷對象是否屬于垃圾的過程。在標(biāo)記完成后雕欺,統(tǒng)一回收掉所有被標(biāo)記的對象岛马,也可以反過來,標(biāo)記存活的對象屠列,統(tǒng)一回收所有未被標(biāo)記的對象啦逆。示意圖如下:

標(biāo)記-清除算法

這個算法雖然很簡單,但是有兩個明顯的缺點:

  1. 執(zhí)行效率不穩(wěn)定笛洛。如果 Java 堆中包含大量對象夏志,而且其中大部分是需要被回收的,這時必須進(jìn)行大量標(biāo)記和清除的動作苛让,導(dǎo)致標(biāo)記和清除兩個過程的執(zhí)行效率都隨對象數(shù)量增長而降低;
  2. 導(dǎo)致內(nèi)存空間碎片化沟蔑。標(biāo)記湿诊、清除之后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會導(dǎo)致當(dāng)以后在程序運行過程中需要分配較大對象時無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作瘦材,非常影響程序運行效率厅须。

3.2 標(biāo)記-復(fù)制算法

標(biāo)記-復(fù)制算法常簡稱復(fù)制算法,這一算法正好解決了標(biāo)記-清除算法在面對大量可回收對象時執(zhí)行效率低下的問題食棕。其實現(xiàn)方法也很易懂:在可用內(nèi)存中劃分出兩塊大小相同的區(qū)域朗和,每次只使用其中一塊,另一塊保持空閑狀態(tài)宣蠕,第一塊用完的時候例隆,就把存活的對象全部復(fù)制到第二塊區(qū)域甥捺,然后把第一塊全部清空抢蚀。如下圖所示:

標(biāo)記-復(fù)制算法

這個算法很適合用于對象存活率低的情況,因為它只關(guān)注存活對象而無需理會可回收對象镰禾,所以 JVM 中新生代的垃圾收集正是采用的這一算法皿曲。但是其缺點也很明顯,每次都要浪費一半的內(nèi)存吴侦,未免太過奢侈屋休,不過新生代有更精細(xì)的內(nèi)存劃分,比較好地解決了這個問題备韧,見下文劫樟。

3.3 標(biāo)記-整理算法

這個算法完美解決了標(biāo)記-清除算法的空間碎片化問題,其標(biāo)記過程與“標(biāo)記-清除”算法一樣织堂,但后續(xù)步驟不是直接對可回收對象進(jìn)行清理叠艳,而是讓所有存活的對象都向內(nèi)存空間一端移動,然后直接清理掉邊界以外的內(nèi)存易阳。

標(biāo)記-整理算法

這個算法雖然可以很好地解決空間碎片化問題附较,但是每次垃圾回收都要移動存活的對象,還要對引用這些對象的地方進(jìn)行更新潦俺,對象移動的操作也需要全程暫停用戶線程 (Stop The World)拒课。

3.4 分代收集算法

與其說是算法,不如說是理論事示。如今大多數(shù)虛擬機(jī)的實現(xiàn)版本都遵循了“分代收集”的理論進(jìn)行設(shè)計早像,這個理論可以看作是經(jīng)驗之談,因為開發(fā)人員在開發(fā)過程中發(fā)現(xiàn)了 JVM 中存活對象的數(shù)量和它們的年齡之間有著某種規(guī)律肖爵,如下圖:

存活對象數(shù)量與年齡的關(guān)系

在此基礎(chǔ)上扎酷,人們得出了以下假說:

  1. 絕大多數(shù)對象都是朝生夕滅的。
  2. 熬過越多次垃圾收集過程的對象就越難以消亡遏匆。

根據(jù)這兩個假說法挨,可以把 JVM 的堆內(nèi)存大致分為新生代和老年代谁榜,新生代對象大多存活時間短,每次回收時只關(guān)注如何保留少量存活而不是去標(biāo)記那些大量將要被回收的對象凡纳,就能以較低代價回收到大量的空間窃植,所以這一區(qū)域一般采用標(biāo)記-復(fù)制算法進(jìn)行垃圾收集,頻率比較高荐糜。而老年代則是一些難以消亡的對象巷怜,可以采用標(biāo)記-清除和標(biāo)記整理算法進(jìn)行垃圾收集,頻率可以低一些暴氏。

按照 Hotspot 虛擬機(jī)的實現(xiàn)延塑,針對新生代和老年代的垃圾收集又分為不同的類型,也有不同的名詞答渔,如下:

  1. 部分收集 (Partial GC):指目標(biāo)不是完整收集整個Java堆的垃圾收集关带,其中又分為:

    • 新生代收集 (Minor GC / Young GC):指目標(biāo)只是新生代的垃圾收集。

    • 老年代收集 (Major GC / Old GC):指目標(biāo)只是老年代的垃圾收集沼撕,目前只有CMS收集器的并發(fā)收集階段是單獨收集老年代的行為宋雏。

    • 混合收集 (Mixed GC):指目標(biāo)是收集整個新生代以及部分老年代的垃圾收集,目前只有G1收集器會有這種行為务豺。

  2. 整堆收集 (Full GC):收集整個Java堆和方法區(qū)的垃圾收集磨总。

人們經(jīng)常會混淆 Major GC 和 Full GC,不過這也有情可原笼沥,因為這兩種 GC 行為都包含了老年代的垃圾收集蚪燕,而單獨的老年代收集 (Major GC) 又比較少見,大多數(shù)情況下只要包含老年代收集奔浅,就會是整堆收集 (Full GC)馆纳,不過還是分得清楚一點比較好哈。

四乘凸、JVM 的內(nèi)存分配和垃圾收集機(jī)制

經(jīng)過前面的鋪墊厕诡,現(xiàn)在終于可以一窺 JVM 的內(nèi)存分配和垃圾收集機(jī)制的真面目了。

4.1 JVM 堆內(nèi)存的劃分

JVM堆內(nèi)存劃分

Java 堆是 JVM 所管理的內(nèi)存中最大的一塊营勤,也是垃圾收集器的管理區(qū)域灵嫌。大多數(shù)垃圾收集器都會將堆內(nèi)存劃分為上圖所示的幾個區(qū)域,整體分為新生代和老年代葛作,比例為 1 : 2寿羞,新生代又進(jìn)一步分為 Eden、From Survivor 和 To Survivor赂蠢,默認(rèn)比例為 8 : 1 : 1绪穆,請注意,可通過 SurvivorRatio 參數(shù)進(jìn)行設(shè)置。請注意玖院,從 JDK 8 開始菠红,JVM 中已經(jīng)不再有永久代的概念了,Java 堆上的無論哪個區(qū)域难菌,存儲的都只能是對象的實例试溯,將Java 堆細(xì)分的目的只是為了更好地回收內(nèi)存,或者更快地分配內(nèi)存郊酒。

4.2 分代收集原理

4.2.1 新生代中對象的分配與回收

大多數(shù)情況下遇绞,對象優(yōu)先在新生代 Eden 區(qū)中分配,當(dāng) Eden 區(qū)沒有足夠空間進(jìn)行分配時燎窘,虛擬機(jī)將發(fā)起一次 Minor GC摹闽。Eden、From Survivor 和 To Survivor 的比例為 8 : 1 : 1褐健,之所以按這個比例是因為絕大多數(shù)對象都是朝生夕滅的付鹿,垃圾收集時 Eden 存活的對象數(shù)量不會太多,Survivor 空間小一點也足以容納铝量,每次新生代中可用內(nèi)存空間為整個新生代容量的90% (Eden 的 80% 加上 To Survivor 的 10%)倘屹,只有From Survivor 空間银亲,即 10% 的新生代是會被“浪費”的慢叨。不會像原始的標(biāo)記-復(fù)制算法那樣浪費一半的內(nèi)存空間。From Survivor 和 To Survivor 的空間并不是固定的务蝠,而是在 S0 和 S1 之間動態(tài)轉(zhuǎn)換的拍谐,第一次 Minor GC 時會選擇 S1 作為 To Survivor,并將 Eden 中存活的對象復(fù)制到其中馏段,并將對象的年齡加1轩拨,注意新生代使用的垃圾收集算法是標(biāo)記-復(fù)制算法的改良版。下面是示意圖院喜,請注意其中第一步的變色是為了醒目亡蓉,虛擬機(jī)只做了標(biāo)記存活對象的操作。

第一次Minor GC示意圖

在后續(xù)的 Minor GC 中喷舀,S0 和 S1會交替轉(zhuǎn)化為 From Survivor 和 To Survivor砍濒,Eden 和 From Survivor 中的存活對象會復(fù)制到 To Survivor 中,并將年齡加 1硫麻。如下圖所示:

循環(huán)進(jìn)行Minor GC示意圖

4.2.2 對象晉升老年代

在以下這些情況下爸邢,對象會晉升到老年代。

  1. 長期存活對象將進(jìn)入老年代

    對象在 Survivor 區(qū)中每熬過一次Minor GC拿愧,年齡就增加1歲杠河,當(dāng)它的年齡增加到一定程度 (默認(rèn)為15),就會被晉升到老年代中。對象晉升老年代的年齡閾值券敌,可以通過參數(shù) -XX:MaxTenuringThreshold 設(shè)置唾戚,這個參數(shù)的最大值是15,因為對象年齡信息儲存在對象頭中待诅,占4個比特 (bit)的內(nèi)存颈走,所能表示最大數(shù)字就是15。

晉升老年代示意圖
  1. 大對象可以直接進(jìn)入老年代

    對于大對象咱士,尤其是很長的字符串立由,或者元素數(shù)量很多的數(shù)組,如果分配在 Eden 中序厉,會很容易過早占滿 Eden 空間導(dǎo)致 Minor GC锐膜,而且大對象在 Eden 和兩個 Survivor 之間的來回復(fù)制也還會有很大的內(nèi)存復(fù)制開銷。所以我們可以通過設(shè)置 -XX:PretenureSizeThreshold 的虛擬機(jī)參數(shù)讓大對象直接進(jìn)入老年代弛房。

  2. 動態(tài)對象年齡判斷

    為了能更好地適應(yīng)不同程序的內(nèi)存狀況道盏,HotSpot 虛擬機(jī)并不是永遠(yuǎn)要求對象的年齡必須達(dá)到 -XX:MaxTenuringThreshold 才能晉升老年代,如果在 Survivor 空間中相同年齡所有對象大小的總和大于 Survivor 空間的一半文捶,年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代荷逞,無須等到 -XX:MaxTenuringThreshold 中要求的年齡。

  3. 空間分配擔(dān)保 (Handle Promotion)

    當(dāng) Survivor 空間不足以容納一次 Minor GC 之后存活的對象時粹排,就需要依賴其他內(nèi)存區(qū)域 (實際上大多數(shù)情況下就是老年代) 進(jìn)行分配擔(dān)保种远。在發(fā)生 Minor GC 之前,虛擬機(jī)必須先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間顽耳,如果這個條件成立坠敷,那這一次 Minor GC 可以確保是安全的。如果不成立射富,則虛擬機(jī)會先查看 - XX:HandlePromotionFailure 參數(shù)的設(shè)置值是否允許擔(dān)保失敗 (Handle Promotion Failure)膝迎;如果允許,那會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小胰耗,如果大于限次,將嘗試進(jìn)行一次 Minor GC,盡管這次 Minor GC 是有風(fēng)險的柴灯;如果小于卖漫,或者-XX: HandlePromotionFailure設(shè)置不允許冒險,那這時就要改為進(jìn)行一次 Full GC弛槐。

總結(jié)

本文介紹了 JVM 的垃圾收集機(jī)制懊亡,并用大量圖片和動圖來幫助大家理解,如有錯誤乎串,歡迎指正店枣。后續(xù)文章會繼續(xù)介紹 JVM 中的各種垃圾收集器速警,包括最前沿的 ZGC 和 Shenandoah 收集器,是 JVM 領(lǐng)域的最新科技成果鸯两,敬請期待闷旧。

最后是參考文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钝侠,隨后出現(xiàn)的幾起案子该园,更是在濱河造成了極大的恐慌,老刑警劉巖帅韧,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件里初,死亡現(xiàn)場離奇詭異,居然都是意外死亡忽舟,警方通過查閱死者的電腦和手機(jī)双妨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叮阅,“玉大人刁品,你說我怎么就攤上這事『评眩” “怎么了挑随?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長及刻。 經(jīng)常有香客問我镀裤,道長竞阐,這世上最難降的妖魔是什么缴饭? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮骆莹,結(jié)果婚禮上颗搂,老公的妹妹穿的比我還像新娘。我一直安慰自己幕垦,他們只是感情好丢氢,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著先改,像睡著了一般疚察。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仇奶,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天貌嫡,我揣著相機(jī)與錄音,去河邊找鬼。 笑死岛抄,一個胖子當(dāng)著我的面吹牛别惦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夫椭,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼掸掸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蹭秋?” 一聲冷哼從身側(cè)響起扰付,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仁讨,沒想到半個月后悯周,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡陪竿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年禽翼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片族跛。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡闰挡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出礁哄,到底是詐尸還是另有隱情长酗,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布桐绒,位于F島的核電站夺脾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茉继。R本人自食惡果不足惜咧叭,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烁竭。 院中可真熱鬧菲茬,春花似錦、人聲如沸派撕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽终吼。三九已至镀赌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間际跪,已是汗流浹背商佛。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工蛙粘, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人威彰。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓出牧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親歇盼。 傳聞我的和親對象是個殘疾皇子舔痕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容