理解JVM(4)- 堆內(nèi)存的分代管理

前一篇從整體上了解了一下JVM的運(yùn)行時(shí)數(shù)據(jù)區(qū),它由線程私有的棧內(nèi)存線程共享的堆內(nèi)存、方法區(qū)組成棘伴。本章節(jié)將詳細(xì)了解一下堆內(nèi)存又被分為哪些區(qū)域寞埠,或者說(shuō)JVM是如何把對(duì)象分配到這些區(qū)域上的

JVM根據(jù)對(duì)象在內(nèi)存中存活時(shí)間的長(zhǎng)短,把堆內(nèi)存分為新生代(包括一個(gè)Eden區(qū)排嫌、兩個(gè)Survivor區(qū))和老年代(Tenured或Old)畸裳。Perm代(永久代,Java 8開(kāi)始被“元空間”取代)屬于方法區(qū)了淳地,而且僅在Full GC時(shí)被回收怖糊。大致如下圖


Heap Generation

為對(duì)象分配空間,就是把一塊確定大小的內(nèi)存從堆中劃分出來(lái)(有一種例外情況颇象,就是有可能經(jīng)過(guò)JIT優(yōu)化編譯后伍伤,對(duì)象被拆分成標(biāo)量類(lèi)型從而變成了棧上分配)。新創(chuàng)建的對(duì)象主要分配在新生代的Eden區(qū)上遣钳,如果JVM啟動(dòng)了本地線程分配緩沖(TLAB扰魂,Thread Local Allocation Buffer),則對(duì)象將按線程優(yōu)先分配在TLAB上蕴茴,此區(qū)域仍然位于新生代的Eden區(qū)內(nèi)劝评。

關(guān)于TLAB

創(chuàng)建對(duì)象需要從堆中劃分出一塊確定大小的區(qū)域,那分配內(nèi)存就是把指針從可用空閑區(qū)域挪動(dòng)一段與對(duì)象大小相等的距離倦淀。而對(duì)象的創(chuàng)建是很頻繁的行為蒋畜,在并發(fā)情況并不是線程安全的,可能出現(xiàn)在給對(duì)象A分配內(nèi)存撞叽,指針還沒(méi)來(lái)得及修改姻成,對(duì)象B又同時(shí)使用了原來(lái)的指針來(lái)分配內(nèi)存的情況。為了解決這個(gè)問(wèn)題愿棋,一個(gè)可行的方案就是TLAB科展,即把內(nèi)存分配的動(dòng)作按照線程劃分在不同的空間內(nèi)進(jìn)行,即每個(gè)線程在堆內(nèi)預(yù)先分配一小塊內(nèi)存糠雨,稱為“本地線程分配緩沖”才睹。哪個(gè)線程要給對(duì)象分配內(nèi)存,就在自己的TLAB上分配甘邀,當(dāng)自己的TLAB用完再去申請(qǐng)新的TLAB砂竖,這個(gè)時(shí)候再去進(jìn)行指針的同步鎖定,從而減小開(kāi)銷(xiāo)鹃答。


TLAB

對(duì)象優(yōu)先分配在Eden區(qū)

大部分情況下,對(duì)象會(huì)在新生代的Eden區(qū)中分配空間突硝,當(dāng)Eden區(qū)沒(méi)有足夠大小的連續(xù)空間來(lái)分配給新創(chuàng)建的對(duì)象時(shí)测摔,JVM將會(huì)觸發(fā)一次Minor GC

HotSpot的開(kāi)發(fā)人員將GC執(zhí)行分為比較模糊的三種模型:

  • Minor GC:發(fā)生在新生代,回收新生代中的垃圾,速度很快但也很頻繁
  • Major GC:發(fā)生在老年代锋八,比Minor GC慢10倍以上浙于;通常會(huì)伴隨一次Minor GC
  • Full GC:回收所有區(qū)域,包括堆內(nèi)存挟纱、方法區(qū)(Java 8之前的“永久代”羞酗,Java 8開(kāi)始取代永久代的“元空間”)和直接內(nèi)存,速度慢紊服,工作線程的暫停時(shí)間長(zhǎng)

