Android 內(nèi)存管理

Android是一個(gè)基于Linux實(shí)現(xiàn)的操作系統(tǒng)宫补。但對(duì)于Linux內(nèi)核來(lái)說(shuō)只壳,Android也僅僅只是一個(gè)運(yùn)行在內(nèi)核之上的應(yīng)用程序饵筑,與其他運(yùn)行在內(nèi)核之上的應(yīng)用程序沒(méi)有任何區(qū)別腰湾。所以Android需要一套機(jī)制管理運(yùn)行在Linux進(jìn)程中的APK應(yīng)用程序雷恃。Android內(nèi)存管理包含兩部分,一部分是Framework對(duì)內(nèi)存的管理费坊,一部分是Linux內(nèi)核對(duì)內(nèi)存管理倒槐,這兩部分共同決定應(yīng)用程序的生命周期。本文主要闡述Android內(nèi)存管理機(jī)制的實(shí)現(xiàn)原理附井,以及在應(yīng)用開(kāi)發(fā)中需要注意的一些事項(xiàng)讨越,最后本文總結(jié)了如何實(shí)現(xiàn)殺不死進(jìn)程的一種方法。

Linux 進(jìn)程回收


在Android中永毅,大部分應(yīng)用程序都運(yùn)行在一個(gè)獨(dú)立的Linux進(jìn)程中把跨,每個(gè)進(jìn)程都有獨(dú)立的內(nèi)存空間。隨著各種應(yīng)用程序啟動(dòng)沼死,系統(tǒng)內(nèi)存不斷下降着逐,為了保證新應(yīng)用能夠運(yùn)行,Android需要一套機(jī)制殺死暫時(shí)閑置的進(jìn)程漫雕。

Android Framework并不能直接回收內(nèi)存滨嘱,其管理進(jìn)程的服務(wù)(ActivityManagerService,以下簡(jiǎn)稱(chēng)AmS)也同應(yīng)用程序一樣運(yùn)行在Java虛擬機(jī)環(huán)境里浸间。Java虛擬機(jī)都運(yùn)行在各自獨(dú)立的內(nèi)存空間太雨,所以ActivityManagerService沒(méi)有辦法感知應(yīng)用程序是否OOM。

Android系統(tǒng)中還運(yùn)行了一個(gè)OOM進(jìn)程魁蒜。該進(jìn)程啟動(dòng)時(shí)首先會(huì)在Linux內(nèi)核中把自己注冊(cè)為一個(gè)OOM Killer囊扳。AmS需要把每一個(gè)應(yīng)用程序的oom_adj值告知OOM Killer吩翻,這個(gè)值的范圍在-16到15之間,值越低锥咸,說(shuō)明越重要狭瞎,這個(gè)值類(lèi)似于Linux中的nice值,只在標(biāo)準(zhǔn)的Linux中搏予,有其自己的OOM Killer熊锭。Android中的OOM Killer進(jìn)程僅僅適用于Android應(yīng)用程序。

當(dāng)內(nèi)核的內(nèi)存管理模塊檢測(cè)到系統(tǒng)內(nèi)存不足時(shí)就會(huì)通知OOM Killer雪侥,然后OOM Killer根據(jù)AmS所告知的優(yōu)先級(jí)強(qiáng)制退出優(yōu)先級(jí)低的應(yīng)用程序碗殷。

應(yīng)用程序在內(nèi)存中的狀態(tài)


Android官方聲稱(chēng),Activity退出后速缨,其所在進(jìn)程并不會(huì)被立即殺死锌妻,從而在下次啟動(dòng)Activity時(shí),能夠提高啟動(dòng)速度旬牲。這些Activity只有在內(nèi)存緊張時(shí)才會(huì)被系統(tǒng)殺死仿粹。所以對(duì)于應(yīng)用程序來(lái)說(shuō),關(guān)閉并不意味著釋放內(nèi)存原茅。

