不止面試-JVM垃圾回收面試題詳解

第一部分:面試題

本次分享我們將嘗試回答以下問題:

  1. GC 是什么? 為什么要有 GC?
  2. 簡單說一下java的垃圾回收機(jī)制柴灯。
  3. JVM的常見垃圾回收算法有哪些泡嘴?
  4. 為什么要使用分代回收機(jī)制蔓纠?
  5. 如何判斷一個對象是否存活?
  6. 如果對象的引用被置為 null溃槐,垃圾收集器是否會立即釋放對象占用的內(nèi)存?

第二部分:深入原理

好帅矗,讓我們開始吧偎肃。還是那句話,如果時間不夠可以直接拉到最后看答案浑此。

java垃圾回收的知識點(diǎn)雖然看起來難累颂,但知識點(diǎn)非常集中,而且很好理解凛俱。不信紊馏?不信就往下看吧。

1. 所謂GC

GC就是垃圾收集的意思(Gabage Collection)最冰。

我們在開發(fā)中會創(chuàng)建很多對象瘦棋,這些對象一股腦的都扔進(jìn)了堆里(還記得jvm內(nèi)存模型嗎稀火?不記得的話翻翻前面的文章)暖哨,如果這些對象只增加不減少,那么堆空間很快就會被耗盡凰狞。所以我們需要把一些沒用的對象清理掉篇裁。

2.對象已死嗎

垃圾回收,就是要把那些不再使用的對象找出來然后清理掉赡若,釋放其占用的內(nèi)存空間达布。

判斷一個對象是否還在使用,用咱們java圈子的行話講逾冬,就是判斷對象是否死亡(反之就是存活)黍聂。

在java中判斷對象死亡有兩種方式:

  • 引用計(jì)數(shù)法
  • 可達(dá)性分析法

下面我們詳細(xì)講講

2.1 引用計(jì)數(shù)法

引用計(jì)數(shù)法的思想十分樸素,它的做法是給對象添加一個引用計(jì)數(shù)器身腻,每當(dāng)有一個地方引用該對象产还,這個計(jì)數(shù)器就加1。當(dāng)引用失效時嘀趟,計(jì)數(shù)器就減1脐区。如果計(jì)數(shù)器為0了,說明該對象不再被引用她按,成為死亡對象牛隅。

不過這種算法有一個致命缺點(diǎn),就是無法處理對象相互引用的情況酌泰。

你看媒佣,假如有A、B兩個對象陵刹,它們互相引用默伍,那么對象中的引用計(jì)數(shù)器會始終大于0。

所以這種算法已經(jīng)沒人用了。

2.2 可達(dá)性分析法

2.2.1 什么是可達(dá)性

可達(dá)性分析法就是目前的主流算法巡验,也是java正在使用的算法际插。

它的做法是,通過一系列被稱為“GC Roots”的對象作為起點(diǎn)显设,從這些起點(diǎn)開始往下搜索框弛,搜索所走過的路徑稱為引用鏈(Reference Chain)。當(dāng)一個對象沒有和任何引用鏈相連捕捂,即稱為該對象不可達(dá)(圖論的說法)瑟枫,認(rèn)為該對象死亡。

來看下面這張圖:

file

上圖中A指攒、B慷妙、C都跟GC Roots有直接或間接的引用關(guān)系,所以是存活對象允悦。而D膝擂、E、F雖然相互之間有引用隙弛,但是和GC Roots并無引用關(guān)系架馋,所以是死亡對象。

2.2.2 哪些對象可作為GC Roots

有四類對象可作為可達(dá)性分析的GC Roots

  • 棧(棧幀中的本地變量表)中引用的對象
  • 方法區(qū)中類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧中JNI引用的對象

總而言之全闷,GC Roots是所有Java線程中處于活躍狀態(tài)的棧幀,靜態(tài)引用等指向GC堆里的對象的引用叉寂。換句話說,就是當(dāng)前所有正在被調(diào)用的方法的引用類型的參數(shù)/局部變量/臨時值总珠。

2.3 所謂引用