絕大多數(shù)對(duì)象所占的內(nèi)存空間會(huì)在Minor GC中被回收(IBM公司的專門(mén)研究表明檀轨,新生代中的對(duì)象98%是“朝生夕死”的),那些存活下來(lái)的對(duì)象會(huì)被分配到某一個(gè)Survivor(幸存區(qū)欺嗤,名字也很形象)参萄,但如果Survivor的空間不足以安置存活對(duì)象的話,JVM會(huì)通過(guò)“空間分配擔(dān)保機(jī)制”提前轉(zhuǎn)移這些對(duì)象到老年代去煎饼。

  1. 新生代中為什么有兩個(gè)Survivor區(qū)讹挎?為什么每次只使用其中一個(gè)呢?

這跟新生代采用的垃圾回收算法有關(guān)吆玖,新生代用的是“復(fù)制”算法筒溃,該算法的特點(diǎn)是犧牲一定的空間成本,來(lái)?yè)Q取高效率的垃圾回收沾乘,此算法不會(huì)產(chǎn)生內(nèi)存碎片怜奖,回收后內(nèi)存比較規(guī)整。關(guān)于各回收算法的細(xì)節(jié)意鲸,下一個(gè)章節(jié)再介紹烦周,這里就不累贅了。

  1. “空間分配擔(dān)痹豕耍”是什么读慎?

在發(fā)生Minor GC之前,JVM會(huì)先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對(duì)象總空間槐雾,如果這個(gè)條件成立夭委,那么Minor GC可以確保是安全的。如果不成立募强,則JVM會(huì)查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗株灸。若允許,那么會(huì)繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對(duì)象的平均大小擎值,如果大于慌烧,將嘗試進(jìn)行一次Minor GC,盡管這次Minor GC是有風(fēng)險(xiǎn)的鸠儿;如果小于屹蚊,或者HandlePromotionFailure設(shè)置不允許冒險(xiǎn)厕氨,那這時(shí)要改為進(jìn)行一次Full GC。

下面這個(gè)示例代碼演示了Survivor區(qū)空間不足汹粤,對(duì)象通過(guò)分配擔(dān)保機(jī)制被提前轉(zhuǎn)移到老年代去命斧。Debug執(zhí)行三條對(duì)象創(chuàng)建語(yǔ)句,通過(guò)JDK自帶的Java VisualVM工具jvisualvm(同時(shí)安裝Visual GC插件)嘱兼,可以直觀的看到各個(gè)內(nèi)存區(qū)的變化情況国葬。

/**
 *  -Xms90m -Xmx90m -XX:+UseParNewGC
 *
 * 固定堆大小:90m
 *     - Young Gen: 1/3 * 90 = 30m (默認(rèn) Tenured / Young = 2)
 *         - Survivor * 2 : 1/10 * 30 = 3m * 2 (兩個(gè)Survivor芹壕,默認(rèn) Eden / Survivor = 8)
 *         - Eden: 8/10 * 30 = 24m
 *     - Tenured: 2/3 * 90 = 60m  (默認(rèn) Tenured / Young = 2)
 */
public class HandlePromotionDemo {

    public static void main(String[] args) {
        byte[] obj1 = new byte[1024 * 1024 * 2];
        byte[] obj2 = new byte[1024 * 1024 * 10];
        byte[] obj3 = new byte[1024 * 1024 * 20];
    }

}

以下三個(gè)截圖分別展示了三個(gè)對(duì)象依次創(chuàng)建后的內(nèi)存各區(qū)情況


第一行代碼執(zhí)行完汇四,2MB的對(duì)象obj1創(chuàng)建成功后,Eden消耗2.480MB哪雕,這里大于obj1的大小是因?yàn)閂isualVM GC監(jiān)測(cè)工具自身也會(huì)創(chuàng)建一些臨時(shí)對(duì)象船殉。不管如何,還是可以直觀的看到obj1分配到了Eden區(qū)
第二行代碼執(zhí)行完斯嚎,10MB的對(duì)象obj2創(chuàng)建成功后利虫,Eden消耗的空間增加到了12.480MB,注意圖中圈出來(lái)的陡升區(qū)域堡僻,obj2就是在那一刻創(chuàng)建成功的
第三行代碼執(zhí)行完糠惫,20MB的對(duì)象obj3創(chuàng)建成功后,Eden消耗的空間變成了20MB钉疫。在創(chuàng)建obj3之前硼讽,JVM檢測(cè)到容量為24MB的Eden已經(jīng)消耗了12.480MB,剩下的空間不足以安置obj3牲阁,所以觸發(fā)Minor GC固阁,obj1被移到幸存區(qū)S1,但S1不能再容納大對(duì)象obj2城菊,通過(guò)“空間分配擔(dān)北溉迹”,obj2被提前轉(zhuǎn)移到老年代凌唬。此時(shí)被清空了的Eden區(qū)域可以用來(lái)分配新對(duì)象obj3了并齐,創(chuàng)建成功后,Eden消耗了20MB即為obj3的大小

