Java命令: jstack

jstack

jstack是java虛擬機(jī)自帶的一種堆棧跟蹤工具。

功能

jstack用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照井辜。線程快照是當(dāng)前java虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合岸军,生成線程快照的主要目的是定位線程出現(xiàn)長時(shí)間停頓的原因荸恕,如線程間死鎖叹誉、死循環(huán)糖埋、請求外部資源導(dǎo)致的長時(shí)間等待等。 線程出現(xiàn)停頓的時(shí)候通過jstack來查看各個(gè)線程的調(diào)用堆棧哼转,就可以知道沒有響應(yīng)的線程到底在后臺(tái)做什么事情明未,或者等待什么資源。 如果java程序崩潰生成core文件壹蔓,jstack工具可以用來獲得core文件的java stack和native stack的信息趟妥,從而可以輕松地知道java程序是如何崩潰和在程序何處發(fā)生問題。另外披摄,jstack工具還可以附屬到正在運(yùn)行的java程序中,看到當(dāng)時(shí)運(yùn)行的java程序的java stack和native stack的信息, 如果現(xiàn)在運(yùn)行的java程序呈現(xiàn)hung的狀態(tài)勇凭,jstack是非常有用的虾标。

So,jstack命令主要用來查看Java線程的調(diào)用堆棧的贞让,可以用來分析線程問題(如死鎖)。

線程狀態(tài)

想要通過jstack命令來分析線程的情況的話制跟,首先要知道線程都有哪些狀態(tài)舅桩,下面這些狀態(tài)是我們使用jstack命令查看線程堆棧信息時(shí)可能會(huì)看到的線程的幾種狀態(tài):

NEW,未啟動(dòng)的。不會(huì)出現(xiàn)在Dump中雨膨。
RUNNABLE,在虛擬機(jī)內(nèi)執(zhí)行的擂涛。
BLOCKED,受阻塞并等待監(jiān)視器鎖。
WATING,無限期等待另一個(gè)線程執(zhí)行特定操作聊记。
TIMED_WATING,有時(shí)限的等待另一個(gè)線程的特定操作撒妈。
TERMINATED,已退出的恢暖。

Monitor

在多線程的 JAVA程序中,實(shí)現(xiàn)線程之間的同步狰右,就要說說 Monitor杰捂。 Monitor是 Java中用以實(shí)現(xiàn)線程之間的互斥與協(xié)作的主要手段,它可以看成是對象或者 Class的鎖棋蚌。每一個(gè)對象都有嫁佳,也僅有一個(gè) monitor。下 面這個(gè)圖谷暮,描述了線程和 Monitor之間關(guān)系蒿往,以 及線程的狀態(tài)轉(zhuǎn)換圖:
![image13]

進(jìn)入?yún)^(qū)(Entrt Set):表示線程通過synchronized要求獲取對象的鎖。如果對象未被鎖住,則迚入擁有者;否則則在進(jìn)入?yún)^(qū)等待湿弦。一旦對象鎖被其他線程釋放,立即參與競爭熄浓。

擁有者(The Owner):表示某一線程成功競爭到對象鎖。

等待區(qū)(Wait Set):表示線程通過對象的wait方法,釋放對象的鎖,并在等待區(qū)等待被喚醒省撑。

從圖中可以看出赌蔑,一個(gè) Monitor在某個(gè)時(shí)刻,只能被一個(gè)線程擁有竟秫,該線程就是 Active Thread娃惯,而其它線程都是 Waiting Thread,分別在兩個(gè)隊(duì)列 Entry SetWait Set里面等候肥败。在 Entry Set中等待的線程狀態(tài)是 Waiting for monitor entry趾浅,而在 Wait Set中等待的線程狀態(tài)是 in Object.wait()。 先看 Entry Set里面的線程馒稍。我們稱被 synchronized保護(hù)起來的代碼段為臨界區(qū)皿哨。當(dāng)一個(gè)線程申請進(jìn)入臨界區(qū)時(shí),它就進(jìn)入了 Entry Set隊(duì)列纽谒。對應(yīng)的 code就像:

synchronized(obj) {
.........

}

調(diào)用修飾

表示線程在方法調(diào)用時(shí),額外的重要的操作证膨。線程Dump分析的重要信息。修飾上方的方法調(diào)用鼓黔。

