性能優(yōu)化工具(十三)-使用 Memory Profiler 查看 Java 堆和內(nèi)存分配

Memory Profiler 是 Android Profiler 中的一個組件,可幫助您識別導致應(yīng)用卡頓它抱、凍結(jié)甚至崩潰的內(nèi)存泄漏和流失。 它顯示一個應(yīng)用內(nèi)存使用量的實時圖表,讓您可以捕獲堆轉(zhuǎn)儲跨跨、強制執(zhí)行垃圾回收以及跟蹤內(nèi)存分配悼做。

一疯特、 為什么應(yīng)分析您的應(yīng)用內(nèi)存

Android 提供一個托管內(nèi)存環(huán)境—當它確定您的應(yīng)用不再使用某些對象時,垃圾回收器會將未使用的內(nèi)存釋放回堆中肛走。 雖然 Android 查找未使用內(nèi)存的方式在不斷改進漓雅,但對于所有 Android 版本,系統(tǒng)都必須在某個時間點短暫地暫停您的代碼朽色。 大多數(shù)情況下邻吞,這些暫停難以察覺。 不過葫男,如果您的應(yīng)用分配內(nèi)存的速度比系統(tǒng)回收內(nèi)存的速度快抱冷,則當收集器釋放足夠的內(nèi)存以滿足您的分配需要時,您的應(yīng)用可能會延遲梢褐。 此延遲可能會導致您的應(yīng)用跳幀旺遮,并使系統(tǒng)明顯變慢赵讯。

盡管您的應(yīng)用不會表現(xiàn)出變慢,但如果存在內(nèi)存泄漏耿眉,則即使應(yīng)用在后臺運行也會保留該內(nèi)存边翼。 此行為會強制執(zhí)行不必要的垃圾回收 Event,因而拖慢系統(tǒng)的內(nèi)存性能鸣剪。 最后组底,系統(tǒng)被迫終止您的應(yīng)用進程以回收內(nèi)存。 然后筐骇,當用戶返回您的應(yīng)用時债鸡,它必須完全重啟。

為幫助防止這些問題铛纬,您應(yīng)使用 Memory Profiler 執(zhí)行以下操作:

  • 在時間線中查找可能會導致性能問題的不理想的內(nèi)存分配模式厌均。
  • 轉(zhuǎn)儲 Java 堆以查看在任何給定時間哪些對象耗盡了使用內(nèi)存。 長時間進行多個堆轉(zhuǎn)儲可幫助識別內(nèi)存泄漏饺鹃。
  • 記錄正常用戶交互和極端用戶交互期間的內(nèi)存分配以準確識別您的代碼在何處短時間分配了過多對象莫秆,或分配了泄漏的對象。

如需了解可減少應(yīng)用內(nèi)存使用的編程做法悔详,請閱讀管理您的應(yīng)用內(nèi)存镊屎。

二、 Memory Profiler 概覽

當您首次打開 Memory Profiler 時茄螃,您將看到一條表示應(yīng)用內(nèi)存使用量的詳細時間線缝驳,并可訪問用于強制執(zhí)行垃圾回收、捕捉堆轉(zhuǎn)儲和記錄內(nèi)存分配的各種工具归苍。

圖 1. Memory Profiler

如圖 1 所示用狱,Memory Profiler 的默認視圖包括以下各項:

  1. 用于強制執(zhí)行垃圾回收 Event 的按鈕。
  2. 用于捕獲堆轉(zhuǎn)儲的按鈕拼弃。
  3. 用于記錄內(nèi)存分配情況的按鈕夏伊。 此按鈕僅在連接至運行 Android 7.1 或更低版本的設(shè)備時才會顯示。
  4. 用于放大/縮小時間線的按鈕吻氧。
  5. 用于跳轉(zhuǎn)至實時內(nèi)存數(shù)據(jù)的按鈕溺忧。
  6. Event 時間線,其顯示 Activity 狀態(tài)盯孙、用戶輸入 Event 和屏幕旋轉(zhuǎn) Event鲁森。
  7. 內(nèi)存使用量時間線,其包含以下內(nèi)容:
    • 一個顯示每個內(nèi)存類別使用多少內(nèi)存的堆疊圖表振惰,如左側(cè)的 y 軸以及頂部的彩色鍵所示歌溉。
    • 虛線表示分配的對象數(shù),如右側(cè)的 y 軸所示骑晶。
    • 用于表示每個垃圾回收 Event 的圖標痛垛。

