java性能調(diào)優(yōu)工具

1麦轰、JDK命令行工具

1.1淑倾、jps命令

jps用于列出Java的進程卫玖,jps可以增加參數(shù),-m用于輸出傳遞給Java進程的參數(shù)踊淳,-l用于輸出主函數(shù)的完整路徑假瞬,-v可以用于顯示傳遞給jvm的參數(shù)。

jps -l -m -v
31427 sun.tools.jps.Jps -l -m -v -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home -Xms8m

1.2迂尝、jstat命令

jstat是一個可以用于觀察Java應(yīng)用程序運行時信息的工具脱茉,它的功能非常強大,可以通過它查看堆信息的詳細情況垄开,它的基本使用方法為:

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] 

選項option可以由以下值組成:

jstat -class pid:顯示加載class的數(shù)量琴许,及所占空間等信息。  

jstat -compiler pid:顯示VM實時編譯的數(shù)量等信息溉躲。

jstat -gc pid:可以顯示gc的信息榜田,查看gc的次數(shù),及時間锻梳。其中最后五項箭券,分別是young gc的次數(shù),young gc的時間疑枯,full gc的次數(shù)辩块,full gc的時間,gc的總時間荆永。

jstat -gccapacity:可以顯示废亭,VM內(nèi)存中三代(young,old,perm)對象的使用和占用大小,如:PGCMN顯示的是最小perm的內(nèi)存使用量具钥,PGCMX顯示的是perm的內(nèi)存最大使用量豆村,PGC是當前新生成的perm內(nèi)存占用量,PC是但前perm內(nèi)存占用量骂删。其他的可以根據(jù)這個類推掌动, OC是old內(nèi)純的占用量。

jstat -gcnew pid:new對象的信息桃漾。

jstat -gcnewcapacity pid:new對象的信息及其占用量坏匪。

jstat -gcold pid:old對象的信息拟逮。

jstat -gcoldcapacity pid:old對象的信息及其占用量撬统。

jstat -gcpermcapacity pid: perm對象的信息及其占用量。

jstat -gcutil pid:統(tǒng)計gc信息統(tǒng)計敦迄。

jstat -printcompilation pid:當前VM執(zhí)行的信息恋追。

除了以上一個參數(shù)外凭迹,還可以同時加上 兩個數(shù)字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次苦囱,一共打印6次嗅绸。

這些參數(shù)中最常用的參數(shù)是gcutil,下面是該參數(shù)的輸出介紹以及一個簡單例子:

S0  — Heap上的 Survivor space 0 區(qū)已使用空間的百分比  

S1 — Heap上的 Survivor space 1 區(qū)已使用空間的百分比

E — Heap上的 Eden space 區(qū)已使用空間的百分比

O — Heap上的 Old space 區(qū)已使用空間的百分比

P — Perm space 區(qū)已使用空間的百分比

YGC — 從應(yīng)用程序啟動到采樣時發(fā)生 Young GC 的次數(shù)

YGCT– 從應(yīng)用程序啟動到采樣時 Young GC 所用的時間(單位秒)

FGC — 從應(yīng)用程序啟動到采樣時發(fā)生 Full GC 的次數(shù)

FGCT– 從應(yīng)用程序啟動到采樣時 Full GC 所用的時間(單位秒)

GCT — 從應(yīng)用程序啟動到采樣時用于垃圾回收的總時間(單位秒)

實例使用1:

[root@localhost bin]# jstat -gcutil 25444

S0 S1 E O P YGC YGCT FGC FGCT GCT

11.63 0.00 56.46 66.92 98.49 162 0.248 6 0.331 0.579

1.3撕彤、jinfo命令

jinfo可以用來查看正在運行的Java應(yīng)用程序的擴展參數(shù)鱼鸠,甚至在運行時修改部分參數(shù),它的基本語法為:

jinfo <option> <pid>

jinfo可以查看運行時參數(shù):

jinfo -flag MaxTenuringThreshold 31518
-XX:MaxTenuringThreshold=15