Activity在內(nèi)存中的狀態(tài)
系統(tǒng)只有一個(gè)Activity處于與用戶(hù)交互的狀態(tài)吭历,對(duì)于非交互狀態(tài)的Activity,AmS會(huì)在內(nèi)部暫時(shí)緩存起來(lái)而不是立即殺死员咽,但如果后臺(tái)Activity數(shù)目超過(guò)一定閾值毒涧,AmS則會(huì)強(qiáng)制殺死一些優(yōu)先級(jí)低的Activity。以下是Activity在內(nèi)存或者說(shuō)在AmS中的狀態(tài):

  • AmS會(huì)記錄最近啟動(dòng)的20個(gè)Activity贝室,如果超過(guò)20則舍棄最早記錄的Activity契讲。
  • AmS會(huì)將所有正在運(yùn)行的Activity保存在一個(gè)列表中,對(duì)于使用back返回的Activity則從列表中清除滑频。
  • AmS使用Lru算法保存所有最近使用過(guò)的Activity捡偏。
  • AmS使用一個(gè)列表(mStoppingActivities)保存需要停止的Activity,這種情況
    發(fā)生在啟動(dòng)一個(gè)Activity時(shí)峡迷,AmS遵循先啟動(dòng)后停止的策略银伟,將需要停止的Activity保存在此列表中,等AmS閑置下來(lái)后再停止Activity绘搞。
  • AmS使用一個(gè)列表保存處于finish狀態(tài)(onDestory())的Activity彤避,當(dāng)一個(gè)Activity處于finish狀態(tài)時(shí)(onDestory()執(zhí)行后)不會(huì)被立即殺死,而是保存到該列表中直到超過(guò)系統(tǒng)設(shè)定的警戒線才會(huì)回收該列表中的Activity夯辖。

應(yīng)用進(jìn)程在內(nèi)存中的狀態(tài)
每個(gè)應(yīng)用程序都對(duì)應(yīng)著一個(gè)ActivityThread類(lèi)琉预,該類(lèi)初始化后就進(jìn)入Looper.loop()函數(shù)中無(wú)限循環(huán)。

Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
Looper.loop();

以后則依靠消息機(jī)制運(yùn)行蒿褂,既當(dāng)有消息時(shí)處理消息圆米,沒(méi)有消息則應(yīng)用進(jìn)程進(jìn)入sleep狀態(tài)卒暂。loop()方法內(nèi)部代碼如下所示:

public static final loop() {
  Looper me = myLooper();
  MessageQueue queue = me.mQueue;
  while(true){
    Message msg = queue.next();// might block
    ...
  }
}

在Linux內(nèi)核調(diào)度中,如果一個(gè)線程的狀態(tài)為sleep娄帖,則除了占用調(diào)度本身的時(shí)間也祠,不會(huì)占用CPU時(shí)間片。

有三種情況會(huì)喚醒應(yīng)用線程近速,一種是定時(shí)器中斷(比如我們?cè)O(shè)置的鬧鐘诈嘿,在程序中可以設(shè)置定時(shí)任務(wù)),第二種是用戶(hù)按鍵消息削葱,第三種是Binder消息(Binder用于進(jìn)程間通信永淌,其在應(yīng)用程序中會(huì)自動(dòng)創(chuàng)建一個(gè)線程,Binder在接收到消息后會(huì)想U(xiǎn)I主線程發(fā)送一個(gè)消息從而使queue.next()繼續(xù)執(zhí)行)這就是所謂的消息驅(qū)動(dòng)模式佩耳。

所以設(shè)計(jì)良好的應(yīng)用程序當(dāng)處于后臺(tái)時(shí)不會(huì)占用任何CPU時(shí)間,更不會(huì)拖慢系統(tǒng)運(yùn)行速度谭跨。其所占用的僅僅是內(nèi)存干厚,即使釋放所占用的內(nèi)存也不會(huì)提高系統(tǒng)運(yùn)行速度。當(dāng)然這里說(shuō)的是設(shè)計(jì)良好的應(yīng)用程序螃宙,目前國(guó)內(nèi)很多應(yīng)用在處于后臺(tái)狀態(tài)時(shí)依然會(huì)偷偷干很多事情蛮瞄,這無(wú)疑就拖慢了系統(tǒng)運(yùn)行速度。