不過草慧,如果您使用的是運行 Android 7.1 或更低版本的設(shè)備,則默認情況下榜晦,并不是所有分析數(shù)據(jù)均可見冠蒋。 如果您看到一條消息羽圃,其顯示“Advanced profiling is unavailable for the selected process”乾胶,則需要啟用高級分析以查看下列內(nèi)容:

  • Event 時間線
  • 分配的對象數(shù)
  • 垃圾回收 Event

在 Android 8.0 及更高版本上,始終為可調(diào)試應(yīng)用啟用高級分析朽寞。

三识窿、 如何計算內(nèi)存

您在 Memory Profiler(圖 2)頂部看到的數(shù)字取決于您的應(yīng)用根據(jù) Android 系統(tǒng)機制所提交的所有私有內(nèi)存頁面數(shù)。 此計數(shù)不包含與系統(tǒng)或其他應(yīng)用共享的頁面脑融。

圖 2. Memory Profiler 頂部的內(nèi)存計數(shù)圖例

內(nèi)存計數(shù)中的類別如下所示:

  • Java:從 Java 或 Kotlin 代碼分配的對象內(nèi)存喻频。

  • Native:從 C 或 C++ 代碼分配的對象內(nèi)存。

    即使您的應(yīng)用中不使用 C++肘迎,您也可能會看到此處使用的一些原生內(nèi)存甥温,因為 Android 框架使用原生內(nèi)存代表您處理各種任務(wù),如處理圖像資源和其他圖形時妓布,即使您編寫的代碼采用 Java 或 Kotlin 語言姻蚓。

  • Graphics:圖形緩沖區(qū)隊列向屏幕顯示像素(包括 GL 表面、GL 紋理等等)所使用的內(nèi)存匣沼。 (請注意狰挡,這是與 CPU 共享的內(nèi)存,不是 GPU 專用內(nèi)存释涛。)

  • Stack: 您的應(yīng)用中的原生堆棧和 Java 堆棧使用的內(nèi)存加叁。 這通常與您的應(yīng)用運行多少線程有關(guān)。

  • Code:您的應(yīng)用用于處理代碼和資源(如 dex 字節(jié)碼唇撬、已優(yōu)化或已編譯的 dex 碼它匕、.so 庫和字體)的內(nèi)存。

  • Other:您的應(yīng)用使用的系統(tǒng)不確定如何分類的內(nèi)存窖认。

  • Allocated:您的應(yīng)用分配的 Java/Kotlin 對象數(shù)豫柬。 它沒有計入 C 或 C++ 中分配的對象。

    當連接至運行 Android 7.1 及更低版本的設(shè)備時耀态,此分配僅在 Memory Profiler 連接至您運行的應(yīng)用時才開始計數(shù)轮傍。 因此,您開始分析之前分配的任何對象都不會被計入首装。 不過创夜,Android 8.0 附帶一個設(shè)備內(nèi)置分析工具,該工具可記錄所有分配仙逻,因此驰吓,在 Android 8.0 及更高版本上涧尿,此數(shù)字始終表示您的應(yīng)用中待處理的 Java 對象總數(shù)。

