JVM運(yùn)行期優(yōu)化及逃逸分析實(shí)戰(zhàn)

運(yùn)行期優(yōu)化

樓主最近在網(wǎng)上看到一篇寫關(guān)于JVM運(yùn)行期優(yōu)化的博客杈女,經(jīng)過整理洋丐,現(xiàn)在分享給大家:

image.png

我們知道淑掌,Java 是解釋執(zhí)行的蒿讥,可是解釋執(zhí)行畢竟還是有點(diǎn)慢的,這也使得 Java 一直被認(rèn)為是效率低下的語言……,不過隨著即時(shí)編譯技術(shù)的發(fā)展芋绸,Java 的運(yùn)行速度得到了很大的提升媒殉,在本篇文章中,我們將會(huì)對(duì) Java 的運(yùn)行期優(yōu)化摔敛,也就是即時(shí)編譯 (Just In Time, JIT) 時(shí)進(jìn)行的優(yōu)化進(jìn)行詳細(xì)的講解廷蓉,我們先來看看什么是即時(shí)編譯。

即時(shí)編譯

什么是即時(shí)編譯恒削?

  • 當(dāng)虛擬機(jī)發(fā)現(xiàn)某個(gè)方法或某段代碼運(yùn)行的特別頻繁時(shí)池颈,會(huì)把這段代碼認(rèn)為成熱點(diǎn)代碼;
  • 在運(yùn)行時(shí)钓丰,虛擬機(jī)會(huì)將這段代碼編譯成平臺(tái)相關(guān)的機(jī)器碼躯砰,并進(jìn)行各種層次的優(yōu)化。

HotSpot 虛擬機(jī)內(nèi)的即時(shí)編譯器運(yùn)作過程

我們主要通過以下 5 個(gè)問題來了解 HotSpot 虛擬機(jī)的即時(shí)編譯器。

為什么要使用解釋器與編譯器并存的架構(gòu)?

  • 解釋器的優(yōu)點(diǎn):可以提高程序的響應(yīng)速度(省去了編譯的時(shí)間),并且節(jié)約內(nèi)存。
  • 編譯器的優(yōu)點(diǎn):可以提高執(zhí)行效率藕溅。
  • 虛擬機(jī)參數(shù)設(shè)置:
    • 強(qiáng)制運(yùn)行于解析模式:-Xint略吨,編譯器完全不工作乞榨;
    • 強(qiáng)制運(yùn)行于編譯模式:-Xcomp,當(dāng)編譯器編譯失敗時(shí),解釋執(zhí)行還是會(huì)介入的。
      • 混合模式:-Xmixed 開始解釋執(zhí)行划址,啟動(dòng)速度較快,對(duì)熱點(diǎn)代碼實(shí)行檢測(cè)和編譯

為什么虛擬機(jī)要實(shí)現(xiàn)兩個(gè)不同的 JIT 編譯器宜狐?

  • Client Compiler(C1):不激進(jìn)優(yōu)化;
  • Server Compiler(C2):激進(jìn)優(yōu)化,如果激進(jìn)優(yōu)化不成立,再退回為解釋執(zhí)行或者 C1 編譯器執(zhí)行翼岁。

什么是虛擬機(jī)的分層編譯榆俺?

分層編譯就是根據(jù)編譯器編譯、優(yōu)化的規(guī)模與耗時(shí)付枫,劃分出不同的編譯層次二打,在代碼運(yùn)行的過程中,可以動(dòng)態(tài)的選擇將某一部分代碼片段提升一個(gè)編譯層次或者降低一個(gè)編譯層次掂榔。

C1 與 C2 編譯器會(huì)同時(shí)工作继效,許多代碼可能會(huì)被多次編譯。

目的: 在程序的啟動(dòng)響應(yīng)時(shí)間和運(yùn)行效率間達(dá)到平衡装获。