locked <地址> 目標(biāo):使用synchronized申請對象鎖成功,監(jiān)視器的擁有者央勒。
waiting to lock <地址> 目標(biāo):使用synchronized申請對象鎖未成功,在迚入?yún)^(qū)等待。
waiting on <地址> 目標(biāo):使用synchronized申請對象鎖成功后,釋放鎖幵在等待區(qū)等待澳化。
parking to wait for <地址> 目標(biāo)

locked

at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement

通過synchronized關(guān)鍵字,成功獲取到了對象的鎖,成為監(jiān)視器的擁有者,在臨界區(qū)內(nèi)操作崔步。對象鎖是可以線程重入的。

waiting to lock

at com.jiuqi.dna.core.impl.CacheHolder.isVisibleIn(CacheHolder.java:165)
- waiting to lock <0x0000000097ba9aa8> (a CacheHolder)
at com.jiuqi.dna.core.impl.CacheGroup$Index.findHolder
at com.jiuqi.dna.core.impl.ContextImpl.find
at com.jiuqi.dna.bap.basedata.common.util.BaseDataCenter.findInfo

waiting on

at java.lang.Object.wait(Native Method)
- waiting on <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo
- locked <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingThread.run

通過synchronized關(guān)鍵字,成功獲取到了對象的鎖后,調(diào)用了wait方法,進(jìn)入對象的等待區(qū)等待缎谷。在調(diào)用棧頂出現(xiàn),線程狀態(tài)為WAITING或TIMED_WATING井濒。

parking to wait for

park是基本的線程阻塞原語,不通過監(jiān)視器在對象上阻塞。隨concurrent包會(huì)出現(xiàn)的新的機(jī)制,不synchronized體系不同。

線程動(dòng)作

線程狀態(tài)產(chǎn)生的原因

runnable:狀態(tài)一般為RUNNABLE瑞你。
in Object.wait():等待區(qū)等待,狀態(tài)為WAITING或TIMED_WAITING酪惭。
waiting for monitor entry:進(jìn)入?yún)^(qū)等待,狀態(tài)為BLOCKED。
waiting on condition:等待區(qū)等待捏悬、被park撞蚕。
sleeping:休眠的線程,調(diào)用了Thread.sleep()润梯。

Wait on condition 該狀態(tài)出現(xiàn)在線程等待某個(gè)條件的發(fā)生过牙。具體是什么原因,可以結(jié)合 stacktrace來分析纺铭。 最常見的情況就是線程處于sleep狀態(tài)寇钉,等待被喚醒。 常見的情況還有等待網(wǎng)絡(luò)IO:在java引入nio之前舶赔,對于每個(gè)網(wǎng)絡(luò)連接扫倡,都有一個(gè)對應(yīng)的線程來處理網(wǎng)絡(luò)的讀寫操作,即使沒有可讀寫的數(shù)據(jù)竟纳,線程仍然阻塞在讀寫操作上撵溃,這樣有可能造成資源浪費(fèi),而且給操作系統(tǒng)的線程調(diào)度也帶來壓力锥累。在 NewIO里采用了新的機(jī)制缘挑,編寫的服務(wù)器程序的性能和可擴(kuò)展性都得到提高。 正等待網(wǎng)絡(luò)讀寫桶略,這可能是一個(gè)網(wǎng)絡(luò)瓶頸的征兆语淘。因?yàn)榫W(wǎng)絡(luò)阻塞導(dǎo)致線程無法執(zhí)行。一種情況是網(wǎng)絡(luò)非常忙际歼,幾 乎消耗了所有的帶寬惶翻,仍然有大量數(shù)據(jù)等待網(wǎng)絡(luò)讀 寫;另一種情況也可能是網(wǎng)絡(luò)空閑鹅心,但由于路由等問題吕粗,導(dǎo)致包無法正常的到達(dá)。所以要結(jié)合系統(tǒng)的一些性能觀察工具來綜合分析旭愧,比如 netstat統(tǒng)計(jì)單位時(shí)間的發(fā)送包的數(shù)目溯泣,如果很明顯超過了所在網(wǎng)絡(luò)帶寬的限制 ; 觀察 cpu的利用率,如果系統(tǒng)態(tài)的 CPU時(shí)間榕茧,相對于用戶態(tài)的 CPU時(shí)間比例較高垃沦;如果程序運(yùn)行在 Solaris 10平臺(tái)上,可以用 dtrace工具看系統(tǒng)調(diào)用的情況用押,如果觀察到 read/write的系統(tǒng)調(diào)用的次數(shù)或者運(yùn)行時(shí)間遙遙領(lǐng)先肢簿;這些都指向由于網(wǎng)絡(luò)帶寬所限導(dǎo)致的網(wǎng)絡(luò)瓶頸。(來自http://www.blogjava.net/jzone/articles/303979.html

線程Dump的分析

原則

結(jié)合代碼閱讀的推理。需要線程Dump和源碼的相互推導(dǎo)和印證池充。
造成Bug的根源往往丌會(huì)在調(diào)用棧上直接體現(xiàn),一定格外注意線程當(dāng)前調(diào)用之前的所有調(diào)用桩引。

入手點(diǎn)

進(jìn)入?yún)^(qū)等待