對象是否死亡屏鳍,關(guān)鍵就在于引用。在java中局服,引用其實(shí)有四種:強(qiáng)引用钓瞭、軟引用、弱引用腌逢、虛引用降淮。

  • 強(qiáng)引用

    強(qiáng)引用就是我們?nèi)粘i_發(fā)中最常見的引用,例如

    String str = new String("hello");
    

    只要強(qiáng)引用還在搏讶,對象就不會被回收佳鳖。

  • 軟引用

    軟引用需要專門聲明,例如

    SoftReference<String> str = new SoftReference<String>("hello");
    

    被軟引用關(guān)聯(lián)的對象在內(nèi)存不足時會被回收媒惕。

    這個特性特別適合用來做緩存系吩。

  • 弱引用

    弱引用也需要專門聲明,例如

    WeakReference<String> str = new WeakReference<String>("hello");
    

    被弱引用關(guān)聯(lián)的對象每次GC時都會被回收妒蔚。

    弱引用最常見的用途是實(shí)現(xiàn)可自動清理的集合或者隊(duì)列穿挨。

  • 虛引用

    虛引用是最弱的引用月弛,需要用PhantomReference來聲明,例如

    PhantomReference<String> phantom = new PhantomReference<>(new String("hello"), new ReferenceQueue<>());
    

    它完全不會影響對象的生存時間科盛,唯一的作用是在對象被回收時發(fā)一個系統(tǒng)通知帽衙。

2.4 起死回生

對象在被判定為死亡后,并不會立刻被回收贞绵,而是要經(jīng)過一個過程才會被回收厉萝。在這個回收過程中,死亡對象還有可能活過來榨崩,是不是很神奇谴垫?

來看圖:

file

上圖是對象被回收的過程。一個對象要被回收母蛛,至少要經(jīng)過兩次標(biāo)記翩剪。

如果對象在第二次標(biāo)記之前重新連接上GC Roots,那么它將在第二次標(biāo)記中被移出回收隊(duì)列彩郊,從而復(fù)活前弯。

還有一點(diǎn)需要注意的是,F(xiàn)inalizer線程是一個由虛擬機(jī)自動建立焦辅,且低優(yōu)先級的線程博杖。該線程觸發(fā)對象的finalize()方法之后椿胯,并不會阻塞等待方法執(zhí)行結(jié)束筷登。這樣做是為了防止回收隊(duì)列被阻塞。

finalize()是Object中的方法哩盲,當(dāng)垃圾回收器將要回收對象所占內(nèi)存之前被調(diào)用的方法前方。有些教材推薦用該方法來做“關(guān)閉外部資源”之類的工作,但是實(shí)際上該方法運(yùn)行代價高昂廉油,且不確定性很大惠险,所以并不推薦使用。真要關(guān)閉外部資源抒线,還不如用try-finally來處理班巩。

3.方法區(qū)的回收

方法區(qū)不在堆內(nèi),會被垃圾回收嗎嘶炭?

在jdk1.7中抱慌,方法區(qū)在永久代,而永久代本身就是垃圾回收概念下的產(chǎn)物眨猎,full gc時就會對方法區(qū)回收抑进。

到了jdk1.8,雖然永久代被取消睡陪,但是新增了MaxMetaspaceSize參數(shù)寺渗,對于將死的類及類加載器的垃圾回收將在元數(shù)據(jù)使用達(dá)到“MaxMetaspaceSize”參數(shù)的設(shè)定值時進(jìn)行匿情。

所以,方法區(qū)會被回收信殊。

4.垃圾回收算法

這一節(jié)我們來看下流行的垃圾回收算法炬称,只說思想,不涉及實(shí)現(xiàn)細(xì)節(jié)涡拘。

我們需要了解的垃圾回收算法有以下幾種:

  • 標(biāo)記-清除算法
  • 復(fù)制算法
  • 標(biāo)記-整理算法
  • 分代回收算法

咱們一個個來看下转砖。

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

標(biāo)記-清除算是最基本的回收算法了。它的思想就是先標(biāo)記鲸伴,再清除府蔗。標(biāo)記過程如2.4節(jié)所述,有兩次標(biāo)記汞窗。

它的主要缺點(diǎn)有兩個:

  • 效率不高
  • 會產(chǎn)生大量內(nèi)存碎片

內(nèi)存碎片是指內(nèi)存的空間比較零碎姓赤,缺少大段的連續(xù)空間。這樣假如突然來了一個大對象仲吏,會找不到足夠大的連續(xù)空間來存放不铆,于是不得不再觸發(fā)一次gc。