編譯層次的劃分:

  • 第 0 層:解釋執(zhí)行瑞信,不開啟性能監(jiān)控;
  • 第 1 層:將字節(jié)編譯為機(jī)器碼穴豫,但不進(jìn)行激進(jìn)優(yōu)化凡简,有必要時(shí)會(huì)加入性能監(jiān)控;
  • 第 2 層及以上:將字節(jié)編譯為機(jī)器碼,會(huì)根據(jù)性能監(jiān)控信息進(jìn)行激進(jìn)優(yōu)化秤涩。

如何判斷熱點(diǎn)代碼帜乞,觸發(fā)編譯?

什么是熱點(diǎn)代碼溉仑?

  • 被多次調(diào)用的方法挖函;
  • 被多次執(zhí)行的循環(huán)體;
    • 雖然被判斷為熱點(diǎn)代碼的是循環(huán)體浊竟,不過因?yàn)樘摂M機(jī)的即時(shí)編譯是以方法為單位的怨喘,所以編譯器還是會(huì)將循環(huán)體所在的方法整個(gè)作為編譯對(duì)象。

我們發(fā)現(xiàn)振定,判斷熱點(diǎn)代碼的一個(gè)要點(diǎn)就是: 多次執(zhí)行 必怜。那么虛擬機(jī)是如何知道一個(gè)方法或者一個(gè)循環(huán)體被多次執(zhí)行的呢?

什么是 “多次” 執(zhí)行后频?

  • 基于采樣的熱點(diǎn)探測(cè)
    • 虛擬機(jī)周期檢查各個(gè)線程的棧頂梳庆,如果發(fā)現(xiàn)一個(gè)方法經(jīng)常出現(xiàn)在棧頂,則該方法為熱點(diǎn)方法卑惜。
    • 優(yōu)點(diǎn): 容易獲取方法的調(diào)用關(guān)系膏执,且簡單高效。
    • 缺點(diǎn): 無法精準(zhǔn)的判斷一個(gè)方法的熱度露久,并且容易受到線程阻塞的影響更米,如果一個(gè)方法由于它所在的線程被阻塞的緣故而一直出現(xiàn)在棧頂,我們并不能認(rèn)為這個(gè)方法被調(diào)用的十分頻繁毫痕。
  • 基于計(jì)數(shù)器的熱點(diǎn)探測(cè)
    • 虛擬機(jī)為每一個(gè)方法(或代碼塊)建立一個(gè)計(jì)數(shù)器征峦,一旦執(zhí)行次數(shù)超過一定閾值,就將其判為熱點(diǎn)代碼消请。
    • 優(yōu)點(diǎn): 精確嚴(yán)謹(jǐn)栏笆。
    • 缺點(diǎn): 不能直接獲取方法的調(diào)用關(guān)系,且實(shí)現(xiàn)復(fù)雜臊泰。
    • HotSpot 使用的是這個(gè)蛉加,并且還為每個(gè)方法建立了兩個(gè)計(jì)數(shù)器。

HotSpot 中每個(gè)方法的 2 個(gè)計(jì)數(shù)器

  • 方法調(diào)用計(jì)數(shù)器
    • 統(tǒng)計(jì)方法被調(diào)用的次數(shù)缸逃,處理多次調(diào)用的方法的七婴。
    • 默認(rèn)統(tǒng)計(jì)的不是方法調(diào)用的絕對(duì)次數(shù),而是方法在一段時(shí)間內(nèi)被調(diào)用的次數(shù)察滑,如果超過這個(gè)時(shí)間限制還沒有達(dá)到判為熱點(diǎn)代碼的閾值打厘,則該方法的調(diào)用計(jì)數(shù)器值減半。
      • 關(guān)閉熱度衰減:-XX: -UseCounterDecay(此時(shí)方法計(jì)數(shù)器統(tǒng)計(jì)的是方法被調(diào)用的絕對(duì)次數(shù))贺辰;
      • 設(shè)置半衰期時(shí)間:-XX: CounterHalfLifeTime(單位是秒)户盯;
      • 熱度衰減過程是在 GC 時(shí)順便進(jìn)行嵌施。
  • 回邊計(jì)數(shù)器
    • 統(tǒng)計(jì)一個(gè)方法中 “回邊” 的次數(shù),處理多次執(zhí)行的循環(huán)體的莽鸭。
      • 回邊:在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令(不是所有循環(huán)體都是回邊吗伤,空循環(huán)體是自己跳向自己,沒有向后跳硫眨,不算回邊)足淆。
    • 調(diào)整回邊計(jì)數(shù)器閾值:-XX: OnStackReplacePercentage(OSR比率)
      • Client 模式:回邊計(jì)數(shù)器的閾值 = 方法調(diào)用計(jì)數(shù)器閾值 * OSR比率 / 100
      • Server 模式:回邊計(jì)數(shù)器的閾值 = 方法調(diào)用計(jì)數(shù)器閾值 * ( OSR比率 - 解釋器監(jiān)控比率 ) / 100礁阁;