與以前的 Android Monitor 工具中的內(nèi)存計數(shù)相比檬贰,新的 Memory Profiler 以不同的方式記錄您的內(nèi)存姑廉,因此,您的內(nèi)存使用量現(xiàn)在看上去可能會更高些翁涤。 Memory Profiler 監(jiān)控的類別更多桥言,這會增加總的內(nèi)存使用量,但如果您僅關(guān)心 Java 堆內(nèi)存葵礼,則“Java”項的數(shù)字應(yīng)與以前工具中的數(shù)值相似号阿。

然而,Java 數(shù)字可能與您在 Android Monitor 中看到的數(shù)字并非完全相同鸳粉,這是因為應(yīng)用的 Java 堆是從 Zygote 啟動的扔涧,而新數(shù)字則計入了為它分配的所有物理內(nèi)存頁面。 因此届谈,它可以準確反映您的應(yīng)用實際使用了多少物理內(nèi)存枯夜。

注:目前,Memory Profiler 還會顯示應(yīng)用中的一些誤報的原生內(nèi)存使用量艰山,而這些內(nèi)存實際上是分析工具使用的湖雹。 對于大約 100000 個對象,最多會使報告的內(nèi)存使用量增加 10MB程剥。 在這些工具的未來版本中劝枣,這些數(shù)字將從您的數(shù)據(jù)中過濾掉。

四织鲸、 查看內(nèi)存分配

內(nèi)存分配顯示內(nèi)存中每個對象是如何分配的舔腾。 具體而言,Memory Profiler 可為您顯示有關(guān)對象分配的以下信息:

  • 分配哪些類型的對象以及它們使用多少空間搂擦。
  • 每個分配的堆疊追蹤稳诚,包括在哪個線程中。
  • 對象在何時被取消分配(僅當使用運行 Android 8.0 或更高版本的設(shè)備時)瀑踢。

如果您的設(shè)備運行 Android 8.0 或更高版本扳还,您可以隨時按照下述方法查看您的對象分配: 只需點擊并按住時間線,并拖動選擇您想要查看分配的區(qū)域(如視頻 1 中所示)橱夭。 不需要開始記錄會話氨距,因為 Android 8.0 及更高版本附帶設(shè)備內(nèi)置分析工具,可持續(xù)跟蹤您的應(yīng)用分配棘劣。


視頻 1. 對于Android 8.0 及更高版本俏让,選擇一個現(xiàn)有時間線區(qū)域以查看對象分配

如果您的設(shè)備運行 Android 7.1 或更低版本,則在 Memory Profiler 工具欄中點擊 Record memory allocations

。 記錄時首昔,Android Monitor 將跟蹤您的應(yīng)用中進行的所有分配寡喝。 操作完成后,點擊 Stop recording

(同一個按鈕勒奇;請參閱視頻 2)以查看分配预鬓。


視頻 2. 對于 Android 7.1 及更低版本,您必須顯式記錄內(nèi)存分配

在選擇一個時間線區(qū)域后(或當您使用運行 Android 7.1 或更低版本的設(shè)備完成記錄會話時)赊颠,已分配對象的列表將顯示在時間線下方格二,按類名稱進行分組,并按其堆計數(shù)排序巨税。

注:在 Android 7.1 及更低版本上蟋定,您最多可以記錄 65535 個分配。 如果您的記錄會話超出此限值草添,則記錄中僅保存最新的 65535 個分配。 (在 Android 8.0 及更高版本中扼仲,則沒有實際的限制远寸。)

要檢查分配記錄,請按以下步驟操作:

  1. 瀏覽列表以查找堆計數(shù)異常大且可能存在泄漏的對象屠凶。 為幫助查找已知類驰后,點擊 Class Name 列標題以按字母順序排序。 然后點擊一個類名稱矗愧。 此時在右側(cè)將出現(xiàn) Instance View 窗格灶芝,顯示該類的每個實例,如圖 3 中所示唉韭。
  2. Instance View 窗格中夜涕,點擊一個實例。 此時下方將出現(xiàn) Call Stack 標簽属愤,顯示該實例被分配到何處以及哪個線程中女器。
  3. Call Stack 標簽中,點擊任意行以在編輯器中跳轉(zhuǎn)到該代碼住诸。