jinfo還可以在運行時修改參數(shù)值:

> jinfo -flag PrintGCDetails 31518
-XX:-PrintGCDetails

> jinfo -flag +PrintGCDetails 31518

> jinfo -flag PrintGCDetails 31518

-XX:+PrintGCDetails

1.4羹铅、jmap命令

jmap命令主要用于生成堆快照文件蚀狰,它的使用方法如下:

> jmap -dump:format=b,file=heap.hprof 31531
Dumping heap to /Users/caojie/heap.hprof ...

Heap dump file created

獲得堆快照文件之后,我們可以使用多種工具對文件進行分析职员,例如jhat麻蹋,visual vm等。

1.5焊切、jhat命令

使用jhat工具可以分析Java應(yīng)用程序的堆快照文件扮授,使用命令如下:

> jhat heap.hprof 
Reading from heap.hprof...

Dump file created Tue Nov 11 06:02:05 CST 2014

Snapshot read, resolving...

Resolving 8781 objects...

Chasing references, expect 1 dots.

Eliminating duplicate references.

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.

jhat在分析完成之后,使用HTTP服務(wù)器展示其分析結(jié)果专肪,在瀏覽器中訪問http://127.0.0.1:7000/即可得到分析結(jié)果刹勃。

1.6、jstack命令

jstack可用于導出Java應(yīng)用程序的線程堆棧信息嚎尤,語法為:

jstack -l <pid>

jstack可以檢測死鎖深夯,下例通過一個簡單例子演示jstack檢測死鎖的功能。java代碼如下:

package com.huihui.test;

import java.util.concurrent.locks.ReentrantLock;

public class DeadLock extends Thread {
    protected Object myDirect;
    static ReentrantLock south = new ReentrantLock();
    static ReentrantLock north = new ReentrantLock();

    public DeadLock(Object obj) {
        this.myDirect = obj;
        if (myDirect == south) {
            this.setName("south");
        }
        if (myDirect == north) {
            this.setName("north");
        }
    }

