Android性能優(yōu)化:關(guān)于 內(nèi)存泄露 的知識都在這里了!


前言

  • Android中瓤漏,內(nèi)存泄露的現(xiàn)象十分常見腾夯;而內(nèi)存泄露導(dǎo)致的后果會使得應(yīng)用Crash
  • 本文 全面介紹了內(nèi)存泄露的本質(zhì)颊埃、原因 & 解決方案,最終提供一些常見的內(nèi)存泄露分析工具蝶俱,希望你們會喜歡班利。

目錄

示意圖

1. 簡介

  • ML (Memory Leak)
  • 指 程序在申請內(nèi)存后,當(dāng)該內(nèi)存不需再使用 但 卻無法被釋放 & 歸還給 程序的現(xiàn)象

2. 對應(yīng)用程序的影響

  • 容易使得應(yīng)用程序發(fā)生內(nèi)存溢出榨呆,即 OOM

內(nèi)存溢出 簡介:


示意圖

3. 發(fā)生內(nèi)存泄露的本質(zhì)原因

  • 具體描述
示意圖
  • 特別注意
    從機(jī)制上的角度來說罗标,由于 Java存在垃圾回收機(jī)制(GC),理應(yīng)不存在內(nèi)存泄露积蜻;出現(xiàn)內(nèi)存泄露的原因僅僅是外部人為原因 = 無意識地持有對象引用馒稍,使得 持有引用者的生命周期 > 被引用者的生命周期

4. 儲備知識:Android 內(nèi)存管理機(jī)制

4.1 簡介

示意圖

下面,將針對回收 進(jìn)程浅侨、對象 纽谒、變量的內(nèi)存分配 & 回收進(jìn)行詳細(xì)講解

4.2 針對進(jìn)程的內(nèi)存策略

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

ActivityManagerService 集中管理 所有進(jìn)程的內(nèi)存分配

b. 內(nèi)存回收策略

  • 步驟1:Application Framework 決定回收的進(jìn)程類型
    Android中的進(jìn)程 是托管的;當(dāng)進(jìn)程空間緊張時如输,會 按進(jìn)程優(yōu)先級低->>高的順序 自動回收進(jìn)程

Android將進(jìn)程分為5個優(yōu)先等級鼓黔,具體如下:

示意圖
  • 步驟2:Linux 內(nèi)核真正回收具體進(jìn)程
    1. ActivityManagerService 對 所有進(jìn)程進(jìn)行評分(評分存放在變量adj中)
    2. 更新評分到Linux 內(nèi)核
    3. Linux 內(nèi)核完成真正的內(nèi)存回收

此處僅總結(jié)流程,這其中的過程復(fù)雜不见,有興趣的讀者可研究系統(tǒng)源碼ActivityManagerService.java

4.3 針對對象澳化、變量的內(nèi)存策略

  • Android的對于對象、變量的內(nèi)存策略同 Java
  • 內(nèi)存管理 = 對象 / 變量的內(nèi)存分配 + 內(nèi)存釋放

下面稳吮,將詳細(xì)講解內(nèi)存分配 & 內(nèi)存釋放策略

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

  • 對象 / 變量的內(nèi)存分配 由程序自動 負(fù)責(zé)
  • 共有3種:靜態(tài)分配缎谷、棧式分配、 & 堆式分配灶似,分別面向靜態(tài)變量列林、局部變量 & 對象實例
  • 具體介紹如下
示意圖

注:用1個實例講解 內(nèi)存分配

public class Sample {    
    int s1 = 0;
    Sample mSample1 = new Sample();   
    
    // 方法中的局部變量s2、mSample2存放在 棧內(nèi)存
    // 變量mSample2所指向的對象實例存放在 堆內(nèi)存
      // 該實例的成員變量s1酪惭、mSample1也存放在棧中
    public void method() {        
        int s2 = 0;
        Sample mSample2 = new Sample();
    }
}
    // 變量mSample3所指向的對象實例存放在堆內(nèi)存
    // 該實例的成員變量s1希痴、mSample1也存放在堆內(nèi)存中
    Sample mSample3 = new Sample();