圖 3. 有關(guān)每個已分配對象的詳情顯示在右側(cè)的 **Instance View** 中

默認情況下驾胆,左側(cè)的分配列表按類名稱排列。 在列表頂部贱呐,您可以使用右側(cè)的下拉列表在以下排列方式之間進行切換:

  • Arrange by class:基于類名稱對所有分配進行分組丧诺。
  • Arrange by package:基于軟件包名稱對所有分配進行分組。
  • Arrange by callstack:將所有分配分組到其對應(yīng)的調(diào)用堆棧奄薇。

五驳阎、 捕獲堆轉(zhuǎn)儲

堆轉(zhuǎn)儲顯示在您捕獲堆轉(zhuǎn)儲時您的應(yīng)用中哪些對象正在使用內(nèi)存。 特別是在長時間的用戶會話后,堆轉(zhuǎn)儲會顯示您認為不應(yīng)再位于內(nèi)存中卻仍在內(nèi)存中的對象搞隐,從而幫助識別內(nèi)存泄漏驹愚。 在捕獲堆轉(zhuǎn)儲后,您可以查看以下信息:

  • 您的應(yīng)用已分配哪些類型的對象劣纲,以及每個類型分配多少逢捺。
  • 每個對象正在使用多少內(nèi)存。
  • 在代碼中的何處仍在引用每個對象癞季。
  • 對象所分配到的調(diào)用堆棧劫瞳。 (目前,如果您在記錄分配時捕獲堆轉(zhuǎn)儲绷柒,則只有在 Android 7.1 及更低版本中志于,堆轉(zhuǎn)儲才能使用調(diào)用堆棧。)
圖 4. 查看堆轉(zhuǎn)儲

要捕獲堆轉(zhuǎn)儲废睦,在 Memory Profiler 工具欄中點擊 Dump Java heap

伺绽。 在轉(zhuǎn)儲堆期間,Java 內(nèi)存量可能會暫時增加嗜湃。 這很正常奈应,因為堆轉(zhuǎn)儲與您的應(yīng)用發(fā)生在同一進程中,并需要一些內(nèi)存來收集數(shù)據(jù)购披。

堆轉(zhuǎn)儲顯示在內(nèi)存時間線下杖挣,顯示堆中的所有類類型,如圖 4 所示刚陡。

注:如果您需要更精確地了解轉(zhuǎn)儲的創(chuàng)建時間惩妇,可以通過調(diào)用dumpHprofData()在應(yīng)用代碼的關(guān)鍵點創(chuàng)建堆轉(zhuǎn)儲。

要檢查您的堆筐乳,請按以下步驟操作:

  1. 瀏覽列表以查找堆計數(shù)異常大且可能存在泄漏的對象歌殃。 為幫助查找已知類,點擊 Class Name 列標題以按字母順序排序哥童。 然后點擊一個類名稱挺份。 此時在右側(cè)將出現(xiàn) Instance View 窗格,顯示該類的每個實例贮懈,如圖 5 中所示匀泊。

  2. Instance View 窗格中,點擊一個實例朵你。此時下方將出現(xiàn) References各聘,顯示該對象的每個引用。

    或者抡医,點擊實例名稱旁的箭頭以查看其所有字段躲因,然后點擊一個字段名稱查看其所有引用早敬。 如果您要查看某個字段的實例詳情,右鍵點擊該字段并選擇 Go to Instance大脉。

  3. References 標簽中搞监,如果您發(fā)現(xiàn)某個引用可能在泄漏內(nèi)存,則右鍵點擊它并選擇 Go to Instance镰矿。 這將從堆轉(zhuǎn)儲中選擇對應(yīng)的實例琐驴,顯示您自己的實例數(shù)據(jù)。