大對(duì)象直接進(jìn)去老年代

大對(duì)象就是那些需要大量連續(xù)內(nèi)存空間的對(duì)象客税,比如數(shù)組及很長(zhǎng)的字符串况褪。過(guò)多的大對(duì)象容易導(dǎo)致當(dāng)內(nèi)存空間仍然還有不少時(shí)就會(huì)提前觸發(fā)GC以獲取足夠連續(xù)的空間來(lái)分配給這些大對(duì)象。
虛擬機(jī)提供了一個(gè)參數(shù)-XX:PretenureSizeThreshold更耻,那些大于這個(gè)參數(shù)值的對(duì)象將直接在老年代分配测垛,避免在Eden區(qū)和兩個(gè)Survivor區(qū)之間發(fā)生大量的內(nèi)存復(fù)制(新生代采用的是“復(fù)制”垃圾回收算法)。

下面這個(gè)示例代碼指定一個(gè)Survivor區(qū)域容量大小為4MB秧均,同時(shí)設(shè)置-XX:PretenureSizeThreshold=3145728赐纱,即3MB脊奋,之后創(chuàng)建一個(gè)略大于3MB的對(duì)象。運(yùn)行此程序后疙描,從VisualVM GC中可以看到此對(duì)象被分配到了老年代。

/**
 * -Xmn16m -Xms30m -Xmx30m -XX:SurvivorRatio=2 -XX:+UseParNewGC -XX:PretenureSizeThreshold=3145728 -XX:-UseTLAB
 *
 * Fixed Heap: 30MB
 *    - Survivor * 2: 4MB * 2
 *    - Eden: 8MB
 *    - Tenured: 14MB 
 */
public class BiggerThanPretenureSizeThresholdObjToOld {

    public static void main(String[] args) throws Exception {
        System.gc(); // 嘗試清除由監(jiān)測(cè)工具生成的臨時(shí)對(duì)象
        Thread.sleep(10000L);

        byte[] obj = new byte[1024 * 1024 * 3 + 1];
        boolean flag = true;
        while(flag) {
            Thread.yield();
        }
    }

}
對(duì)象obj創(chuàng)建成功后讶隐,被分配在老年代

對(duì)于極端情況起胰,參數(shù)-XX:PretenureSizeThreshold未設(shè)置,而對(duì)象大于Eden空間的話巫延,則同樣直接在老年代分配空間

長(zhǎng)期存活的對(duì)象會(huì)被晉升到老年代

虛擬機(jī)在進(jìn)行內(nèi)存回收的時(shí)候效五,為了能夠識(shí)別哪些對(duì)象應(yīng)該繼續(xù)留在新生代(某一個(gè)Survivor區(qū))、哪些對(duì)象應(yīng)該被晉升(轉(zhuǎn)移)到老年代炉峰,它給每個(gè)對(duì)象定義了一個(gè)對(duì)象年齡(Age)計(jì)數(shù)器畏妖。所有在新生代出生的對(duì)象,年齡可以認(rèn)為是0疼阔,此時(shí)的數(shù)值沒(méi)有任何意義戒劫。當(dāng)對(duì)象經(jīng)過(guò)第一次Minor GC后任然存活,并且Survivor有足夠的空間來(lái)容納它的話婆廊,對(duì)象被順利轉(zhuǎn)移到Survivor中迅细,此時(shí)對(duì)象開(kāi)始擁有實(shí)際意義的年齡,為1歲淘邻。在此之后茵典,Survivor中的對(duì)象每“熬過(guò)”一次Minor GC,年齡就會(huì)增加1歲宾舅,當(dāng)達(dá)到一定的年齡閾值(默認(rèn)是15歲统阿,可通過(guò)參數(shù)-XX:MaxTenuringThreshold設(shè)置),對(duì)象就會(huì)被晉升到老年代中筹我。老年代中的對(duì)象就沒(méi)有年齡的意義了扶平。