    @Override
    public void run() {
        if (myDirect == south) {
            try {
                north.lockInterruptibly();
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                south.lockInterruptibly();
                System.out.println("car to south has passed");
            } catch (InterruptedException e1) {
                System.out.println("car to south is killed");
            } finally {
                if (north.isHeldByCurrentThread())
                    north.unlock();
                if (south.isHeldByCurrentThread())
                    south.unlock();
            }
        }

        if (myDirect == north) {
            try {
                south.lockInterruptibly();
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                north.lockInterruptibly();
                System.out.println("car to north has passed");
            } catch (InterruptedException e1) {
                System.out.println("car to north is killed");
            } finally {
                if (north.isHeldByCurrentThread())
                    north.unlock();
                if (south.isHeldByCurrentThread())
                    south.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        DeadLock car2south = new DeadLock(south);
        DeadLock car2north = new DeadLock(north);
        car2south.start();
        car2north.start();
        Thread.sleep(1000);
    }

}

使用jps命令查看進程號為32627诺苹,然后使用jstack -l 32637 > a.txt命令把堆棧信息打印到文件中咕晋,該文件內(nèi)容如下:

2016-09-18 22:26:12
Full thread dump Java HotSpot(TM) Client VM (25.101-b13 mixed mode, sharing):

"DestroyJavaVM" #10 prio=5 os_prio=0 tid=0x156e6800 nid=0x2648 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None


"north" #9 prio=5 os_prio=0 tid=0x156e8800 nid=0x21cc waiting on condition [0x15a5f000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x04aad4b0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at
    java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.huihui.test.DeadLock.run(DeadLock.java:50)

   Locked ownable synchronizers:
    - <0x04aad488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"south" #8 prio=5 os_prio=0 tid=0x156e8000 nid=0x19e4 waiting on condition [0x159cf000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x04aad488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.huihui.test.DeadLock.run(DeadLock.java:30)

   Locked ownable synchronizers:
    - <0x04aad4b0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00f49400 nid=0xfe8 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C1 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x00f3f000 nid=0x1314 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00f3d400 nid=0x2d94 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00f2c800 nid=0x2d20 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00f23c00 nid=0xd3c in Object.wait() [0x0497f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x04a08980> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x04a08980> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

   Locked ownable synchronizers:
    - None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00ec6c00 nid=0x3a00 in Object.wait() [0x048ef000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x04a06a70> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x04a06a70> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
    - None

"VM Thread" os_prio=2 tid=0x00ec2800 nid=0x2414 runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x156e0400 nid=0x28d4 waiting on condition 

JNI global references: 6


Found one Java-level deadlock:
=============================
"north":
  waiting for ownable synchronizer 0x04aad4b0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "south"
"south":
  waiting for ownable synchronizer 0x04aad488, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "north"

Java stack information for the threads listed above:
===================================================
"north":
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x04aad4b0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.huihui.test.DeadLock.run(DeadLock.java:50)
"south":
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x04aad488> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.huihui.test.DeadLock.run(DeadLock.java:30)

Found 1 deadlock.

從這個輸出可以知道:

1、在輸出的最后一段收奔,有明確的"Found one Java-level deadlock"輸出掌呜,所以通過jstack命令我們可以檢測死鎖;
2坪哄、輸出中包含了所有線程质蕉,除了我們的north,sorth線程外,還有"Attach Listener", "C2 CompilerThread0", "C2 CompilerThread1"等等翩肌;
3模暗、每個線程下面都會輸出當前狀態(tài),以及這個線程當前持有鎖以及等待鎖念祭,當持有與等待造成循環(huán)等待時兑宇,將導致死鎖。

1.7粱坤、jstatd命令

jstatd命令是一個RMI服務(wù)器程序隶糕,它的作用相當于代理服務(wù)器瓷产,建立本地計算機與遠程監(jiān)控工具的通信,jstatd服務(wù)器能夠?qū)⒈緳C的Java應(yīng)用程序信息傳遞到遠程計算機枚驻,由于需要多臺計算機做演示濒旦,此處略。

1.8再登、hprof工具

hprof工具可以用于監(jiān)控Java應(yīng)用程序在運行時的CPU信息和堆信息尔邓,關(guān)于hprof的官方文檔如下:https://docs.oracle.com/javase/7/docs/technotes/samples/hprof.html

2、Visual VM工具

Visual VM是一個功能強大的多合一故障診斷和性能監(jiān)控的可視化工具锉矢,它集成了多種性能統(tǒng)計工具的功能铃拇,使用Visual VM可以替代jstat、jmap沈撞、jhat慷荔、jstack等工具。在命令行輸入jvisualvm即可啟動visualvm缠俺。
打開Visual VM之后显晶,左邊導航欄會顯示出當前機器所有Java進程:

點擊你想監(jiān)控的程序即可對該程序進行監(jiān)控,Visual VM的性能監(jiān)控頁一共有以下幾個tab頁:

概述頁會顯示程序的基本使用情況壹士,比如磷雇,進程ID,系統(tǒng)屬性躏救,啟動參數(shù)等唯笙。

通過監(jiān)視頁面,可以監(jiān)視應(yīng)用程序的CPU盒使、堆崩掘、永久區(qū)、類加載器和線程數(shù)的整體情況少办,通過頁面上的Perform GC和Heap Dump按鈕還可以手動執(zhí)行Full GC和生成堆快照苞慢。

線程頁面會提供詳細的線程信息,單擊Thread Dump按鈕可以導出當前所有線程的堆棧信息英妓,如果Visual VM在當前線程中找到死鎖挽放,則會以十分顯眼的方式在Threads頁面給予提示。

抽樣器可以對CPU和內(nèi)存兩個性能進行抽樣蔓纠,用于實時地監(jiān)控程序辑畦。CPU采樣器可以將CPU占用時間定位到方法,內(nèi)存采樣器可以查看當前程序的堆信息腿倚。下面是一個頻繁調(diào)用的Java程序纯出,我們會對改程序進行采樣:

package com.huihui.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MethodTime {
    static java.util.Random r = new java.util.Random();
    static Map<String, String> map = null;
    static {
        map = new HashMap<String, String>();
        map.put("1", "Java");
        map.put("2", "C++");
        map.put("3", "Delphi");
        map.put("4", "C");
        map.put("5", "Phython");
    }

    public String getNameById(String id) {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return map.get(id);
    }

    public List<String> getNamesByIds(String ids) {
        List<String> re = new ArrayList<String>();
        String[] strs = ids.split(",");
        for (String id : strs) {
            re.add(getNameById(id));
        }
        return re;
    }

    public List<String> getNamesByIdsBad(String ids) {
        List<String> re = new ArrayList<String>();
        String[] strs = ids.split(",");
        for (String id : strs) {
            // A bad code
            getNameById(id);
            re.add(getNameById(id));
        }
        return re;
    }

    public class NamesByIdsThread implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    int c = r.nextInt(4);
                    String ids = "";
                    for (int i = 0; i < c; i++)
                        ids = Integer.toString((r.nextInt(4) + 1)) + ",";
                    getNamesByIds(ids);
                }
            } catch (Exception e) {
            }
        }
    }

    public class NamesByIdsBadThread implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    int c = r.nextInt(4);
                    String ids = "";
                    for (int i = 0; i < c; i++)
                        ids = Integer.toString((r.nextInt(4) + 1)) + ",";
                    getNamesByIdsBad(ids);
                }
            } catch (Exception e) {
            }
        }
    }

    public static void main(String args[]) {
        MethodTime instance = new MethodTime();
        new Thread(instance.new NamesByIdsThread()).start();
        new Thread(instance.new NamesByIdsBadThread()).start();
    }
}