Android 內(nèi)存回收


Activity所占內(nèi)存在一般情況下不會(huì)被回收谆扎,只有在系統(tǒng)內(nèi)存不夠用時(shí)才會(huì)回收挂捅,并且回收會(huì)遵循一定規(guī)則。大致可以概括為前臺(tái)Activity最后回收堂湖,其次是包含前臺(tái)的Service或者Provider闲先,再其次是后臺(tái)Activity,最后是空進(jìn)程无蜂。

內(nèi)存釋放的三個(gè)地方

  • 第一個(gè)是在ActivityManagerService中運(yùn)行伺糠,即Android所聲稱(chēng)的當(dāng)系統(tǒng)內(nèi)存低時(shí),優(yōu)先釋放沒(méi)有任何Activity的進(jìn)程斥季,然后釋放非前臺(tái)Activity對(duì)應(yīng)的進(jìn)程训桶。
  • 第二個(gè)是在OOM Killer中,此時(shí)AmS只要告訴OOM各個(gè)應(yīng)用的優(yōu)先級(jí)酣倾,然后OOM就會(huì)調(diào)用Linux內(nèi)部的進(jìn)程管理方法殺死優(yōu)先級(jí)較低的進(jìn)程舵揭。
  • 第三個(gè)是在應(yīng)用進(jìn)程本身之中,當(dāng)AmS認(rèn)為目標(biāo)進(jìn)程需要被殺死時(shí)躁锡,首先會(huì)通知目標(biāo)進(jìn)程進(jìn)程內(nèi)存釋放午绳。這包括調(diào)用目標(biāo)進(jìn)程的scheduleLowMemory()方法和processInBackground()方法。

關(guān)閉Activity的三種情況

  • 第一種稚铣,從調(diào)用startActivity()開(kāi)始箱叁,一般情況下墅垮,當(dāng)前都有正在運(yùn)行的Activity,所以需要先暫停當(dāng)前的Activity耕漱,而暫停完畢后算色,AmS會(huì)收到一個(gè)Binder消息,并開(kāi)始從completePaused()處執(zhí)行螟够。在該函數(shù)中灾梦,由于上一個(gè)Activity并沒(méi)有finishing,僅僅是stop妓笙,所以這里會(huì)把上一個(gè)Activity添加到mStoppingActivity列表中若河。當(dāng)目標(biāo)Activity啟動(dòng)后,會(huì)向Ams發(fā)送一個(gè)請(qǐng)求進(jìn)行內(nèi)存回收的消息寞宫,這會(huì)導(dǎo)致AmS在內(nèi)部調(diào)用activityIdleInternal()方法萧福,該方法中首先會(huì)處理mStoppingActivities列表中的Activity,這就會(huì)調(diào)用stopActivityLocked()方法辈赋。這又會(huì)通過(guò)IPC調(diào)用鲫忍,通知應(yīng)用進(jìn)程stop指定的Activity,當(dāng)stop完畢后钥屈,再報(bào)告給AmS悟民,于是AmS再?gòu)腶ctivityStopped()出開(kāi)始執(zhí)行,而這會(huì)調(diào)用trimApplication()方法篷就,該方法會(huì)執(zhí)行內(nèi)存相關(guān)的操作射亏。
  • 第二種,當(dāng)按Back鍵后竭业,會(huì)調(diào)用finishActivityLocked()智润,然后把該Activity的finishing標(biāo)識(shí)設(shè)為true,然后再調(diào)用startPausingLocked()永品,當(dāng)目標(biāo)Activity完成暫停后做鹰,就會(huì)報(bào)告AmS,此時(shí)AmS又會(huì)從completePaused()處開(kāi)始執(zhí)行鼎姐。與第一種情況不同钾麸,由于此時(shí)暫停的Activity的finishing狀態(tài)已經(jīng)設(shè)置為true,所以會(huì)執(zhí)行finishingActivityLocked()炕桨,而不是像第一種情況中僅僅把該Activity添加到mStoppingActivities列表饭尝。
  • 第三種,當(dāng)Activity啟動(dòng)后献宫,會(huì)向AmS發(fā)送一個(gè)Idle消息钥平,這會(huì)導(dǎo)致AmS開(kāi)始執(zhí)行activityIdleInternal()方法。該方法會(huì)首先處理mStoppingActivities列表中的對(duì)象姊途,接著處理mFinishingActivities列表涉瘾,最后再調(diào)用trimApplication()方法知态。