file

4.2 復(fù)制算法

復(fù)制算法的思想是裹唆,把內(nèi)存分成兩塊誓斥,假設(shè)分成A、B兩個區(qū)域吧许帐。

每次對象過來之后劳坑,都放到A區(qū)域里,當(dāng)A區(qū)域滿了之后成畦,把存活的對象復(fù)制到B區(qū)域距芬,然后清空A區(qū)域。

接下來的對象就全部放到B區(qū)域循帐,等B區(qū)域滿了框仔,就把存活對象復(fù)制到A區(qū)域,然后清空B區(qū)域拄养。

就這樣來回倒騰离斩,完成垃圾回收。

優(yōu)點(diǎn)是不會有空間碎片瘪匿,缺點(diǎn)是每次只用得到一半內(nèi)存跛梗。

缺點(diǎn)是在對象存活率較高的場景下(比如老年代那樣的環(huán)境),需要復(fù)制的東西太多柿顶,效率會下降茄袖。

file

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

標(biāo)記-整理算法中的“標(biāo)記”階段和“標(biāo)記-清理”中的標(biāo)記一樣。不同的是嘁锯,死亡對象并不會直接清理宪祥,而是把他們在內(nèi)存中都移動到一起聂薪,然后一起清理。

file

4.4 分代收集算法

分代收集算法其實(shí)沒什么新東西蝗羊,只是把對象按存活率分塊藏澳,然后選用合適的收集算法。

java中使用的就是分代收集算法耀找。

存活率低的對象放在一起翔悠,稱為年輕代,使用復(fù)制算法來收集野芒。

存活率高的對象放在一起蓄愁,稱為老年代,使用標(biāo)記-清除或者標(biāo)記-整理算法狞悲。

5. HotSpot的枚舉GC Roots

前面我們說到了對象的可達(dá)性分析需要從GC Roots開始計(jì)算引用鏈撮抓。

然而可作為GC Roots的對象非常多,一個個來計(jì)算將非常耗時摇锋。

而且在進(jìn)行這項(xiàng)工作時丹拯,虛擬機(jī)必須停下來,就像時間停止那樣(Sun稱之為Stop The World荸恕,哈哈乖酬,是不是很酷),以此保證分析結(jié)果的準(zhǔn)確性融求。

我們的程序咬像,特別是網(wǎng)站應(yīng)用,基本是上是一刻不停的在運(yùn)行的双肤。如果出現(xiàn)長時間的停止施掏,基本上是不可接受的。為了解決這個問題茅糜,各個虛擬機(jī)都采取了一些措施,盡量減少停頓時間(是的素挽,只能減少蔑赘,停頓是不可能消除的)。

我們來看看現(xiàn)在最流行的Hotspot虛擬機(jī)是怎么處理的预明。(還記得啥是HotSpot不缩赛?翻翻前幾篇文章)

5.1 OopMap

在HotSpot中,虛擬機(jī)把對象內(nèi)的什么偏移量上是什么類型的數(shù)據(jù)的信息存在到一個叫做“OopMap”的數(shù)據(jù)結(jié)構(gòu)中撰糠。這樣在計(jì)算引用鏈時直接查OopMap即可酥馍,不用到整個內(nèi)存中去挨個找了,由此提高了分析速度阅酪。

5.2 安全點(diǎn)

然而旨袒,程序中的引用關(guān)系時時刻刻都在變化汁针,如果每次變化都要記錄到OopMap中,也是一項(xiàng)很大的負(fù)擔(dān)砚尽。所以施无,只有在程序執(zhí)行到了特定的位置,才會去記錄到OopMap中必孤。

這個“特定的位置”猾骡,就叫安全點(diǎn)

這里面還有個問題敷搪,就是如何保證在GC發(fā)生時兴想,讓所有的線程正好到達(dá)安全點(diǎn)。

有兩種方式:

  • 搶先式中斷(已經(jīng)沒人用了)

    搶先式中斷的思路是赡勘,先把所有線程中斷襟企,如果有線程沒有跑到安全點(diǎn)上,就恢復(fù)該線程狮含,讓它跑到安全點(diǎn)顽悼。

  • 主動式中斷

    主動式中斷的做法是,設(shè)置一個中斷標(biāo)志几迄,這個標(biāo)志和安全點(diǎn)是重合的蔚龙。讓各個線程去輪詢這個標(biāo)志,發(fā)現(xiàn)需要中斷時映胁,線程就自己中斷掛起木羹。