通過Visual VM的采樣功能,可以找到改程序中占用CPU時間最長的方法:

默認Visual VM不統(tǒng)計內(nèi)置對象的函數(shù)調(diào)用,比如java.*包中的類潦刃,如果要統(tǒng)計這些內(nèi)置對象,單機右上角的設(shè)置進行調(diào)配懈叹。Visual VM雖然可以統(tǒng)計方法的調(diào)用時間乖杠,但是無法給出方法調(diào)用堆棧,Jprofile不僅可以給出方法調(diào)用時間澄成,還可以給出方法調(diào)用堆棧胧洒,較Visual VM更強大。

右擊左導航的應(yīng)用程序墨状,會出現(xiàn)以下菜單:

單機應(yīng)用程序快照卫漫,可以分析當前應(yīng)用程序的快照,單擊堆Dump能夠?qū)Ξ斍暗亩研畔⑦M行分析肾砂。Visual VM的更多使用方法列赎,可以查看Oracle的官方文檔https://docs.oracle.com/javase/7/docs/technotes/guides/visualvm/index.html

BTrace插件

BTrace是一款功能強大的性能檢測工具,它可以在不停機的情況下镐确,通過字節(jié)碼注入包吝,動態(tài)監(jiān)控系統(tǒng)的運行情況,它可以跟蹤指定的方法調(diào)用源葫、構(gòu)造函數(shù)調(diào)用和系統(tǒng)內(nèi)存等信息诗越,本部分打算舉一個例子,講解一下BTrace的使用息堂。要在Visual VM中使用Btrace嚷狞,首先需要安裝Btrace插件,點擊工具->插件即可在線安裝荣堰,安裝后右鍵應(yīng)用程序床未,就會出現(xiàn)如下選項:

點擊Trace application,即可進入BTrace插件界面振坚。使用BTrace可以監(jiān)控指定函數(shù)的耗時即硼,以下腳本通過正則表達式,監(jiān)控所有類的getNameById方法:

package com.huihui.test;

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class TracingScript {
    @TLS
    private static long startTime = 0;

    @OnMethod(clazz = "/.+/", method = "/getNameById/") // 監(jiān)控任意類的getNameById方法

    public static void startMethod() {
        startTime = timeMillis();
    }

    @OnMethod(clazz = "/.+/", method = "/getNameById/", location = @Location(Kind.RETURN)) // 方法返回時觸發(fā)

    public static void endMethod() {
        print(strcat(strcat(name(probeClass()), "."), probeMethod()));
        print(" [");
        print(strcat("Time taken : ", str(timeMillis() - startTime)));
        println("]");
    }
}

點擊運行屡拨,部分輸出如下:

MethodTime.getNameById [Time taken : 5]
MethodTime.getNameById [Time taken : 4]
MethodTime.getNameById [Time taken : 7]
MethodTime.getNameById [Time taken : 7]

BTrace除了可以監(jiān)控函數(shù)耗時外只酥,還可以指定程序運行到某一行代碼觸發(fā)某一行為,定時觸發(fā)行為呀狼,監(jiān)控函數(shù)參數(shù)等等裂允。

3、MAT內(nèi)存分析工具

MAT是一款功能強大的Java堆內(nèi)存分析器哥艇,可以用于查找內(nèi)存泄露以及查看內(nèi)存消耗情況绝编,MAT的官方文檔如下:http://help.eclipse.org/luna/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html
在MAT中有淺堆和深堆的概念,淺堆是指一個對象結(jié)構(gòu)所占用的內(nèi)存大小十饥,深堆是指一個對象被GC回收后可以真正釋放的內(nèi)存大小窟勃。
通過MAT,可以列出所有垃圾回收的根對象逗堵,Java系統(tǒng)的根對象可能是以下類:系統(tǒng)類秉氧,線程,Java局部變量蜒秤,本地棧等等汁咏。在MAT中還可以很清楚的看到根對象到當前對象的引用關(guān)系鏈。
MAT還可以自動檢測內(nèi)存泄露作媚,單擊菜單上的Leak Suspects命令攘滩,MAT會自動生成一份報告,這份報告羅列了系統(tǒng)內(nèi)可能存在內(nèi)存泄露的問題點纸泡。
在MAT中漂问,還可以自動查找并顯示消耗內(nèi)存最多的幾個對象,這些消耗大量內(nèi)存的大對象往往是解決系統(tǒng)性能問題的關(guān)鍵所在女揭。
具體例子级解,略,網(wǎng)速太慢田绑,至今還未下好勤哗。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掩驱,一起剝皮案震驚了整個濱河市芒划,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欧穴,老刑警劉巖民逼,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涮帘,居然都是意外死亡拼苍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門调缨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疮鲫,“玉大人,你說我怎么就攤上這事弦叶】》福” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵伤哺,是天一觀的道長燕侠。 經(jīng)常有香客問我者祖,道長,這世上最難降的妖魔是什么绢彤? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任七问,我火速辦了婚禮,結(jié)果婚禮上茫舶,老公的妹妹穿的比我還像新娘械巡。我一直安慰自己,他們只是感情好奇适,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布坟比。 她就那樣靜靜地躺著芦鳍,像睡著了一般嚷往。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柠衅,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天皮仁,我揣著相機與錄音,去河邊找鬼菲宴。 笑死贷祈,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的喝峦。 我是一名探鬼主播势誊,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谣蠢!你這毒婦竟也來了粟耻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤眉踱,失蹤者是張志新(化名)和其女友劉穎挤忙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谈喳,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡册烈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了婿禽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赏僧。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扭倾,靈堂內(nèi)的尸體忽然破棺而出次哈,到底是詐尸還是另有隱情,我是刑警寧澤吆录,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布窑滞,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏哀卫。R本人自食惡果不足惜巨坊,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望此改。 院中可真熱鬧趾撵,春花似錦、人聲如沸共啃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽移剪。三九已至究珊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纵苛,已是汗流浹背剿涮。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留攻人,地道東北人取试。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像怀吻,于是被迫代替她去往敵國和親瞬浓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

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