以上就是關(guān)閉Activity的三種情況,包括stop和destory立叛,客戶(hù)進(jìn)程中與之對(duì)應(yīng)的就是onStop()和onDestory()的調(diào)用负敏。

如果使用OOM還有AmS機(jī)制殺死后臺(tái)進(jìn)程后,此時(shí)運(yùn)行的Activity數(shù)量依然超過(guò)MAX_ACTIVITIES(20)秘蛇,則需要繼續(xù)銷(xiāo)毀滿(mǎn)足以下三個(gè)條件的Activity:

  1. Activity必須已經(jīng)stop其做,但卻沒(méi)有finishing
  2. 必須是不可見(jiàn)的,既該Activity窗口上面有其他全屏的窗口赁还,如果不是全屏妖泄,則后面的Activity是可見(jiàn)的。
  3. 不能是persistent類(lèi)型艘策,既常駐進(jìn)程不能被殺死蹈胡。

進(jìn)程優(yōu)先級(jí)


Android系統(tǒng)試圖盡可能長(zhǎng)時(shí)間地保持應(yīng)用程序進(jìn)程,但為了新建或者運(yùn)行更加重要的進(jìn)程朋蔫,總是需要清除過(guò)時(shí)進(jìn)程來(lái)回收內(nèi)存审残。為了決定保留或終止哪個(gè)進(jìn)程,根據(jù)進(jìn)程內(nèi)運(yùn)行的組件及這些組件的狀態(tài)斑举,系統(tǒng)把每個(gè)進(jìn)程都劃入一個(gè)“重要性層次結(jié)構(gòu)”中。重要性最低的進(jìn)程首先會(huì)被清除病涨,然后是下一個(gè)最低的富玷,依此類(lèi)推。

重要性層次結(jié)構(gòu)共有5級(jí)既穆,以下列表按照重要程度列出了各類(lèi)進(jìn)程(第一類(lèi)進(jìn)程是最重要的赎懦,將最后一個(gè)被終止):

1)前臺(tái)進(jìn)程

用戶(hù)當(dāng)前操作所必須的進(jìn)程。滿(mǎn)足以下任一條件時(shí)幻工,進(jìn)程被視作處于前臺(tái):
其中運(yùn)行著正與用戶(hù)交互的Activity(Activity對(duì)象的onResume()方法已被調(diào)用)励两。
其中運(yùn)行著與用戶(hù)交互的activity綁定的Service。
其中運(yùn)行著前臺(tái)Service囊颅,既該Service以startForeground()方式被調(diào)用当悔。
其中運(yùn)行著正在執(zhí)行生命周期回調(diào)方法(onCreate()、onStart()或onDestory())的Service踢代。
其中運(yùn)行著正在執(zhí)行onReceive()方法的BroadcastReceiver盲憎。

一般而言,任何時(shí)刻前臺(tái)進(jìn)程的數(shù)量都為數(shù)不多胳挎,只有當(dāng)內(nèi)存不足以維持它們同時(shí)運(yùn)行時(shí)才會(huì)被終止饼疙。通常,設(shè)備這時(shí)候已經(jīng)到了使用虛擬內(nèi)存的地步慕爬,終止一些前臺(tái)進(jìn)程是為了保證用戶(hù)界面的及時(shí)響應(yīng)窑眯。

2) 可見(jiàn)進(jìn)程