HotSpot 熱點(diǎn)代碼探測(cè)流程

基于計(jì)數(shù)器的熱點(diǎn)代碼探測(cè)流程.png

熱點(diǎn)代碼編譯的過程巧号?

虛擬機(jī)在代碼編譯未完成時(shí)會(huì)按照解釋方式繼續(xù)執(zhí)行,編譯動(dòng)作在后臺(tái)的編譯線程執(zhí)行姥闭。

禁止后臺(tái)編譯:-XX: -BackgroundCompilation丹鸿,打開后這個(gè)開關(guān)參數(shù)后,交編譯請(qǐng)求的線程會(huì)等待編譯完成棚品,然后執(zhí)行編譯器輸出的本地代碼靠欢。

經(jīng)典優(yōu)化技術(shù)介紹

Content:

  • 公共子表達(dá)式消除【語言無關(guān)】
  • 數(shù)組范圍檢查消除【語言相關(guān)】
  • 方法內(nèi)聯(lián)【最重要】
  • 逃逸分析【最前沿】

公共子表達(dá)式消除【語言無關(guān)】

如果一個(gè)表達(dá)式 E 已經(jīng)計(jì)算過了,并且從先前的計(jì)算到現(xiàn)在铜跑,E 中所有變量值都沒有發(fā)生變化门怪,則 E 為公共子表達(dá)式,無需再次計(jì)算锅纺,直接用之前的結(jié)果替換薪缆。

數(shù)組范圍檢查消除【語言相關(guān)】

在循環(huán)中使用循環(huán)變量訪問數(shù)組,如果可以判斷循環(huán)變量的范圍在數(shù)組的索引范圍內(nèi)伞广,則可以消除整個(gè)循環(huán)的數(shù)組范圍檢查

方法內(nèi)聯(lián)【最重要】

目的是:去除方法調(diào)用的成本(如建立棧幀等),并為其他優(yōu)化建立良好的基礎(chǔ)疼电,所以一般將方法內(nèi)兩放在優(yōu)化序列最前端嚼锄,因?yàn)樗鼘?duì)其他優(yōu)化有幫助。

類型繼承關(guān)系分析(Class Hierarchy Analysis蔽豺,CHA)