b. 內(nèi)存釋放策略

  • 對象 / 變量的內(nèi)存釋放 由Java垃圾回收器(GC) / 幀棧 負(fù)責(zé)
  • 此處主要講解對象分配(即堆式分配)的內(nèi)存釋放策略 = Java垃圾回收器(GC

由于靜態(tài)分配不需釋放、棧式分配僅 通過幀棧自動出春感、入棧砌创,較簡單,故不詳細(xì)描述

  • Java垃圾回收器(GC)的內(nèi)存釋放 = 垃圾回收算法鲫懒,主要包括:
垃圾收集算法類型
  • 具體介紹如下
總結(jié)

5. 常見的內(nèi)存泄露原因 & 解決方案

  • 常見引發(fā)內(nèi)存泄露原因主要有:
  1. 集合類
  2. Static關(guān)鍵字修飾的成員變量
  3. 非靜態(tài)內(nèi)部類 / 匿名類
  4. 資源對象使用后未關(guān)閉
  • 下面嫩实,我將詳細(xì)介紹每個引發(fā)內(nèi)存泄露的原因

5.1 集合類

  • 內(nèi)存泄露原因
    集合類 添加元素后,仍引用著 集合元素對象窥岩,導(dǎo)致該集合元素對象不可被回收甲献,從而 導(dǎo)致內(nèi)存泄漏

  • 實例演示

// 通過 循環(huán)申請Object 對象 & 將申請的對象逐個放入到集合List
List<Object> objectList = new ArrayList<>();        
       for (int i = 0; i < 10; i++) {
            Object o = new Object();
            objectList.add(o);
            o = null;
        }
// 雖釋放了集合元素引用的本身:o=null)
// 但集合List 仍然引用該對象,故垃圾回收器GC 依然不可回收該對象
  • 解決方案
    集合類添加集合元素對象后谦秧,在使用后必須從集合中刪除竟纳。由于一個集合中有許多元素,故最簡單的方法是:清空集合對象和設(shè)置為null疚鲤。
 // 釋放objectList
        objectList.clear();
        objectList=null;

5.2 Static 關(guān)鍵字修飾的成員變量

  • 儲備知識
    Static 關(guān)鍵字修飾的成員變量的生命周期 = 應(yīng)用程序的生命周期

  • 泄露原因
    若使被 Static 關(guān)鍵字修飾的成員變量 引用耗費資源過多的實例(如Context)锥累,則容易出現(xiàn)該成員變量的生命周期 > 引用實例生命周期的情況,當(dāng)引用實例需結(jié)束生命周期銷毀時集歇,會因靜態(tài)變量的持有而無法被回收桶略,從而出現(xiàn)內(nèi)存泄露

  • 實例講解

public class ClassName {
 // 定義1個靜態(tài)變量
 private static Context mContext;
 //...
// 引用的是Activity的context
 mContext = context; 

// 當(dāng)Activity需銷毀時,由于mContext = 靜態(tài) & 生命周期 = 應(yīng)用程序的生命周期诲宇,故 Activity無法被回收际歼,從而出現(xiàn)內(nèi)存泄露

}
  • 解決方案
  1. 盡量避免 Static 成員變量引用資源耗費過多的實例(如 Context

若需引用 Context,則盡量使用ApplicaitonContext

  1. 使用 弱引用(WeakReference) 代替 強(qiáng)引用 持有實例

注:靜態(tài)成員變量有個非常典型的例子 = 單例模式

  • 儲備知識
    單例模式 由于其靜態(tài)特性姑蓝,其生命周期的長度 = 應(yīng)用程序的生命周期

  • 泄露原因
    若1個對象已不需再使用 而單例對象還持有該對象的引用鹅心,那么該對象將不能被正常回收 從而 導(dǎo)致內(nèi)存泄漏

  • 實例演示

// 創(chuàng)建單例時纺荧,需傳入一個Context
// 若傳入的是Activity的Context旭愧,此時單例 則持有該Activity的引用
// 由于單例一直持有該Activity的引用(直到整個應(yīng)用生命周期結(jié)束),即使該Activity退出宙暇,該Activity的內(nèi)存也不會被回收
// 特別是一些龐大的Activity输枯,此處非常容易導(dǎo)致OOM

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context; // 傳遞的是Activity的context
    }  
  
    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}
  • 解決方案
    單例模式應(yīng)該引用生命周期等于應(yīng)用生命周期的對象。

如上述實例占贫,應(yīng)傳遞ApplicationContext桃熄,因Application的生命周期 = 整個應(yīng)用的生命周期

public class SingleInstanceClass {    
    private static SingleInstanceClass instance;    
    private Context mContext;    
    private SingleInstanceClass(Context context) {        
        this.mContext = context.getApplicationContext(); // 傳遞的是Application 的context
    }    

    public SingleInstanceClass getInstance(Context context) {        
        if (instance == null) {
            instance = new SingleInstanceClass(context);
        }        
        return instance;
    }
}