沒(méi)有前臺(tái)組件屏积、但仍會(huì)影響用戶(hù)在屏幕上所見(jiàn)內(nèi)容的進(jìn)程。滿(mǎn)足以下任一條件時(shí)磅甩,進(jìn)程被認(rèn)為是可見(jiàn)的:
其中運(yùn)行著非前臺(tái)Activity炊林,但用戶(hù)仍然可見(jiàn)到此activity(onPause()方法被調(diào)用)。例如更胖,打開(kāi)了一個(gè)對(duì)話(huà)框铛铁,而activity還允許顯示在對(duì)話(huà)框后面,對(duì)用戶(hù)依然可見(jiàn)却妨。
其中運(yùn)行著被可見(jiàn)(或前臺(tái))activity綁定的Service饵逐。

可見(jiàn)進(jìn)程被認(rèn)為是非常重要的進(jìn)程,除非無(wú)法維持所有前臺(tái)進(jìn)程同時(shí)運(yùn)行了彪标,否則它們是不會(huì)被終止的倍权。

3) 服務(wù)進(jìn)程

此進(jìn)程運(yùn)行著由startService()方法啟動(dòng)的服務(wù),它不會(huì)升級(jí)為前臺(tái)進(jìn)程或可見(jiàn)進(jìn)程捞烟。盡管服務(wù)進(jìn)程不直接和用戶(hù)所見(jiàn)內(nèi)容關(guān)聯(lián)薄声,但他們通常在執(zhí)行一些用戶(hù)關(guān)心的操作(比如在后臺(tái)播放音樂(lè)或從網(wǎng)絡(luò)下載數(shù)據(jù))。因此题画,除非內(nèi)存不足以維持所有前臺(tái)默辨、可見(jiàn)進(jìn)程同時(shí)運(yùn)行,系統(tǒng)會(huì)保持服務(wù)進(jìn)程的運(yùn)行苍息。

4) 后臺(tái)進(jìn)程

包含用戶(hù)不可見(jiàn)activity(Activity對(duì)象的onStop()方法已被調(diào)用)的進(jìn)程缩幸。這些進(jìn)程對(duì)用戶(hù)體驗(yàn)沒(méi)有直接的影響,系統(tǒng)可能在任意時(shí)間終止它們竞思,以回收內(nèi)存供前臺(tái)進(jìn)程表谊、可見(jiàn)進(jìn)程及服務(wù)進(jìn)程使用。

通常系統(tǒng)會(huì)有很多后臺(tái)進(jìn)程在運(yùn)行盖喷,所以它們被保存在一個(gè)LRU(最近最少使用)列表中爆办,以確保最近被用戶(hù)使用的activity最后一個(gè)被終止。如果一個(gè)activity正確實(shí)現(xiàn)了生命周期方法课梳,并保存了當(dāng)前的狀態(tài)距辆,則終止此類(lèi)進(jìn)程不會(huì)對(duì)用戶(hù)體驗(yàn)產(chǎn)生可見(jiàn)的影響。因?yàn)樵谟脩?hù)返回時(shí)暮刃,activity會(huì)恢復(fù)所有可見(jiàn)的狀態(tài)挑格。關(guān)于保存和恢復(fù)狀態(tài)的詳細(xì)信息,請(qǐng)參閱Activity文檔沾歪。

5) 空進(jìn)程

不含任何活動(dòng)應(yīng)用程序組件的進(jìn)程漂彤。保留這種進(jìn)程的唯一目的就是用作緩存,以改善下次在此進(jìn)程中運(yùn)行組件的啟動(dòng)時(shí)間。為了在進(jìn)程緩存和內(nèi)核緩存間平衡系統(tǒng)整體資源挫望,系統(tǒng)經(jīng)常會(huì)終止這種進(jìn)程立润。

依據(jù)進(jìn)程中目前活躍組件的重要程度,Android會(huì)給進(jìn)程評(píng)估一個(gè)盡可能高的級(jí)別媳板。例如桑腮,如果一個(gè)進(jìn)程中運(yùn)行著一個(gè)服務(wù)和一個(gè)用戶(hù)可見(jiàn)的activity,則此進(jìn)程會(huì)被評(píng)定為可見(jiàn)進(jìn)程蛉幸,而不是服務(wù)進(jìn)程破讨。