默認情況下秤标,堆轉(zhuǎn)儲不會向您顯示每個已分配對象的堆疊追蹤绝淡。 要獲取堆疊追蹤,在點擊 Dump Java heap 之前苍姜,您必須先開始記錄內(nèi)存分配牢酵。 然后,您可以在 Instance View 中選擇一個實例衙猪,并查看 Call Stack 標簽以及 References 標簽馍乙,如圖 5 所示。不過屈嗤,在您開始記錄分配之前潘拨,可能已分配一些對象,因此饶号,調(diào)用堆棧不能用于這些對象。 包含調(diào)用堆棧的實例在圖標

上用一個“堆椉韭欤”標志表示茫船。 (遺憾的是,由于堆疊追蹤需要您執(zhí)行分配記錄扭屁,因此算谈,您目前無法在 Android 8.0 上查看堆轉(zhuǎn)儲的堆疊追蹤。)

在您的堆轉(zhuǎn)儲中料滥,請注意由下列任意情況引起的內(nèi)存泄漏:

  • 長時間引用 Activity然眼、ContextView葵腹、Drawable 和其他對象高每,可能會保持對 ActivityContext 容器的引用。
  • 可以保持 Activity 實例的非靜態(tài)內(nèi)部類践宴,如 Runnable鲸匿。
  • 對象保持時間超出所需時間的緩存。
圖 5. 捕獲堆轉(zhuǎn)儲需要的持續(xù)時間標示在時間線中

在類列表中阻肩,您可以查看以下信息:

  • Heap Count:堆中的實例數(shù)带欢。
  • Shallow Size:此堆中所有實例的總大小(以字節(jié)為單位)。
  • Retained Size:為此類的所有實例而保留的內(nèi)存總大星巧贰(以字節(jié)為單位)吁朦。

在類列表頂部,您可以使用左側(cè)下拉列表在以下堆轉(zhuǎn)儲之間進行切換:

  • Default heap:系統(tǒng)未指定堆時渡贾。
  • App heap:您的應(yīng)用在其中分配內(nèi)存的主堆逗宜。
  • Image heap:系統(tǒng)啟動映像,包含啟動期間預(yù)加載的類剥啤。 此處的分配保證絕不會移動或消失锦溪。
  • Zygote heap:寫時復制堆府怯,其中的應(yīng)用進程是從 Android 系統(tǒng)中派生的刻诊。

默認情況下,此堆中的對象列表按類名稱排列牺丙。 您可以使用其他下拉列表在以下排列方式之間進行切換:

  • Arrange by class:基于類名稱對所有分配進行分組则涯。
  • Arrange by package:基于軟件包名稱對所有分配進行分組。
  • Arrange by callstack:將所有分配分組到其對應(yīng)的調(diào)用堆棧冲簿。 此選項僅在記錄分配期間捕獲堆轉(zhuǎn)儲時才有效粟判。 即使如此,堆中的對象也很可能是在您開始記錄之前分配的峦剔,因此這些分配會首先顯示档礁,且只按類名稱列出。

默認情況下吝沫,此列表按 Retained Size 列排序呻澜。 您可以點擊任意列標題以更改列表的排序方式。

Instance View 中惨险,每個實例都包含以下信息:

  • Depth:從任意 GC 根到所選實例的最短 hop 數(shù)羹幸。
  • Shallow Size:此實例的大小。
  • Retained Size:此實例支配的內(nèi)存大斜栌洹(根據(jù) dominator 樹)栅受。

六、 將堆轉(zhuǎn)儲另存為 HPROF

在捕獲堆轉(zhuǎn)儲后恭朗,僅當分析器運行時才能在 Memory Profiler 中查看數(shù)據(jù)屏镊。 當您退出分析會話時,您將丟失堆轉(zhuǎn)儲冀墨。 因此闸衫,如果您要保存堆轉(zhuǎn)儲以供日后查看,可通過點擊時間線下方工具欄中的 Export heap dump as HPROF file