5.3 非靜態(tài)內(nèi)部類 / 匿名類

  • 儲備知識
    非靜態(tài)內(nèi)部類 / 匿名類 默認(rèn)持有 外部類的引用;而靜態(tài)內(nèi)部類則不會
  • 常見情況
    3種型奥,分別是:非靜態(tài)內(nèi)部類的實例 = 靜態(tài)瞳收、多線程、消息傳遞機(jī)制(Handler

5.3.1 非靜態(tài)內(nèi)部類的實例 = 靜態(tài)

  • 泄露原因
    若 非靜態(tài)內(nèi)部類所創(chuàng)建的實例 = 靜態(tài)(其生命周期 = 應(yīng)用的生命周期)厢汹,會因 非靜態(tài)內(nèi)部類默認(rèn)持有外部類的引用 而導(dǎo)致外部類無法釋放缎讼,最終 造成內(nèi)存泄露

即 外部類中 持有 非靜態(tài)內(nèi)部類的靜態(tài)對象

  • 實例演示
// 背景:
// a. 在啟動頻繁的Activity中,為了避免重復(fù)創(chuàng)建相同的數(shù)據(jù)資源坑匠,會在Activity內(nèi)部創(chuàng)建一個非靜態(tài)內(nèi)部類的單例
// b. 每次啟動Activity時都會使用該單例的數(shù)據(jù)

public class TestActivity extends AppCompatActivity {  
    
    // 非靜態(tài)內(nèi)部類的實例的引用
    // 注:設(shè)置為靜態(tài)  
    public static InnerClass innerClass = null; 
   
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);   

        // 保證非靜態(tài)內(nèi)部類的實例只有1個
        if (innerClass == null)
            innerClass = new InnerClass();
    }

    // 非靜態(tài)內(nèi)部類的定義    
    private class InnerClass {        
        //...
    }
}

// 造成內(nèi)存泄露的原因:
// a. 當(dāng)TestActivity銷毀時血崭,因非靜態(tài)內(nèi)部類單例的引用(innerClass)的生命周期 = 應(yīng)用App的生命周期、持有外部類TestActivity的引用
// b. 故 TestActivity無法被GC回收厘灼,從而導(dǎo)致內(nèi)存泄漏
  • 解決方案
    1. 將非靜態(tài)內(nèi)部類設(shè)置為:靜態(tài)內(nèi)部類(靜態(tài)內(nèi)部類默認(rèn)不持有外部類的引用)
    2. 該內(nèi)部類抽取出來封裝成一個單例
    3. 盡量 避免 非靜態(tài)內(nèi)部類所創(chuàng)建的實例 = 靜態(tài)

若需使用Context夹纫,建議使用 ApplicationContext