5.3 安全區(qū)域

雖然安全點(diǎn)已經(jīng)完美解決了如何保證在GC發(fā)生時,讓所有的線程正好到達(dá)安全點(diǎn)的問題解孙。

但是有一些情況下坑填,線程失去了行為能力,比如線程處于sleep或者blocked狀態(tài)弛姜。這個時候線程無法去響應(yīng)JVM的中斷請求脐瑰,而JVM顯然也不肯能一直等待某幾個線程。該怎么辦呢廷臼?

這種情況就需要“安全區(qū)域”來解決苍在。

安全區(qū)域是指在一段代碼片段中,引用關(guān)系不會發(fā)生變化荠商,這個區(qū)域中任意地方開始GC都是安全的寂恬。

6.垃圾收集器

前面咱們說的都是垃圾收集的方法和思路,垃圾收集器則是具體的實(shí)現(xiàn)莱没。

先來看下hotSpot中垃圾收集器的總圖(到j(luò)dk1.8)

file

6.1 并行和并發(fā)

在開始講解之前初肉,我們先了解一下什么是并行和并發(fā)。

并行:垃圾收集器是多線程同時工作的饰躲,但是用戶線程仍然處于等待狀態(tài)牙咏。

并發(fā):用戶線程和垃圾收集器線程同時執(zhí)行(也有可能是交替執(zhí)行)臼隔。

下面咱們說說幾個常用的使用方案

6.1 jdk1.8默認(rèn)垃圾收集器

查看當(dāng)前使用的垃圾收集器可以使用以下命令:

~ java -XX:+PrintCommandLineFlags -version

然后會看到以下內(nèi)容:

-XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

可見jdk1.8默認(rèn)工作在Server模式下,默認(rèn)使用ParallelGC垃圾收集器眠寿。

如果要看更詳細(xì)的信息躬翁,還可以使用以下命令:

java -XX:+PrintFlagsFinal -version | grep GC

這個命令打印的內(nèi)容有點(diǎn)多,我們主要找值為true的信息盯拱。默認(rèn)情況會有以下兩行:

bool UseParallelGC                            := true    
bool UseParallelOldGC                          = true       

6.1.1 Parallel Scavenge收集器

從上面的總圖能看到盒发,這是一個工作在年輕代的收集器,使用復(fù)制算法狡逢,是一個并行的多線程收集器宁舰。

它的目標(biāo)是達(dá)到一個可控制的吞吐量。所謂吞吐量就是CPU用于運(yùn)行用戶代碼的時間與CPU總消耗時間的比值奢浑。比如虛擬機(jī)總共運(yùn)行了100分鐘蛮艰,其中垃圾收集花了1分鐘,那吞吐量就是99%雀彼。

6.1.2 Parallel Old收集器

Parallel Old是一個工作在老年代的收集器壤蚜,使用“標(biāo)記-整理”算法。也是一個關(guān)注吞吐量的垃圾收集器徊哑。

6.2 web應(yīng)用垃圾收集器方案

ParallelGC組合重視的是吞吐量袜刷,非常適合在后臺運(yùn)算而不需要太多交互的場景。

對于需要大量交互的應(yīng)用莺丑,比如web應(yīng)用著蟹,則需要更短的停頓時間。

所以大多數(shù)web應(yīng)用使用的是ParNew+CMS收集器方案梢莽。

6.2.1 ParNew收集器

parNew也是一個工作在年輕代的收集器萧豆,也使用復(fù)制算法,也是一個并行的多線程收集器昏名。

為什么我要使用這么多“也”……

好吧涮雷,parNew看起來和Parallel Scavenge一模一樣,但其實(shí)他們還是有區(qū)別的葡粒。

parNew是一個重視停頓時間收集器份殿。

不過它最大的特點(diǎn)是:可以和CMS收集器組隊(duì)工作。

Parallel Scavenge就不行…...

6.2.2 CMS收集器