下面我們通過(guò)一個(gè)示例來(lái)演示一下:對(duì)象年齡達(dá)到閾值后被晉升到老年代。設(shè)置參數(shù)崎溃,固定堆大小為90MB蜻直,新生代45MB,其中Eden和Survivor各占15MB袁串、15MB概而、15MB,年齡閾值為2歲囱修。

/**
 *  -XX:+PrintGCDetails -Xmn45m -Xms90m -Xmx90m -XX:SurvivorRatio=1 -XX:MaxTenuringThreshold=2 -XX:+UseParNewGC
 *
 *  Fixed Heap: 90M
 *      - Survivor *2: 15M *2
 *      - Edeb: 15M
 *      - Tenured(Old): 45M
 */
public class AgeOlderThanTenuringThresholdObjToOld {

    public static void main(String[] args) throws Exception {
        System.gc(); //嘗試清除由監(jiān)測(cè)工具生成的臨時(shí)對(duì)象

        byte[] obj1 = new byte[1024 * 1024 * 2]; //執(zhí)行完這一行之后各區(qū)使用情況: Eden[obj1]: 2/15, S0: 0/15, S1: 0/15, Old: 0/45
        byte[] obj2 = new byte[1024 * 1024 * 2]; //執(zhí)行完這一行之后各區(qū)使用情況: Eden[obj1,obj2]: 4/15, S0: 0/15, S1: 0/15, Old: 0/45
        byte[] obj3 = new byte[1024 * 1024 * 12]; //對(duì)象obj3創(chuàng)建成功之前赎瑰,虛擬機(jī)檢測(cè)到Eden剩余空間(15-4=11)不足以分配給obj3,因此觸發(fā)第一次Minor GC來(lái)釋放空間給obj3破镰,obj1和obj2晉升到幸存區(qū)餐曼,年齡為1压储,各區(qū)使用情況: Eden[obj3]: 12/15, S0: 0/15, S1[obj1(age=1),obj2(age=1)]: 4/15, Old: 0/45
        obj3 = null; //obj3不再有任何引用關(guān)聯(lián),下次GC的時(shí)候?qū)?huì)被回收
        byte[] obj4 = new byte[1024 * 1024 * 4]; //對(duì)象obj4創(chuàng)建成功之前源譬,虛擬機(jī)檢測(cè)到Eden剩余空間(15-12=3)不足以分配給obj4集惋,因此觸發(fā)第二次Minor GC來(lái)釋放空間給obj4,這次GC中obj3會(huì)被回收踩娘,之后各區(qū)使用情況: Eden[obj4]: 4/15, S0:[obj1(age=2),obj2(age=2)]: 4/15, S1: 0/15, Old: 0/45
        byte[] obj5 = new byte[1024 * 1024 * 12]; //對(duì)象obj5創(chuàng)建成功之前刮刑,虛擬機(jī)檢測(cè)到Eden剩余空間(15-4=11)不足以分配給obj5,因此觸發(fā)第三次MinorGC來(lái)釋放空間給obj5养渴,這次GC中由于obj1,obj2的年齡都到達(dá)了閾值2歲雷绢,所以這兩個(gè)對(duì)象將被晉升到老年代,之后各區(qū)使用情況:Eden[obj5]: 12/15, S0: 0/15, S1[obj4(age=1)]: 4/15, Old[obj1,obj2]: 4/45
    }

}

Debug逐行執(zhí)行上面5個(gè)對(duì)象的創(chuàng)建語(yǔ)句理卑,每個(gè)對(duì)象創(chuàng)建成功后的各區(qū)使用情況如下各圖:

對(duì)象obj1創(chuàng)建成功之后各區(qū)使用情況: Eden[obj1]: 2/15, S0: 0/15, S1: 0/15, Old: 0/45
對(duì)象obj2創(chuàng)建之后各區(qū)使用情況: Eden[obj1,obj2]: 4/15, S0: 0/15, S1: 0/15, Old: 0/45
對(duì)象obj3創(chuàng)建成功之前翘紊,虛擬機(jī)檢測(cè)到Eden剩余空間(15-4=11)不足以分配給obj3,因此觸發(fā)第一次Minor GC來(lái)釋放空間給obj3藐唠,obj1和obj2晉升到幸存區(qū)帆疟,年齡為1,各區(qū)使用情況: Eden[obj3]: 12/15, S0: 0/15, S1[obj1(age=1),obj2(age=1)]: 4/15, Old: 0/45
對(duì)象obj4創(chuàng)建成功之前中捆,虛擬機(jī)檢測(cè)到Eden剩余空間(15-12=3)不足以分配給obj4鸯匹,因此觸發(fā)第二次Minor GC來(lái)釋放空間給obj4,這次GC中obj3會(huì)被回收泄伪,之后各區(qū)使用情況: Eden[obj4]: 4/15, S0:[obj1(age=2),obj2(age=2)]: 4/15, S1: 0/15, Old: 0/45
對(duì)象obj5創(chuàng)建成功之前殴蓬,虛擬機(jī)檢測(cè)到Eden剩余空間(15-4=11)不足以分配給obj5,因此觸發(fā)第三次MinorGC來(lái)釋放空間給obj5蟋滴,這次GC中由于obj1,obj2的年齡都到達(dá)了閾值2歲染厅,所以這兩個(gè)對(duì)象將被晉升到老年代,之后各區(qū)使用情況:Eden[obj5]: 12/15, S0: 0/15, S1[obj4(age=1)]: 4/15, Old[obj1,obj2]: 4/45

動(dòng)態(tài)對(duì)象年齡判斷

虛擬機(jī)并不是永遠(yuǎn)的要等到對(duì)象年齡達(dá)到閾值后才能晉升到老年代津函,當(dāng)Survivor中相同年齡(比如N)的所有對(duì)象的大小總和大于Survivor的一半的時(shí)候肖粮,那些年齡大于等于N所有對(duì)象將會(huì)直接提前進(jìn)入老年代。

示例代碼如下:固定堆大小為90MB尔苦,新生代45MB涩馆,其中Eden和Survivor各占15MB、15MB允坚、15MB魂那,未設(shè)置最大年齡閾值,使用默認(rèn)值15稠项。

/**
 *  -XX:+PrintGCDetails -Xmn45m -Xms90m -Xmx90m -XX:SurvivorRatio=1 -XX:+UseParNewGC
 *
 *  Fixed Heap: 90M
 *      - Survivor *2: 15M *2
 *      - Edeb: 15M
 *      - Tenured(Old): 45M
 */
public class DynamicAge {

    public static void main(String[] args) throws Exception {
        System.gc(); //嘗試清除由監(jiān)測(cè)工具生成的臨時(shí)對(duì)象

        byte[] obj1 = new byte[1024 * 1024 * 4]; //執(zhí)行完這一行之后各區(qū)使用情況: Eden[obj1]: 4/15, S0: 0/15, S1: 0/15, Old: 0/45
        byte[] obj2 = new byte[1024 * 1024 * 4]; //執(zhí)行完這一行之后各區(qū)使用情況: Eden[obj1,obj2]: 8/15, S0: 0/15, S1: 0/15, Old: 0/45
        byte[] obj3 = new byte[1024 * 1024 * 12]; //對(duì)象obj3創(chuàng)建成功之前涯雅,虛擬機(jī)檢測(cè)到Eden剩余空間(15-8=7)不足以分配給obj3,因此觸發(fā)第一次Minor GC來(lái)釋放空間給obj3展运,obj1和obj2晉升到幸存區(qū),年齡為1,各區(qū)使用情況: Eden[obj3]: 12/15, S0: 0/15, S1[obj1(age=1),obj2(age=1)]: 8/15, Old: 0/45
        obj3 = null; //obj3不再有任何引用關(guān)聯(lián)次员,下次GC的時(shí)候?qū)?huì)被回收
        byte[] obj4 = new byte[1024 * 1024 * 4]; //對(duì)象obj4創(chuàng)建成功之前,虛擬機(jī)檢測(cè)到Eden剩余空間(15-12=3)不足以分配給obj4怒允,因此觸發(fā)第二次MinorGC來(lái)釋放空間給obj4,這次GC中由于Survivor區(qū)中的obj1和obj2的大小之和8超過(guò)了Survivor大小15的一半琴庵,所以這兩個(gè)對(duì)象將被提前晉升到老年代误算,而對(duì)象obj3由于沒(méi)有任何引用,直接被回收了迷殿,之后各區(qū)使用情況: Eden[obj4]: 4/15, S0: 0/15, S1: 0/15, Old[obj1,obj2]: 8/45
     
    }

}