用于確定在目前已加載的類中区丑,某個(gè)接口是否有多于一種的實(shí)現(xiàn),某個(gè)類是否存在子類修陡、子類是否為抽象類等沧侥。

  • 對(duì)于非虛方法:
    • 直接進(jìn)行內(nèi)聯(lián),其調(diào)用方法的版本在編譯時(shí)已經(jīng)確定魄鸦,是根據(jù)變量的靜態(tài)類型決定的宴杀。
  • 對(duì)于虛方法: (激進(jìn)優(yōu)化,要預(yù)留“逃生門”)
    • 向 CHA 查詢此方法在當(dāng)前程序下是否有多個(gè)目標(biāo)可選擇拾因;
      • 只有一個(gè)目標(biāo)版本:
        • 先對(duì)這唯一的目標(biāo)進(jìn)行內(nèi)聯(lián)旺罢;
        • 如果之后的執(zhí)行中旷余,虛擬機(jī)沒有加載到會(huì)令這個(gè)方法接收者的繼承關(guān)系發(fā)生改變的新類,則該內(nèi)聯(lián)代碼可以一直使用扁达;
        • 如果加載到導(dǎo)致繼承關(guān)系發(fā)生變化的新類正卧,就拋棄已編譯的代碼。
      • 有多個(gè)目標(biāo)版本:
        • 使用內(nèi)聯(lián)緩存跪解,未發(fā)生方法調(diào)用前炉旷,內(nèi)聯(lián)緩存為空;
        • 第一次調(diào)用發(fā)生后叉讥,記錄調(diào)用方法的對(duì)象的版本信息窘行;
        • 之后的每次調(diào)用都要先與內(nèi)聯(lián)緩存中的對(duì)象版本信息進(jìn)行比較;
          • 版本信息一樣节吮,繼續(xù)使用內(nèi)聯(lián)代碼抽高;
          • 版本信息不一樣,說明程序使用了虛方法的多態(tài)特性透绩,這時(shí)取消內(nèi)聯(lián)翘骂,查找虛方法進(jìn)行方法分派。

逃逸分析【最前沿】

基本行為

分析對(duì)象的作用域帚豪,看它有沒有能在當(dāng)前作用域之外使用:

  • 方法逃逸:對(duì)象在方法中定義之后碳竟,能被外部方法引用,如作為參數(shù)傳遞到了其他方法中狸臣。
  • 線程逃逸:賦值給 static 變量莹桅,或可以在其他線程中訪問的實(shí)例變量。

對(duì)于不會(huì)逃逸到方法或線程外的對(duì)象能進(jìn)行優(yōu)化

  • 棧上分配: 對(duì)于不會(huì)逃逸到方法外的對(duì)象烛亦,可以在棧上分配內(nèi)存诈泼,這樣這個(gè)對(duì)象所占用的空間可以隨棧幀出棧而銷毀,減小 GC 的壓力煤禽。

    Java虛擬機(jī)中掷贾,在Java堆上分配創(chuàng)建對(duì)象的內(nèi)存空間幾乎是Java程序員都清楚的常識(shí)了捞奕,Java堆中的對(duì)象對(duì)于各個(gè)線程都是共享和可見的,可以回收堆中不再使用的對(duì)象,但回收動(dòng)作無論是篩選可回收對(duì)象轨帜,還是回收和整理內(nèi)存都需要耗費(fèi)時(shí)間.如果確定一個(gè)對(duì)象不會(huì)逃逸出方法之外费尽,那讓這個(gè)對(duì)象在棧上分配內(nèi)存將會(huì)是一個(gè)很不錯(cuò)的主意帽撑,對(duì)象所占用的內(nèi)存空間就可以隨棧幀出棧而銷毀.在一般應(yīng)用中褒搔,不會(huì)逃逸的局部變量所占的比例很大,如果能使用棧上分配恳啥,那大量的對(duì)象就會(huì)隨著方法的結(jié)束而自動(dòng)銷毀了偏灿,垃圾回收系統(tǒng)的壓力將會(huì)小很多.

  • 標(biāo)量替換(重要):

    • 標(biāo)量:基本數(shù)據(jù)類型和 reference。
    • 不創(chuàng)建對(duì)象钝的,而是將對(duì)象拆分成一個(gè)一個(gè)標(biāo)量菩混,然后直接在棧上分配忿墅,是棧上分配的一種實(shí)現(xiàn)方式。
    • HotSpot 使用的是標(biāo)量替換而不是棧上分配沮峡,因?yàn)閷?shí)現(xiàn)棧上分配需要更改大量假設(shè)了 “對(duì)象只能在堆中分配” 的代碼疚脐。

    標(biāo)量是指一個(gè)數(shù)據(jù)已經(jīng)無法再分解為更小的數(shù)據(jù)來表示了.Java虛擬機(jī)中原始數(shù)據(jù)類型(int,long等數(shù)值類型以及reference類型等)都不能再進(jìn)一步分解,它們就可以稱為標(biāo)量.相對(duì)的邢疙,如果一個(gè)數(shù)據(jù)可以繼續(xù)分解棍弄,那么它就稱作聚合量,Java中的對(duì)象就是最典型的聚合量.如果把一個(gè)Java對(duì)象拆散疟游,根據(jù)程序訪問的情況呼畸,將其使用到的成員變量恢復(fù)原始數(shù)據(jù)來訪問就叫做標(biāo)量替換.如果逃逸分析證明一個(gè)對(duì)象不會(huì)被外部訪問,并且這個(gè)對(duì)象可以被拆散的話颁虐,那程序真正執(zhí)行的時(shí)候?qū)⒖赡懿粍?chuàng)建這個(gè)對(duì)象蛮原,而改為直接創(chuàng)建它的若干個(gè)被這個(gè)方法使用到的成員變量來代替.將對(duì)象拆分后,除了可以讓對(duì)象的成員變量在棧上(棧上存儲(chǔ)的數(shù)據(jù)另绩,有很大概率會(huì)被虛擬機(jī)分配至物理機(jī)器的高速寄存器中存儲(chǔ))分配和讀寫之外儒陨,還可以為后續(xù)進(jìn)一步的優(yōu)化手段創(chuàng)建條件.

  • 鎖消除: 不會(huì)逃逸到線程外的方法不需要進(jìn)行同步。

    線程同步本身是一個(gè)相對(duì)耗時(shí)的過程笋籽,如果逃逸分析能夠確定一個(gè)變量不會(huì)逃逸出線程蹦漠,無法被其他線程訪問,那這個(gè)變量的讀寫肯定就不會(huì)有競(jìng)爭车海,對(duì)這個(gè)變量實(shí)施的同步措施也就可以消除掉.