CMS是一款十分優(yōu)秀的老年代垃圾收集器嗽交,響應(yīng)速度快、停頓時間短颂斜,是現(xiàn)在大多數(shù)互聯(lián)網(wǎng)公司的選擇夫壁,大家要好好掌握。

CMS使用“標(biāo)記-清除”算法沃疮,分為4個步驟:

  • 初始標(biāo)記(STW)
  • 并發(fā)標(biāo)記
  • 重新標(biāo)記(STW)
  • 并發(fā)清除

其中盒让,初始標(biāo)記很快梅肤,只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象。

并發(fā)標(biāo)記和重新標(biāo)記要Stop The World邑茄,并發(fā)標(biāo)記就是在標(biāo)記死亡對象姨蝴,重新標(biāo)記是為了修正并發(fā)標(biāo)記期間發(fā)生變動的那部分對象。

從耗時來看肺缕,并發(fā)標(biāo)記>重新標(biāo)記>初始標(biāo)記左医。

并發(fā)清除和并發(fā)標(biāo)記耗時最長,但收集器線程是和用戶線程一起并發(fā)執(zhí)行的同木,所以沒有停頓浮梢。

CMS固然優(yōu)秀,但也有一些缺點(diǎn):

  • 耗CPU資源

    收集器線程和用戶線程并發(fā)工作彤路,所以收集時會搶占CPU資源

  • 無法處理浮動垃圾

    浮動垃圾是指在標(biāo)記過程之后出現(xiàn)的垃圾秕硝。這部分垃圾在本次回收中無法處理,只能等下次洲尊。

  • 產(chǎn)生碎片空間

    使用“標(biāo)記-清除”算法就會有這個問題曲聂。不過可以通過參數(shù)設(shè)置開啟碎片整理,比如3次回收后就來一次帶碎片整理的回收后室。

6.3 G1收集器

G1收集器是目前最新的垃圾收集器他炊,到j(luò)dk1.7時達(dá)到可商用程度。

G1收集器可以同時hold住年輕代和老年代姆吭,不需要和別的收集器搭配使用榛做。

G1收集器使用的也是分代算法,它的思路是内狸,把內(nèi)存空間分成一個個小格子检眯,每個格子稱為一個Region。如下圖:

file

優(yōu)先回收價值大的Region昆淡。

年輕代使用并發(fā)復(fù)制算法锰瘸,有STW。

老年代回收步驟大致可以分為以下幾個:

  • 初始標(biāo)記(STW)
  • 并發(fā)標(biāo)記
  • 最終標(biāo)記(STW)
  • 篩選回收(STW)

目前JDK1.9已經(jīng)默認(rèn)使用G1收集器昂灵,但是在JDK1.8版本中G1收集器似乎還有不少問題避凝,使用的還不多。

7.內(nèi)存分配策略

終于要放出這張圖了:

file

其實(shí)我在一開頭就像放這張圖眨补,但是想著先講點(diǎn)前置知識管削,沒想到這一講,就叫講到這了…...

7.1 年輕代的策略

在年輕代分為三個區(qū)域撑螺,Eden區(qū)含思、Survivor1區(qū)、Survivor2區(qū)。有時候Survivor1區(qū)含潘、Survivor2區(qū)又叫from區(qū)和to區(qū)饲做。

對象優(yōu)先分配到Eden區(qū)。Eden區(qū)要滿的時候遏弱,會有一次復(fù)制回收盆均,把存活的對象放到Survivor1區(qū)。

等Eden區(qū)再次要滿的時候漱逸,又會有一次復(fù)制回收泪姨,把Eden區(qū)和Survivor1區(qū)的存活對象放到Survivor2區(qū)。

然后如此循環(huán)虹脯。

7.2 大對象的策略

虛擬機(jī)提供了一個-XX:PretenureSizeThreshold參數(shù)驴娃,大于這個參數(shù)的對象會直接進(jìn)入老年代,防止年輕代發(fā)生大量內(nèi)存復(fù)制循集。

7.3 晉升策略

年輕代的對象沒熬過一次Minor GC唇敞,年齡就加一歲。默認(rèn)15歲時咒彤,就會進(jìn)入老年代疆柔。

不過這個條件并非絕對,如果Survivor中相同年齡的對象總和大于Survivor空間的一半镶柱,那么年齡大于等于該年齡的對象可以直接晉升到老年代旷档。