Debug逐行執(zhí)行上面4個(gè)對(duì)象的創(chuàng)建語(yǔ)句,每個(gè)對(duì)象創(chuàng)建成功后的各區(qū)使用情況如下各圖:

對(duì)象obj1創(chuàng)建之后各區(qū)使用情況: Eden[obj1]: 4/15, S0: 0/15, S1: 0/15, Old: 0/45

對(duì)象obj2創(chuàng)建之后各區(qū)使用情況: Eden[obj1,obj2]: 8/15, S0: 0/15, S1: 0/15, Old: 0/45
對(duì)象obj3創(chuàng)建成功之前咖杂,虛擬機(jī)檢測(cè)到Eden剩余空間(15-8=7)不足以分配給obj3庆寺,因此觸發(fā)第一次Minor GC來(lái)釋放空間給obj3,obj1和obj2晉升到幸存區(qū)诉字,年齡為1懦尝,各區(qū)使用情況: Eden[obj3]: 12/15, S0: 0/15, S1[obj1(age=1),obj2(age=1)]: 8/15, Old: 0/45
對(duì)象obj4創(chuàng)建成功之前,虛擬機(jī)檢測(cè)到Eden剩余空間(15-12=3)不足以分配給obj4壤圃,因此觸發(fā)第二次MinorGC來(lái)釋放空間給obj4陵霉,這次GC中由于Survivor區(qū)中的obj1和obj2的大小之和8超過(guò)了Survivor大小15的一半,所以這兩個(gè)對(duì)象將被提前晉升到老年代伍绳,而對(duì)象obj3由于沒(méi)有任何引用踊挠,直接被回收了,之后各區(qū)使用情況: Eden[obj4]: 4/15, S0: 0/15, S1: 0/15, Old[obj1,obj2]: 8/45

至此冲杀,關(guān)于對(duì)象在堆內(nèi)各區(qū)分配的幾種情況就大致講解到這里效床。下一章將了解一下垃圾收集器的原理。

上一篇:理解JVM(3)- 運(yùn)行時(shí)數(shù)據(jù)區(qū)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末权谁,一起剝皮案震驚了整個(gè)濱河市剩檀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旺芽,老刑警劉巖沪猴,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異采章,居然都是意外死亡运嗜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)共缕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洗出,“玉大人,你說(shuō)我怎么就攤上這事图谷◆婊睿” “怎么了阱洪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)菠镇。 經(jīng)常有香客問(wèn)我冗荸,道長(zhǎng),這世上最難降的妖魔是什么利耍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任蚌本,我火速辦了婚禮,結(jié)果婚禮上隘梨,老公的妹妹穿的比我還像新娘程癌。我一直安慰自己,他們只是感情好轴猎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布嵌莉。 她就那樣靜靜地躺著,像睡著了一般捻脖。 火紅的嫁衣襯著肌膚如雪锐峭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天可婶,我揣著相機(jī)與錄音沿癞,去河邊找鬼。 笑死矛渴,一個(gè)胖子當(dāng)著我的面吹牛椎扬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曙旭,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼盗舰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了桂躏?” 一聲冷哼從身側(cè)響起钻趋,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剂习,沒(méi)想到半個(gè)月后蛮位,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳞绕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年失仁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片们何。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萄焦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拂封,我是刑警寧澤茬射,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站冒签,受9級(jí)特大地震影響在抛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜萧恕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一刚梭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧票唆,春花似錦朴读、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吆视,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間酥宴,已是汗流浹背啦吧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拙寡,地道東北人授滓。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像肆糕,于是被迫代替她去往敵國(guó)和親般堆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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