虛擬機(jī)參數(shù)

  • 開啟逃逸分析:-XX: +DoEscapeAnalysis
  • 開啟標(biāo)量替換:-XX: +EliminateAnalysis
  • 開啟鎖消除:-XX: +EliminateLocks
  • 查看分析結(jié)果:-XX: PrintEscapeAnalysis
  • 查看標(biāo)量替換情況:-XX: PrintEliminateAllocations

一個(gè)優(yōu)化的例子

原始代碼:

static class B {
    int value;
    final int get() {
        return value;
    }
}

public void foo() {
    y = b.get();
    // ...do stuff...
    z = b.get();
    sum = y + z;
}

第一步優(yōu)化: 方法內(nèi)聯(lián)(一般放在優(yōu)化序列最前端笛园,因?yàn)閷?duì)其他優(yōu)化有幫助)

目的:

  • 去除方法調(diào)用的成本(如建立棧幀等)
  • 為其他優(yōu)化建立良好的基礎(chǔ)
public void foo() {
    y = b.value;
    // ...do stuff...
    z = b.value;
    sum = y + z;
}

第二步優(yōu)化: 公共子表達(dá)式消除

public void foo() {
    y = b.value;
    // ...do stuff...  // 因?yàn)檫@部分并沒有改變 b.value 的值
                       // 如果把 b.value 看成一個(gè)表達(dá)式,就是公共表達(dá)式消除
    z = y;             // 把這一步的 b.value 替換成 y
    sum = y + z;
}

第三步優(yōu)化: 復(fù)寫傳播

public void foo() {
    y = b.value;
    // ...do stuff...
    y = y;             // z 變量與以相同侍芝,完全沒有必要使用一個(gè)新的額外變量
                       // 所以將 z 替換為 y
    sum = y + z;
}

第四步優(yōu)化: 無用代碼消除

無用代碼:

  • 永遠(yuǎn)不會(huì)執(zhí)行的代碼
  • 完全沒有意義的代碼
public void foo() {
    y = b.value;
    // ...do stuff...
    // y = y; 這句沒有意義的研铆,去除
    sum = y + y;
}