5.3.2 多線程:AsyncTask、實現(xiàn)Runnable接口设凹、繼承Thread類

  • 儲備知識
    多線程的使用方法 = 非靜態(tài)內(nèi)部類 / 匿名類舰讹;即 線程類 屬于 非靜態(tài)內(nèi)部類 / 匿名類
  • 泄露原因
    當(dāng) 工作線程正在處理任務(wù)而外部類需銷毀時, 由于 工作線程實例 持有外部類引用闪朱,將使得外部類無法被垃圾回收器(GC)回收月匣,從而造成 內(nèi)存泄露
  1. 多線程主要使用的是:AsyncTask钻洒、實現(xiàn)Runnable接口 & 繼承Thread
  2. 前3者內(nèi)存泄露的原理相同,此處主要以繼承Thread類 為例說明
  • 實例演示
  /** 
   * 方式1:新建Thread子類(內(nèi)部類)
   */  
    public class MainActivity extends AppCompatActivity {

    public static final String TAG = "carson:";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 通過創(chuàng)建的內(nèi)部類 實現(xiàn)多線程
        new MyThread().start();

    }
    // 自定義的Thread子類
    private class MyThread extends Thread{
        @Override
        public void run() {
            try {
                Thread.sleep(5000);
                Log.d(TAG, "執(zhí)行了多線程");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 /** 
   * 方式2:匿名Thread內(nèi)部類
   */ 
    public class MainActivity extends AppCompatActivity {

    public static final String TAG = "carson:";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 通過匿名內(nèi)部類 實現(xiàn)多線程
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    Log.d(TAG, "執(zhí)行了多線程");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}


/** 
* 分析:內(nèi)存泄露原因
*/ 
// 工作線程Thread類屬于非靜態(tài)內(nèi)部類 / 匿名內(nèi)部類锄开,運(yùn)行時默認(rèn)持有外部類的引用
// 當(dāng)工作線程運(yùn)行時素标,若外部類MainActivity需銷毀
// 由于此時工作線程類實例持有外部類的引用,將使得外部類無法被垃圾回收器(GC)回收萍悴,從而造成 內(nèi)存泄露
  • 解決方案
    從上面可看出头遭,造成內(nèi)存泄露的原因有2個關(guān)鍵條件:
  1. 存在 ”工作線程實例 持有外部類引用“ 的引用關(guān)系
  2. 工作線程實例的生命周期 > 外部類的生命周期,即工作線程仍在運(yùn)行 而 外部類需銷毀

解決方案的思路 = 使得上述任1條件不成立 即可癣诱。對應(yīng)打破上述條件的解決方案如下:

/** 
 * 解決方式1:靜態(tài)內(nèi)部類
 * 原理:靜態(tài)內(nèi)部類 不默認(rèn)持有外部類的引用计维,從而使得 “工作線程實例 持有 外部類引用” 的引用關(guān)系 不復(fù)存在
 * 具體實現(xiàn):將Thread的子類設(shè)置成 靜態(tài)內(nèi)部類
 */  
  public class MainActivity extends AppCompatActivity {

  public static final String TAG = "carson:";
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      // 通過創(chuàng)建的內(nèi)部類 實現(xiàn)多線程
      new MyThread().start();

  }
  // 分析1:自定義Thread子類
  // 設(shè)置為:靜態(tài)內(nèi)部類
  private static class MyThread extends Thread{
      @Override
      public void run() {
          try {
              Thread.sleep(5000);
              Log.d(TAG, "執(zhí)行了多線程");
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  }
}

/** 
 * 解決方案2:當(dāng)外部類結(jié)束生命周期時,強(qiáng)制結(jié)束線程
 * 原理:使得 工作線程實例的生命周期 與 外部類的生命周期 同步
 * 具體實現(xiàn):當(dāng) 外部類(此處以Activity為例) 結(jié)束生命周期時(此時系統(tǒng)會調(diào)用onDestroy())撕予,強(qiáng)制結(jié)束線程(調(diào)用stop())
 */ 
 @Override
  protected void onDestroy() {
      super.onDestroy();
      Thread.stop();
      // 外部類Activity生命周期結(jié)束時鲫惶,強(qiáng)制結(jié)束線程
  }

5.3.3 消息傳遞機(jī)制:Handler

具體請看文章:Android 內(nèi)存泄露:詳解 Handler 內(nèi)存泄露的原因

5.4 資源對象使用后未關(guān)閉

  • 泄露原因
    對于資源的使用(如 廣播BraodcastReceiver、文件流File实抡、數(shù)據(jù)庫游標(biāo)Cursor剑按、圖片資源Bitmap等),若在Activity銷毀時無及時關(guān)閉 / 注銷這些資源澜术,則這些資源將不會被回收艺蝴,從而造成內(nèi)存泄漏

  • 解決方案
    Activity銷毀時 及時關(guān)閉 / 注銷資源

// 對于 廣播BraodcastReceiver:注銷注冊
unregisterReceiver()

// 對于 文件流File:關(guān)閉流
InputStream / OutputStream.close()

// 對于數(shù)據(jù)庫游標(biāo)cursor:使用后關(guān)閉游標(biāo)
cursor.close()

// 對于 圖片資源Bitmap:Android分配給圖片的內(nèi)存只有8M,若1個Bitmap對象占內(nèi)存較多鸟废,當(dāng)它不再被使用時猜敢,應(yīng)調(diào)用recycle()回收此對象的像素所占用的內(nèi)存;最后再賦為null 
Bitmap.recycle()盒延;
Bitmap = null;

// 對于動畫(屬性動畫)
// 將動畫設(shè)置成無限循環(huán)播放repeatCount = “infinite”后
// 在Activity退出時記得停止動畫

5.5 其他使用

  • 除了上述4種常見情況缩擂,還有一些日常的使用會導(dǎo)致內(nèi)存泄露
  • 主要包括:ContextWebView添寺、Adapter胯盯,具體介紹如下
示意圖

5.6 總結(jié)

下面,我將用一張圖總結(jié)Android中內(nèi)存泄露的原因 & 解決方案

示意圖

6. 輔助分析內(nèi)存泄露的工具

  • 哪怕完全了解 內(nèi)存泄露的原因计露,但難免還是會出現(xiàn)內(nèi)存泄露的現(xiàn)象
  • 下面將簡單介紹幾個主流的分析內(nèi)存泄露的工具博脑,分別是
    1. MAT(Memory Analysis Tools)
    2. Heap Viewer
    3. Allocation Tracker
    4. Android Studio 的 Memory Monitor
    5. LeakCanary

6.1 MAT(Memory Analysis Tools)

  • 定義:一個EclipseJava Heap 內(nèi)存分析工具 ->>下載地址
  • 作用:查看當(dāng)前內(nèi)存占用情況

通過分析 Java 進(jìn)程的內(nèi)存快照 HPROF 分析,快速計算出在內(nèi)存中對象占用的大小票罐,查看哪些對象不能被垃圾收集器回收 & 可通過視圖直觀地查看可能造成這種結(jié)果的對象

6.2 Heap Viewer

  • 定義:一個的 Java Heap 內(nèi)存分析工具
  • 作用:查看當(dāng)前內(nèi)存快照

可查看 分別有哪些類型的數(shù)據(jù)在堆內(nèi)存總 & 各種類型數(shù)據(jù)的占比情況

6.3 Allocation Tracker

  • 簡介:一個內(nèi)存追蹤分析工具
  • 作用:追蹤內(nèi)存分配信息叉趣,按順序排列
  • 具體使用:Allocation Tracker使用攻略

6.4 Memory Monitor

  • 簡介:一個 Android Studio 自帶 的圖形化檢測內(nèi)存工具

  • 作用:跟蹤系統(tǒng) / 應(yīng)用的內(nèi)存使用情況。核心功能如下


    示意圖
  • 具體使用:Android Studio 的 Memory Monitor使用攻略

6.5 LeakCanary


7. 總結(jié)

  • 本文 全面介紹了內(nèi)存泄露的本質(zhì)该押、原因 & 解決方案疗杉,希望大家在開發(fā)時盡量避免出現(xiàn)內(nèi)存泄露

  • 下一篇文章我將對講解Android 性能優(yōu)化的相關(guān)知識,感興趣的同學(xué)可以繼續(xù)關(guān)注


請點贊蚕礼!因為你的鼓勵是我寫作的最大動力烟具!

相關(guān)文章閱讀
Android開發(fā):最全面梢什、最易懂的Android屏幕適配解決方案
Android事件分發(fā)機(jī)制詳解:史上最全面、最易懂
Android開發(fā):史上最全的Android消息推送解決方案
Android開發(fā):最全面朝聋、最易懂的Webview詳解
Android開發(fā):JSON簡介及最全面解析方法!
Android四大組件:Service服務(wù)史上最全面解析
Android四大組件:BroadcastReceiver史上最全面解析


歡迎關(guān)注Carson_Ho的簡書嗡午!

不定期分享關(guān)于安卓開發(fā)的干貨,追求短玖翅、平翼馆、快割以,但卻不缺深度金度。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市严沥,隨后出現(xiàn)的幾起案子猜极,更是在濱河造成了極大的恐慌,老刑警劉巖消玄,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跟伏,死亡現(xiàn)場離奇詭異,居然都是意外死亡翩瓜,警方通過查閱死者的電腦和手機(jī)受扳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兔跌,“玉大人勘高,你說我怎么就攤上這事》匚Γ” “怎么了华望?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長仅乓。 經(jīng)常有香客問我赖舟,道長,這世上最難降的妖魔是什么夸楣? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任宾抓,我火速辦了婚禮,結(jié)果婚禮上豫喧,老公的妹妹穿的比我還像新娘洞慎。我一直安慰自己,他們只是感情好嘿棘,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布劲腿。 她就那樣靜靜地躺著甘凭,像睡著了一般弃鸦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天载碌,我揣著相機(jī)與錄音,去河邊找鬼莹痢。 笑死疲陕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矿辽。 我是一名探鬼主播丹允,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼袋倔!你這毒婦竟也來了雕蔽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤宾娜,失蹤者是張志新(化名)和其女友劉穎批狐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體前塔,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡嚣艇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了华弓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片食零。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖寂屏,靈堂內(nèi)的尸體忽然破棺而出贰谣,到底是詐尸還是另有隱情,我是刑警寧澤凑保,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布冈爹,位于F島的核電站,受9級特大地震影響欧引,放射性物質(zhì)發(fā)生泄漏频伤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一芝此、第九天 我趴在偏房一處隱蔽的房頂上張望憋肖。 院中可真熱鬧,春花似錦婚苹、人聲如沸岸更。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怎炊。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間评肆,已是汗流浹背债查。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瓜挽,地道東北人盹廷。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像久橙,于是被迫代替她去往敵國和親俄占。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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