此外,一個(gè)進(jìn)程的級(jí)別可能會(huì)由于其它進(jìn)程的依賴(lài)而被提高——為其它進(jìn)程提供服務(wù)的進(jìn)程級(jí)別永遠(yuǎn)不會(huì)低于使用此服務(wù)的進(jìn)程奕纫。比如:如果A進(jìn)程中的content provider為進(jìn)程B中的客戶(hù)端提供服務(wù)提陶,或進(jìn)程A中的服務(wù)被進(jìn)程B中的組件所調(diào)用,則A進(jìn)程至少被視為與進(jìn)程B同樣重要匹层。

因?yàn)檫\(yùn)行服務(wù)的進(jìn)程級(jí)別是高于后臺(tái)activity進(jìn)程的隙笆,所以,如果activity需要啟動(dòng)一個(gè)長(zhǎng)時(shí)間運(yùn)行的操作升筏,則為其啟動(dòng)一個(gè)服務(wù)會(huì)比簡(jiǎn)單地創(chuàng)建一個(gè)工作線程更好些——尤其是該操作時(shí)間比activity的生存期還要長(zhǎng)的情況下撑柔。比如,一個(gè)activity要把圖片上傳至Web網(wǎng)站您访,就應(yīng)該創(chuàng)建一個(gè)服務(wù)來(lái)執(zhí)行之铅忿,即使用戶(hù)離開(kāi)了此activity,上傳還是會(huì)在后臺(tái)繼續(xù)運(yùn)行灵汪。不論activity發(fā)生什么情況辆沦,使用服務(wù)可以保證操作至少擁有“服務(wù)進(jìn)程”的優(yōu)先級(jí)。同理识虚,廣播接收器broadcast receiver也是使用服務(wù)來(lái)處理耗時(shí)任務(wù)的,而不是簡(jiǎn)單地把它放入線程中妒茬。

殺不死的Service


如何讓?xiě)?yīng)用在手機(jī)中存活更長(zhǎng)時(shí)間担锤?網(wǎng)上各種方法可謂是千奇百怪,有些簡(jiǎn)直異想天開(kāi)乍钻。

  • 系統(tǒng)廣播喚醒應(yīng)用肛循,比如手機(jī)開(kāi)機(jī),網(wǎng)絡(luò)切換等
  • 接入第三方SDK喚醒應(yīng)用银择,比如接入微信SDK會(huì)喚醒微信
  • 免殺白名單多糠,比如360免殺白名單,MIUI系統(tǒng)免殺白名單
  • 全家桶浩考,應(yīng)用之間互相喚醒夹孔,比如百度系,阿里系應(yīng)用
  • 兩個(gè)Service互相喚醒(這個(gè)就別想了,不靠譜)
  • 使用Timer定時(shí)器(一樣不靠譜)

設(shè)計(jì)良好的應(yīng)用不應(yīng)該在用戶(hù)不使用的時(shí)候依然保持運(yùn)行搭伤。一直在后臺(tái)運(yùn)行不光費(fèi)電費(fèi)流量只怎,還是造成系統(tǒng)卡頓的主要原因之一(參見(jiàn)上文分析)。正常的做法是優(yōu)化你的應(yīng)用程序怜俐,減少不合理場(chǎng)景的情況身堡,除一些必要服務(wù)應(yīng)用外,大部分應(yīng)用不需要一直在后臺(tái)保存運(yùn)行狀態(tài)拍鲤。

有正常的做法就有不正常的做法贴谎,讓?xiě)?yīng)用長(zhǎng)時(shí)間停留在用戶(hù)手機(jī)中無(wú)外乎就是增加所謂的活躍用戶(hù)數(shù)等一些產(chǎn)品指標(biāo)。這對(duì)于很多公司還是很有吸引力的季稳。

如上文所說(shuō)擅这,無(wú)論應(yīng)用怎么掙扎,當(dāng)處于不可見(jiàn)進(jìn)程的情況下隨時(shí)都有可能被殺死绞幌。所以使用前臺(tái)進(jìn)程是最有效的方法蕾哟。但前臺(tái)進(jìn)程必須有一個(gè)Notifcation顯示在通知欄中,有沒(méi)有辦法讓?xiě)?yīng)用以前臺(tái)進(jìn)程的方式啟動(dòng)同時(shí)又不顯示Notifcation莲蜘?方法當(dāng)然有谭确,就是利用系統(tǒng)漏洞:

  • API<18,啟動(dòng)前臺(tái)Service時(shí)直接傳入new Notifcation();
  • API>=18票渠,同時(shí)啟動(dòng)兩個(gè)id相同的前臺(tái)Service逐哈,然后再將后啟動(dòng)的Service做stop處理