逃逸分析實(shí)戰(zhàn)

實(shí)驗(yàn)準(zhǔn)備
  1. 強(qiáng)制開啟逃逸分析(JVM默認(rèn)開啟太醫(yī))
    -XX:+DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m
  2. 關(guān)閉逃逸分析
    -XX:-DoEscapeAnalysis -XX:+PrintGCDetail -Xmx10m -Xms10m
代碼實(shí)例
public class OnStackTest {
    public static void alloc() {
        byte[] b = new byte[2];
        b[0] = 1;
    }

    public static void main(String[] args) {
        long b = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            alloc();
        }
        long e = System.currentTimeMillis();
        System.out.println(e - b);
    }
}
實(shí)驗(yàn)結(jié)果
  1. 開啟逃逸的運(yùn)行結(jié)果


    開啟逃逸分析
  2. 關(guān)閉逃逸的運(yùn)行結(jié)果


    關(guān)閉逃逸分享
實(shí)驗(yàn)分析

分析一下,這里是將2個(gè)字節(jié)的數(shù)據(jù)循環(huán)分配1千萬次州叠,開啟逃逸的運(yùn)行時(shí)間為28milisecond棵红, 而未開啟則為2726, 為未開啟的將近1/100.
差異效果還是非常明顯的…..

實(shí)驗(yàn)總結(jié)

棧上的空間一般而言是非常小的留量,只能存放若干變化和小的數(shù)據(jù)結(jié)構(gòu),大容量的存儲(chǔ)結(jié)構(gòu)是做不到哟冬。這里的例子是一個(gè)極端的千萬次級(jí)的循環(huán)楼熄,突出了通過逃逸分析,讓其直接從棧上分配浩峡,從而極大降低了GC的次數(shù)可岂,提升了程序整體的執(zhí)行效能。
所以翰灾,逃逸分析的效果只能在特定場(chǎng)景下缕粹,滿足高頻和高數(shù)量的容量比較小的變量分配結(jié)構(gòu)稚茅,才可以生效。

轉(zhuǎn)載于

  1. https://github.com/TangBean/understanding-the-jvm/blob/master/Ch4-Java%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E4%BC%98%E5%8C%96/00-Java%E8%BF%90%E8%A1%8C%E6%9C%9F%E4%BC%98%E5%8C%96.md#%E9%80%83%E9%80%B8%E5%88%86%E6%9E%90%E6%9C%80%E5%89%8D%E6%B2%BF
  2. https://blog.csdn.net/blueheart20/article/details/76167489
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末平斩,一起剝皮案震驚了整個(gè)濱河市亚享,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绘面,老刑警劉巖欺税,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異揭璃,居然都是意外死亡晚凿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門瘦馍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歼秽,“玉大人,你說我怎么就攤上這事情组≡锟辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵呻惕,是天一觀的道長荆责。 經(jīng)常有香客問我,道長亚脆,這世上最難降的妖魔是什么做院? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮濒持,結(jié)果婚禮上键耕,老公的妹妹穿的比我還像新娘。我一直安慰自己柑营,他們只是感情好屈雄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著官套,像睡著了一般酒奶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奶赔,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天惋嚎,我揣著相機(jī)與錄音,去河邊找鬼站刑。 笑死另伍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绞旅。 我是一名探鬼主播摆尝,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼温艇,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了堕汞?” 一聲冷哼從身側(cè)響起勺爱,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎臼朗,沒想到半個(gè)月后邻寿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡视哑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年绣否,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挡毅。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蒜撮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跪呈,到底是詐尸還是另有隱情段磨,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布耗绿,位于F島的核電站苹支,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏误阻。R本人自食惡果不足惜债蜜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望究反。 院中可真熱鬧寻定,春花似錦、人聲如沸精耐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卦停。三九已至向胡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惊完,已是汗流浹背僵芹。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留专执,地道東北人淮捆。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓郁油,卻偏偏與公主長得像本股,于是被迫代替她去往敵國和親攀痊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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