"d&a-3588" daemon waiting for monitor entry [0x000000006e5d5000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()
- waiting to lock <0x0000000602f38e90> (a java.lang.Object)
at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()

線程狀態(tài)BLOCKED,線程動(dòng)作wait on monitor entry,調(diào)用修飾waiting to lock總是一起出現(xiàn)。表示在代碼級別已經(jīng)存在沖突的調(diào)用收夸。必然有問題的代碼,需要盡可能減少其發(fā)生坑匠。

同步塊阻塞

一個(gè)線程鎖住某對象,大量其他線程在該對象上等待。

"blocker" runnable
java.lang.Thread.State: RUNNABLE
at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23)
- locked <0x00000000eb8eff68> (a java.lang.Object)
"blockee-11" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
"blockee-86" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)

持續(xù)運(yùn)行的IO IO操作是可以以RUNNABLE狀態(tài)達(dá)成阻塞卧惜。例如:數(shù)據(jù)庫死鎖厘灼、網(wǎng)絡(luò)讀寫。 格外注意對IO線程的真實(shí)狀態(tài)的分析咽瓷。 一般來說,被捕捉到RUNNABLE的IO調(diào)用,都是有問題的设凹。

以下堆棧顯示: 線程狀態(tài)為RUNNABLE。 調(diào)用棧在SocketInputStream或SocketImpl上,socketRead0等方法茅姜。 調(diào)用棧包含了jdbc相關(guān)的包闪朱。很可能發(fā)生了數(shù)據(jù)庫死鎖

"d&a-614" daemon prio=6 tid=0x0000000022f1f000 nid=0x37c8 runnable
[0x0000000027cbd000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at oracle.net.ns.Packet.receive(Packet.java:240)
at oracle.net.ns.DataPacket.receive(DataPacket.java:92)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:172)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:117)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1034)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:588)

分線程調(diào)度的休眠

  • 正常的線程池等待
"d&a-131" in Object.wait()
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo(WorkingManager.java:322)
- locked <0x0000000313f656f8> (a com.jiuqi.dna.core.impl.WorkingThread)
at com.jiuqi.dna.core.impl.WorkingThread.run(WorkingThread.java:40)
  • 可疑的線程等待
"d&a-121" in Object.wait()
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at com.jiuqi.dna.core.impl.AcquirableAccessor.exclusive()
- locked <0x00000003011678d8> (a com.jiuqi.dna.core.impl.CacheGroup)
at com.jiuqi.dna.core.impl.Transaction.lock()

入手點(diǎn)總結(jié)

wait on monitor entry: 被阻塞的,肯定有問題

runnable : 注意IO線程

in Object.wait(): 注意非線程池等待

使用

想要學(xué)習(xí)一個(gè)命令,先來看看幫助钻洒,使用jstack -help查看幫助:

hollis@hos:~$ jstack -help
Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message
  • -F當(dāng)’jstack [-l] pid’沒有相應(yīng)的時(shí)候強(qiáng)制打印棧信息
  • -l長列表. 打印關(guān)于鎖的附加信息,例如屬于java.util.concurrent的ownable synchronizers列表.
  • -m打印java和native c/c++框架的所有棧信息.
  • -h | -help打印幫助信息
  • pid 需要被打印配置信息的java進(jìn)程id,可以用jps查詢.

首先奋姿,我們分析這么一段程序的線程情況:

/**
 * @author hollis
 */
public class JStackDemo1 {
    public static void main(String[] args) {
        while (true) {
            //Do Nothing
        }
    }
}

先是有jps查看進(jìn)程號:

hollis@hos:~$ jps
29788 JStackDemo1
29834 Jps
22385 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar

然后使用jstack 查看堆棧信息:

hollis@hos:~$ jstack 29788
2015-04-17 23:47:31
...此處省略若干內(nèi)容...
"main" prio=10 tid=0x00007f197800a000 nid=0x7462 runnable [0x00007f197f7e1000]
   java.lang.Thread.State: RUNNABLE
    at javaCommand.JStackDemo1.main(JStackDemo1.java:7)

我們可以從這段堆棧信息中看出什么來呢?我們可以看到素标,當(dāng)前一共有一條用戶級別線程,線程處于runnable狀態(tài)称诗,執(zhí)行到JStackDemo1.java的第七行。 看下面代碼:

/**
 * @author hollis
 */
public class JStackDemo1 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Thread1());
        thread.start();
    }
}
class Thread1 implements Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println(1);
        }
    }
}

線程堆棧信息如下:

"Reference Handler" daemon prio=10 tid=0x00007fbbcc06e000 nid=0x286c in Object.wait() [0x00007fbbc8dfc000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x0000000783e066e0> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:503)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
    - locked <0x0000000783e066e0> (a java.lang.ref.Reference$Lock)

我們能看到:

線程的狀態(tài): WAITING 線程的調(diào)用棧 線程的當(dāng)前鎖住的資源: <0x0000000783e066e0> 線程當(dāng)前等待的資源:<0x0000000783e066e0>

為什么同時(shí)鎖住的等待同一個(gè)資源:

線程的執(zhí)行中糯钙,先獲得了這個(gè)對象的 Monitor(對應(yīng)于 locked <0x0000000783e066e0>)粪狼。當(dāng)執(zhí)行到 obj.wait(), 線程即放棄了 Monitor的所有權(quán),進(jìn)入 “wait set”隊(duì)列(對應(yīng)于 waiting on <0x0000000783e066e0> )任岸。

死鎖分析

學(xué)會(huì)了怎么使用jstack命令之后再榄,我們就可以看看,如何使用jstack分析死鎖了享潜,這也是我們一定要掌握的內(nèi)容困鸥。 啥叫死鎖? 所謂死鎖: 是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中剑按,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象疾就,若無外力作用,它們都將無法推進(jìn)下去艺蝴。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖猬腰,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。 說白了猜敢,我現(xiàn)在想吃雞蛋灌餅姑荷,桌子上放著雞蛋和餅盒延,但是我和我的朋友同時(shí)分別拿起了雞蛋和病,我手里拿著雞蛋鼠冕,但是我需要他手里的餅添寺。他手里拿著餅,但是他想要我手里的雞蛋懈费。就這樣计露,如果不能同時(shí)拿到雞蛋和餅,那我們就不能繼續(xù)做后面的工作(做雞蛋灌餅)憎乙。所以票罐,這就造成了死鎖。 看一段死鎖的程序:

package javaCommand;
/**
 * @author hollis
 */
public class JStackDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(new DeadLockclass(true));//建立一個(gè)線程
        Thread t2 = new Thread(new DeadLockclass(false));//建立另一個(gè)線程
        t1.start();//啟動(dòng)一個(gè)線程
        t2.start();//啟動(dòng)另一個(gè)線程
    }
}
class DeadLockclass implements Runnable {
    public boolean falg;// 控制線程
    DeadLockclass(boolean falg) {
        this.falg = falg;
    }
    public void run() {
        /**
         * 如果falg的值為true則調(diào)用t1線程
         */
        if (falg) {
            while (true) {
                synchronized (Suo.o1) {
                    System.out.println("o1 " + Thread.currentThread().getName());
                    synchronized (Suo.o2) {
                        System.out.println("o2 " + Thread.currentThread().getName());
                    }
                }
            }
        }
        /**
         * 如果falg的值為false則調(diào)用t2線程
         */
        else {
            while (true) {
                synchronized (Suo.o2) {
                    System.out.println("o2 " + Thread.currentThread().getName());
                    synchronized (Suo.o1) {
                        System.out.println("o1 " + Thread.currentThread().getName());
                    }
                }
            }
        }
    }
}