目前,QQ问顷,微信昂秃,支付寶等知名應(yīng)用都使用此方案。不過(guò)如果應(yīng)用占用太多內(nèi)存即使是前臺(tái)進(jìn)程也依然會(huì)被干掉杜窄。

這些所謂的實(shí)現(xiàn)進(jìn)程殺不死的方案并不都是一勞永逸的方法肠骆,以犧牲用戶(hù)體驗(yàn)為代價(jià)很有可能會(huì)激怒用戶(hù)卸載你的應(yīng)用,所以最好的方式還是遵循Android規(guī)范開(kāi)發(fā)性能更優(yōu)更合理的應(yīng)用程序塞耕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚀腿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扫外,更是在濱河造成了極大的恐慌莉钙,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筛谚,死亡現(xiàn)場(chǎng)離奇詭異磁玉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)驾讲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)蚊伞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)席赂,“玉大人,你說(shuō)我怎么就攤上這事厚柳⊙踉妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵别垮,是天一觀的道長(zhǎng)便监。 經(jīng)常有香客問(wèn)我,道長(zhǎng)碳想,這世上最難降的妖魔是什么烧董? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮胧奔,結(jié)果婚禮上逊移,老公的妹妹穿的比我還像新娘。我一直安慰自己龙填,他們只是感情好胳泉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著岩遗,像睡著了一般扇商。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宿礁,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天案铺,我揣著相機(jī)與錄音,去河邊找鬼梆靖。 笑死控汉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的返吻。 我是一名探鬼主播姑子,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼测僵!你這毒婦竟也來(lái)了街佑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恨课,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后岳服,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體剂公,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吊宋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纲辽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拖吼,靈堂內(nèi)的尸體忽然破棺而出鳞上,到底是詐尸還是另有隱情,我是刑警寧澤吊档,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布篙议,位于F島的核電站,受9級(jí)特大地震影響怠硼,放射性物質(zhì)發(fā)生泄漏鬼贱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一香璃、第九天 我趴在偏房一處隱蔽的房頂上張望这难。 院中可真熱鬧,春花似錦葡秒、人聲如沸姻乓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹋岩。三九已至,卻和暖如春炸站,著一層夾襖步出監(jiān)牢的瞬間星澳,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工旱易, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留禁偎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓阀坏,卻偏偏與公主長(zhǎng)得像如暖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忌堂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評(píng)論 25 707
  • 一.操作系統(tǒng)相關(guān)基礎(chǔ)知識(shí) 1.物理內(nèi)存盒至、虛擬內(nèi)存、邏輯地址與交換空間 物理內(nèi)存(RAM):加載到內(nèi)存地址寄存器中的...
    Geeks_Liu閱讀 9,126評(píng)論 6 30
  • Android中的內(nèi)存管理機(jī)制 分配機(jī)制 Android為每個(gè)進(jìn)程分配內(nèi)存的時(shí)候士修,采用了彈性的分配方式枷遂,也就是剛開(kāi)...
    帝王鯊kingcp閱讀 997評(píng)論 0 8
  • 寂寥無(wú)記誰(shuí)主頭 片片妄念不知由 誤入娑婆一堆肉 爭(zhēng)名逐利為度舟 有時(shí)候,活著活著就迷茫了棋嘲,走著走著就忘了要去哪酒唉! ...
    佛進(jìn)閱讀 467評(píng)論 1 0
  • python程序退出方式 sys.exit()執(zhí)行該語(yǔ)句會(huì)直接退出程序,這也是經(jīng)常使用的方法沸移,也不需要考慮平臺(tái)等因...
    西電大俠閱讀 32,534評(píng)論 0 3