7.4 空間分配擔(dān)保

年輕代在Minor GC后會有對象進(jìn)入老年代,在極端情況下歇拆,年輕代所有對象都存活并進(jìn)入老年代鞋屈。

所以在MinorGC之前,虛擬機(jī)會檢查老年代的連續(xù)內(nèi)存空間是否大于年輕代所有對象總和故觅。

如果空間不夠厂庇,那么這次MinorGC是有風(fēng)險的。

如果允許冒險输吏,Minor GC會直接執(zhí)行权旷,如果失敗,會再發(fā)起一次full GC贯溅。

如果不允許冒險拄氯,則先執(zhí)行一次full GC,再進(jìn)行Minor GC它浅。

第三部分:面試題答案

  1. GC 是什么? 為什么要有 GC?

    GC就是垃圾回收译柏,釋放掉沒用的對象占用的空間,保證內(nèi)存空間不被迅速耗盡姐霍。

  2. 簡單說一下java的垃圾回收機(jī)制艇纺。

    java采用分代回收,分為年輕代邮弹、老年代黔衡、永久代。年輕代又分為E區(qū)腌乡、S1區(qū)盟劫、S2區(qū)。

    到j(luò)dk1.8与纽,永久代被元空間取代了侣签。

    年輕代都使用復(fù)制算法,老年代的收集算法看具體用什么收集器急迂。默認(rèn)是PS收集器影所,采用標(biāo)記-整理算法。

  3. JVM的常見垃圾回收算法有哪些僚碎?

    復(fù)制猴娩、標(biāo)記清除、標(biāo)記整理勺阐、分代回收

  4. 為什么要使用分代回收機(jī)制卷中?

    因?yàn)闆]有一種算法能適用所有場合。在對象存活率低的場景下渊抽,復(fù)制算法最合適蟆豫。

    對象存活率高時,標(biāo)記清除或者標(biāo)記整理算法最合適懒闷。

    所以才需要分代來處理十减。

  5. 如何判斷一個對象是否存活?

    現(xiàn)在主流使用的都是可達(dá)性分析法。從GC Roots對象計(jì)算引用鏈愤估,能鏈上的就是存活的帮辟。

  6. 如果對象的引用被置為 null,垃圾收集器是否會立即釋放對象占用的內(nèi)存?

    不會灵疮。對象回收需要一個過程织阅,這個過程中對象還能復(fù)活。而且垃圾回收具有不確定性震捣,指不定什么時候開始回收荔棉。

引用文獻(xiàn)

如何簡單理解GC roots和 gc的標(biāo)記過程

理解Java中的弱引用

理解Java中的弱引用(Weak Reference)

Java PhantomReference詳解

《深入理解Java虛擬機(jī)》
系列文章總目錄:https://mp.weixin.qq.com/s/56JgXLArTAEDj1f3y4arLA

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蒿赢,隨后出現(xiàn)的幾起案子润樱,更是在濱河造成了極大的恐慌,老刑警劉巖羡棵,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壹若,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)店展,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門养篓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赂蕴,你說我怎么就攤上這事柳弄。” “怎么了概说?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵碧注,是天一觀的道長。 經(jīng)常有香客問我糖赔,道長萍丐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任放典,我火速辦了婚禮逝变,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刻撒。我一直安慰自己骨田,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布声怔。 她就那樣靜靜地躺著态贤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪醋火。 梳的紋絲不亂的頭發(fā)上悠汽,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機(jī)與錄音芥驳,去河邊找鬼柿冲。 笑死,一個胖子當(dāng)著我的面吹牛兆旬,可吹牛的內(nèi)容都是我干的假抄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼丽猬,長吁一口氣:“原來是場噩夢啊……” “哼宿饱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脚祟,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谬以,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后由桌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體为黎,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邮丰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了铭乾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剪廉。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖片橡,靈堂內(nèi)的尸體忽然破棺而出妈经,到底是詐尸還是另有隱情,我是刑警寧澤捧书,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站骤星,受9級特大地震影響经瓷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洞难,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一舆吮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧队贱,春花似錦色冀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至编丘,卻和暖如春与学,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉抓。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工索守, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抑片。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓卵佛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敞斋。 傳聞我的和親對象是個殘疾皇子截汪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

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