class Suo {
    static Object o1 = new Object();
    static Object o2 = new Object();
}

當(dāng)我啟動(dòng)該程序時(shí)寨闹,我們看一下控制臺(tái):
![image14]

我們發(fā)現(xiàn)胶坠,程序只輸出了兩行內(nèi)容君账,然后程序就不再打印其它的東西了繁堡,但是程序并沒有停止。這樣就產(chǎn)生了死鎖乡数。 當(dāng)線程1使用synchronized鎖住了o1的同時(shí)椭蹄,線程2也是用synchronized鎖住了o2。當(dāng)兩個(gè)線程都執(zhí)行完第一個(gè)打印任務(wù)的時(shí)候净赴,線程1想鎖住o2绳矩,線程2想鎖住o1。但是玖翅,線程1當(dāng)前鎖著o1翼馆,線程2鎖著o2。所以兩個(gè)想成都無法繼續(xù)執(zhí)行下去金度,就造成了死鎖应媚。

然后,我們使用jstack來看一下線程堆棧信息:

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007f0134003ae8 (object 0x00000007d6aa2c98, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007f0134006168 (object 0x00000007d6aa2ca8, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at javaCommand.DeadLockclass.run(JStackDemo.java:40)
    - waiting to lock <0x00000007d6aa2c98> (a java.lang.Object)
    - locked <0x00000007d6aa2ca8> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:745)
"Thread-0":
    at javaCommand.DeadLockclass.run(JStackDemo.java:27)
    - waiting to lock <0x00000007d6aa2ca8> (a java.lang.Object)
    - locked <0x00000007d6aa2c98> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

哈哈猜极,堆棧寫的很明顯中姜,它告訴我們 Found one Java-level deadlock,然后指出造成死鎖的兩個(gè)線程的內(nèi)容跟伏。然后丢胚,又通過 Java stack information for the threads listed above來顯示更詳細(xì)的死鎖的信息。 他說

Thread-1在想要執(zhí)行第40行的時(shí)候受扳,當(dāng)前鎖住了資源<0x00000007d6aa2ca8>,但是他在等待資源<0x00000007d6aa2c98> Thread-0在想要執(zhí)行第27行的時(shí)候携龟,當(dāng)前鎖住了資源<0x00000007d6aa2c98>,但是他在等待資源<0x00000007d6aa2ca8> 由于這兩個(gè)線程都持有資源,并且都需要對方的資源勘高,所以造成了死鎖峡蟋。 原因我們找到了浮定,就可以具體問題具體分析,解決這個(gè)死鎖了层亿。

其他

虛擬機(jī)執(zhí)行Full GC時(shí),會(huì)阻塞所有的用戶線程桦卒。因此,即時(shí)獲取到同步鎖的線程也有可能被阻塞。 在查看線程Dump時(shí),首先查看內(nèi)存使用情況匿又。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末方灾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碌更,更是在濱河造成了極大的恐慌裕偿,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痛单,死亡現(xiàn)場離奇詭異嘿棘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)旭绒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門鸟妙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挥吵,你說我怎么就攤上這事重父。” “怎么了忽匈?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵房午,是天一觀的道長。 經(jīng)常有香客問我丹允,道長郭厌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任雕蔽,我火速辦了婚禮折柠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萎羔。我一直安慰自己液走,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布贾陷。 她就那樣靜靜地躺著缘眶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪髓废。 梳的紋絲不亂的頭發(fā)上巷懈,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機(jī)與錄音慌洪,去河邊找鬼顶燕。 笑死凑保,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涌攻。 我是一名探鬼主播欧引,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼恳谎!你這毒婦竟也來了芝此?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤因痛,失蹤者是張志新(化名)和其女友劉穎婚苹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸵膏,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膊升,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谭企。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廓译。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赞咙,靈堂內(nèi)的尸體忽然破棺而出责循,到底是詐尸還是另有隱情糟港,我是刑警寧澤攀操,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站秸抚,受9級特大地震影響速和,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剥汤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一颠放、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吭敢,春花似錦碰凶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畜晰,卻和暖如春砾莱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凄鼻。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工腊瑟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聚假,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓闰非,卻偏偏與公主長得像膘格,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子财松,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

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