诽嘉,將堆轉(zhuǎn)儲導出到一個 HPROF 文件中蔚出。 在顯示的對話框中弟翘,確保使用 .hprof 后綴保存文件。

然后骄酗,通過將此文件拖到一個空的編輯器窗口(或?qū)⑵渫系轿募撕灆谥校┫∮啵梢栽?Android Studio 中重新打開該文件。

要使用其他 HPROF 分析器如 jhat趋翻,您需要將 HPROF 文件從 Android 格式轉(zhuǎn)換為 Java SE HPROF 格式睛琳。 您可以使用 android_sdk/platform-tools/目錄中提供的 hprof-conv 工具執(zhí)行此操作。 運行包括以下兩個參數(shù)的 hprof-conv命令:原始 HPROF 文件和轉(zhuǎn)換后 HPROF 文件的寫入位置踏烙。 例如:

hprof-conv heap-original.hprof heap-converted.hprof

七师骗、 分析內(nèi)存的技巧

使用 Memory Profiler 時,您應(yīng)對應(yīng)用代碼施加壓力并嘗試強制內(nèi)存泄漏讨惩。 在應(yīng)用中引發(fā)內(nèi)存泄漏的一種方式是辟癌,先讓其運行一段時間,然后再檢查堆荐捻。 泄漏在堆中可能逐漸匯聚到分配頂部黍少。 不過,泄漏越小处面,您越需要運行更長時間的應(yīng)用才能看到泄漏厂置。

您還可以通過以下方式之一觸發(fā)內(nèi)存泄漏:

  • 將設(shè)備從縱向旋轉(zhuǎn)為橫向,然后在不同的 Activity 狀態(tài)下反復操作多次魂角。 旋轉(zhuǎn)設(shè)備經(jīng)常會導致應(yīng)用泄漏 Activity昵济、ContextView 對象,因為系統(tǒng)會重新創(chuàng)建 Activity野揪,而如果您的應(yīng)用在其他地方保持對這些對象之一的引用砸紊,系統(tǒng)將無法對其進行垃圾回收。
  • 處于不同的 Activity 狀態(tài)時囱挑,在您的應(yīng)用與另一個應(yīng)用之間切換(導航到主屏幕,然后返回到您的應(yīng)用)沼溜。

提示: 您還可以使用 monkeyrunner 測試框架執(zhí)行上述步驟平挑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者系草。
  • 序言:七十年代末通熄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子找都,更是在濱河造成了極大的恐慌唇辨,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件能耻,死亡現(xiàn)場離奇詭異赏枚,居然都是意外死亡亡驰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門饿幅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凡辱,“玉大人,你說我怎么就攤上這事袒哥“霸桑” “怎么了侠仇?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長乳乌。 經(jīng)常有香客問我,道長市咆,這世上最難降的妖魔是什么汉操? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮床绪,結(jié)果婚禮上客情,老公的妹妹穿的比我還像新娘。我一直安慰自己癞己,他們只是感情好膀斋,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痹雅,像睡著了一般仰担。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绩社,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天摔蓝,我揣著相機與錄音,去河邊找鬼愉耙。 笑死贮尉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的朴沿。 我是一名探鬼主播猜谚,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赌渣!你這毒婦竟也來了魏铅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坚芜,失蹤者是張志新(化名)和其女友劉穎览芳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸿竖,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡沧竟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年铸敏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屯仗。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡搞坝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出魁袜,到底是詐尸還是另有隱情桩撮,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布峰弹,位于F島的核電站店量,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鞠呈。R本人自食惡果不足惜融师,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚁吝。 院中可真熱鬧旱爆,春花似錦、人聲如沸窘茁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山林。三九已至房待,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驼抹,已是汗流浹背桑孩。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留框冀,地道東北人流椒。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像明也,于是被迫代替她去往敵國和親镣隶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

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