深入理解Java虛擬機(jī)-垃圾收集器及內(nèi)存分配策略

  • 哪些內(nèi)存需要回收
  • 什么時候回收
  • 如何回收

如何判斷對象是否存活

可達(dá)性分析算法(Reachability Analysis): 通過一系列"GC Roots"對象作為起始點(diǎn),從這些節(jié)點(diǎn)開始往下搜索炭菌,搜索過的路徑稱為引用鏈(Reference Chain),當(dāng)任意一個對象到GC Roots沒有任何引用鏈相連時罪佳,則證明此對象不可用。

GC Roots對象包括以下幾種:

  • 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象
  • 方法區(qū)中類靜態(tài)變量屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧中JNI(本地Native方法)引用的對象

引用包括:

  • 強(qiáng)引用:Java代碼中類似Object obj = new Object()這類的引用黑低。只要有強(qiáng)引用在赘艳,垃圾收集器永遠(yuǎn)不會回收掉被引用的對象
  • 軟引用:用來描述一些還有用但并非必要的對象。對于軟引用關(guān)聯(lián)著的對象克握,在系統(tǒng)發(fā)生內(nèi)存溢出之前蕾管,將會把這些對象列進(jìn)回收范圍之中進(jìn)行二次回收。如果這次回收還沒有足夠的內(nèi)存菩暗,才會拋出內(nèi)存溢出異常掰曾。
  • 弱引用:比軟引用更弱一些,只能存活到垃圾收集活動發(fā)生之前停团。
  • 虛引用:它是最弱的一種引用關(guān)系旷坦,它存在的目的就是能在這個對象被收集器回收時收到系統(tǒng)通知。

對象的死亡

在可達(dá)性分析算法中不可達(dá)的對象佑稠,至少要經(jīng)歷兩次標(biāo)記的過程秒梅,才確定是否被回收:

1、如果對象在可達(dá)性分析后發(fā)現(xiàn)沒有與GC Roots相連的引用鏈舌胶,那它將會被第一次標(biāo)記并進(jìn)行一次篩選捆蜀,篩選的條件是此對象是否有必要執(zhí)行finalize()方法。當(dāng)對象沒有覆蓋finalize()方法時辆琅,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過漱办,虛擬機(jī)將這兩種情況都視為“沒有必要執(zhí)行”。

2婉烟、如果對象有必要執(zhí)行finalize()方法娩井,那么這個對象將會被放在一個F—Queue隊(duì)列之中,虛擬機(jī)的finalizer線程會執(zhí)行它

3似袁、finalize()方法是對象逃脫死亡的最后一次機(jī)會洞辣,稍后GC將對F-Queue隊(duì)列中的對象進(jìn)行第二次小規(guī)模的標(biāo)記,如果對象成功在finalize()中拯救自己(建立與引用鏈的聯(lián)系)昙衅,那在第二次標(biāo)記時它將被移除出“即將回收”的集合扬霜;否則它就要被回收。

方法區(qū)的回收(永久代)

方法區(qū)垃圾收集的效率是比較低的而涉,收集的內(nèi)容主要有兩部分:廢棄的常量和無用的類

無用的類需要符合三個條件:

  • 該類的所有實(shí)例都已經(jīng)被回收
  • 加載該類的ClassLoader已經(jīng)被回收
  • 該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用著瓶,無法在任何地方通過反射訪問該類的方法

垃圾收集算法

標(biāo)記-清除算法

標(biāo)記-清除算法分兩階段:首先標(biāo)記所有需要回收的對象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象

標(biāo)記-清除算法的不足:第一兩個過程的效率都不高啼县;第二會產(chǎn)生內(nèi)存碎片

復(fù)制算法

復(fù)制算法是把內(nèi)存分成相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊內(nèi)存用完了坛缕,就將還存活的對象復(fù)制到另外一塊內(nèi)存上,然后將當(dāng)前這塊內(nèi)存一次清理掉卷胯。

復(fù)制算法的好處就是實(shí)現(xiàn)簡單,效率高威酒,不足之處就是浪費(fèi)內(nèi)存空間窑睁。

如果對象的存活率較高,復(fù)制操作的效率會比較低葵孤,所以復(fù)制算法適合對象存活率較低的情況担钮。

現(xiàn)在商業(yè)虛擬機(jī)及HotSpot虛擬機(jī)都采用這種算法來回收新生代。新生代的內(nèi)存空間會分為Eden尤仍、From Survivor和To Survivor三塊裳朋,每次使用Eden空間和From Survivor空間。當(dāng)進(jìn)行回收時吓著,將Eden空間及From Survivor空間存活的對象復(fù)制到To Survivor,然后清理Eden和From Survivor空間。

標(biāo)記-整理算法

標(biāo)記-整理算法分兩階段:首先標(biāo)記需要回收的對象送挑,然后讓所有存活對象往一端移動绑莺,然后直接清理端邊界以外的內(nèi)存。

標(biāo)記-整理算法適合對象存活率較高的情況惕耕,并且不會產(chǎn)生內(nèi)存碎片

分代收集算法(Generational Collection)

一般把Java堆分成新生代和老年代:

  • 新生代的對象存活率較低纺裁,使用復(fù)制算法

  • 老年代的對象存活率較高,使用“標(biāo)記-清除”或“標(biāo)記-整理”算法

HotSpot的算法實(shí)現(xiàn)

枚舉根節(jié)點(diǎn)

必須確彼九欤可達(dá)性分析執(zhí)行的效率:HotSpot虛擬機(jī)中使用一組OopMap(Ordinary Object Pointer)普通對象指針存放對象的引用欺缘。在類加載完成的時候,HotSpot就把對象內(nèi)什么偏移量是什么類型的數(shù)據(jù)計(jì)算出來挤安,在JIT編譯過程中谚殊,也會在特定的位置記錄下棧和寄存器中哪些位置是引用。

必須確备蛲可達(dá)性分析的執(zhí)行時在“一致性”的快照中進(jìn)行:在整個分析期間整個執(zhí)行系統(tǒng)看起來像被凍結(jié)在某個時間點(diǎn)上(Stop The World)嫩絮。

安全點(diǎn)(Safepoint)

安全點(diǎn)是HotSpot生成OopMap的位置,也是程序停下來GC的地方围肥。安全點(diǎn)的選定基本是以程序“是否具有讓程序長時間執(zhí)行的特征”為標(biāo)準(zhǔn)進(jìn)行選定剿干,“長時間執(zhí)行”的最明顯特征就是指令序列復(fù)用,例如方法的調(diào)用穆刻、循環(huán)跳轉(zhuǎn)置尔、異常跳轉(zhuǎn)等。

如果在GC時讓所有的線程跑到安全點(diǎn)再停頓:

  • 搶先式中斷:首先讓所有線程中斷氢伟,如果發(fā)現(xiàn)有線程中斷的地方不在安全點(diǎn)上榜轿,就恢復(fù)線程幽歼,讓它“跑”到安全點(diǎn)。目前基本沒有虛擬機(jī)才用這種方式
  • 主動式中斷:當(dāng)GC需要中斷線程時差导,不直接對線程操作试躏,僅僅簡單地設(shè)置一個標(biāo)志,各個線程執(zhí)行時主動輪詢這個標(biāo)志设褐,發(fā)現(xiàn)中斷標(biāo)識為真時就自己中斷掛起颠蕴。輪詢標(biāo)志的地方和安全點(diǎn)是重合的,另外再加上創(chuàng)建對象需要分配內(nèi)存的地方助析。

安全區(qū)域(Safe Region)

安全區(qū)域是安全點(diǎn)的擴(kuò)展犀被,解決了程序在“不執(zhí)行”時候的GC安全問題:如果程序處在Sleep或Blocked的狀態(tài),這個時候線程無法響應(yīng)JVM的中斷請求外冀,無法走到安全點(diǎn)寡键。

在線程執(zhí)行到Safe Region中的代碼時,首先標(biāo)識自己已經(jīng)進(jìn)入了Safe Region雪隧。這樣西轩,當(dāng)這段時間內(nèi)發(fā)生GC時,就不用管標(biāo)識自己為Safe Region狀態(tài)的線程了脑沿。在線程要離開Safe Region時藕畔,它要檢查系統(tǒng)是否已經(jīng)完成根節(jié)點(diǎn)枚舉(整個GC過程),如果完成庄拇,線程就繼續(xù)執(zhí)行將注服,否則它就必須等待直到收到可以安全離開Safe Region的信號為止。

垃圾收集器

  • 并行(Parallel):指多條垃圾收集線程并行工作措近,但此時用戶線程仍然處于等待情況
  • 并發(fā)(Concurrent):指用戶線程與垃圾收集線程同時執(zhí)行(但不一定并行溶弟,可能會交替執(zhí)行),用戶程序繼續(xù)瞭郑,而垃圾收集程序運(yùn)行于另外一個CPU上

Serail辜御、ParNew、Parallel Scavenge : 復(fù)制算法

CMS:標(biāo)記-清除算法

Parallel Old屈张、Serial Old我抠、G1:標(biāo)記-整理算法

Serial 收集器

Seral 是一個單線程的收集器。它只會使用一個CPU或者一條收集線程去完成垃圾收集的工作袜茧,在它進(jìn)行垃圾收集時菜拓,必須暫停其他所有的工作線程。

多CPU的情況下笛厦,效率比較低纳鼎。但對于單CPU的情況下,因?yàn)槭菃尉€程,減少了線程之間的交互贱鄙,專注垃圾收集的工作劝贸,效率會比較高,適用于Client模式下的虛擬機(jī)逗宁。

ParNew 收集器

ParNew是Serial的多線程版映九。除了使用多條線程進(jìn)行垃圾收集之外,其余行為都和Serial一樣瞎颗。它默認(rèn)開啟的收集線程和CPU的數(shù)量相同件甥,在CPU非常多的情況下,可以通過參數(shù)-XX:ParallelGCThreads限制垃圾收集的線程數(shù)哼拔。ParNew是目前唯一能和CMS配合工作的收集器引有。

在單CPU的情況下,因?yàn)榇嬖诰€程交互的開銷倦逐,ParNew的性能不一定比Serial收集器的好譬正。不過在當(dāng)前CPU動輒4核的情況下,它是許多運(yùn)行在Server模式下的虛擬機(jī)中首選的新生代收集器檬姥。

使用-XX:UserConcMarkSweepGC或者-XX:UserParNewGC選項(xiàng)來指定

Parallel Scavenge 收集器

Parallel Scavenge 是一個并行的多線程收集器曾我,它的目標(biāo)是達(dá)到一個可控的吞吐量(Throughput),因此也被稱為“吞吐量優(yōu)先”收集器健民。

吞吐量就是CPU用于運(yùn)行用戶代碼的時間與CPU總消耗時間的比值您单,吞吐量=運(yùn)行用戶代碼時間/(運(yùn)行用戶代碼時間+垃圾收集時間)。

停頓時間越短就越適合需要與用戶交互的程序荞雏,良好的響應(yīng)速度能提升用戶的體驗(yàn),而高吞吐量則可以高效地利用CPU時間平酿,盡快地完成程序的運(yùn)算任務(wù)凤优,主要適合后臺運(yùn)算而不需要太多交互的任務(wù)。

Parallel Scavenge收集器提供兩個參數(shù)用于精確控制吞吐量:

  • -XX:MaxGCPauseMillis:最大的GC停頓時間蜈彼。允許一個大于0的毫秒數(shù)筑辨,收集器盡可能保證內(nèi)存回收花費(fèi)的時間不超過設(shè)定值。但這并不意味這個值越小越好幸逆,因?yàn)镚C停頓時間縮短是以犧牲吞吐量和新生代空間來換取的棍辕。因?yàn)槭占?00M的新生代肯定比收集500M的新生代快,原來10秒收集一次还绘,每次停頓100毫秒楚昭,現(xiàn)在5秒收集一次,每次停頓70毫米拍顷,停頓時間是下降了抚太,但吞吐量也降低了。
  • -XX:GCTimeRatio:垃圾收集時間戰(zhàn)總時間的比率,相當(dāng)于是吞吐量的倒數(shù)尿贫。如果把此參數(shù)設(shè)置為19电媳,那允許的最大GC時間就占5%(1/(1+19)),默認(rèn)值是99,就是允許最大1%(1/(1+99))的垃圾收集時間庆亡。

GC自適應(yīng)調(diào)節(jié)策略(GC Ergonomics):-XX:UseAdaptiveSizePolicy 當(dāng)這個參數(shù)打開匾乓,就不需要手工指定新生代的大小(-Xmn)又谋、Eden與Survivor的比例(-XX:SurvivorRatio)拼缝、晉升老年代對象年齡(-XX:PretenureSizeThreshold)等細(xì)節(jié)參數(shù),虛擬機(jī)會根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控搂根,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或者最大的吞吐量珍促。

Serial Old 收集器

Serial Old 是Serail收集器的老年代版本,適合于給Client模式下的虛擬機(jī)使用剩愧。如果在Server模式下:一種用途是在JDK1.5及之前的版本和Parallel Scavenge搭配使用猪叙;另一種用途就是作為CMS收集器的后備預(yù)案,在并發(fā)收集發(fā)生Concurrent Mode Failure時使用

Parallel Old 收集器

Parallel Old是Parallel Scavenge收集器的老年代版本仁卷,使用多線程和“標(biāo)記-整理”算法穴翩,在JDK1.6中才開始提供。

CMS(Concurrent Mark Sweep) 收集器

CMS 收集器是一種以獲取最短回收停頓時間為目標(biāo)的收集器锦积。目前大部分應(yīng)用在互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端上芒帕,這類應(yīng)用尤其重視服務(wù)的響應(yīng)速度,希望系統(tǒng)的停頓時間最短丰介,以給用戶帶來較好的體驗(yàn)背蟆。

CMS收集器基于“標(biāo)記-清除”算法實(shí)現(xiàn),整個過程分為4步驟:

  • 初始標(biāo)記(CMS inital mark) 需要“Stop The World”哮幢,僅僅就只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象
  • 并發(fā)標(biāo)記(CMS Concurrent mark) GC Roots枚舉階段
  • 重新標(biāo)記(CMS remark) 需要“Stop The World”带膀,該階段是修正并發(fā)標(biāo)記期間因?yàn)橛脩艟€程繼續(xù)運(yùn)作導(dǎo)致標(biāo)記產(chǎn)生變動的那部分對象的標(biāo)記記錄
  • 并發(fā)清除(CMS concurrent sweep)

CMS收集器提供了并發(fā)收集、低停頓等優(yōu)點(diǎn)橙垢,但也有很明顯的缺點(diǎn):

1垛叨、CMS收集器對CPU資源敏感:CMS默認(rèn)啟動的回收線程數(shù)是(CPU數(shù)量+3)/4,也就是當(dāng)CPU在4個以上時柜某,并發(fā)回收時垃圾收集線程占不少于25%的CPU資源嗽元,并且隨著CPU數(shù)量的增加而降低。但如果CPU少于4個時(比如2個時)喂击,CMS對用戶程序的影響就會比較大剂癌。

2、CMS收集器無法處理浮動(Float Garbage)垃圾,可能出現(xiàn)“Concurrent Mode Failure”失敗導(dǎo)致發(fā)生另外一次Full GC翰绊。

  • CMS在并發(fā)清理階段用戶線性還在運(yùn)行珍手,伴隨用戶線程的運(yùn)行自然就會有新的垃圾不斷產(chǎn)生,CMS無法在當(dāng)次處理這些垃圾,只能在下次GC時處理琳要,這些垃圾稱為“浮動垃圾”寡具。

  • 由于用戶線程在GC的時候還在運(yùn)行,所以必須預(yù)留足夠的內(nèi)存空間給用戶線程稚补,當(dāng)預(yù)留的內(nèi)存空間無法滿足用戶線程時童叠,就會出現(xiàn)“Concurrent Mode Failure”失敗,CMS啟動后備方案:臨時啟動Serial Old進(jìn)行老年代的垃圾收集课幕,此時厦坛,停頓時間就會比較長。CMS收集器通過參數(shù)-XX:CMSInitiatingOccupancyFraction 來激活自己乍惊,JDK1.5默認(rèn)設(shè)置當(dāng)老年代使用68%觸發(fā)CMS收集器杜秸,JDK1.6中,此值為92%润绎。

3撬碟、CMS收集器采用“標(biāo)記-清除”算法,會產(chǎn)生大量的空間碎片莉撇。會導(dǎo)致老年代還有很多空間呢蛤,因?yàn)檎也坏阶銐虼蟮倪B續(xù)空間不得不進(jìn)行Full GC。

  • -XX:UseCMSCompactAtFullCollection:開關(guān)參數(shù)棍郎,默認(rèn)是開啟其障,用于在CMS收集器頂不住需要進(jìn)行Full GC是開啟內(nèi)存碎片整理,這樣會導(dǎo)致停頓時間變長
  • -XX:CMSFullGCsBeforeCompaction:這個參數(shù)用于設(shè)置執(zhí)行多少次不壓縮的Full GC后涂佃,跟著來一次帶壓縮的励翼。默認(rèn)為0,表示每次進(jìn)入Full GC時都進(jìn)行內(nèi)存碎片整理

G1 收集器

G1是一款面向服務(wù)端應(yīng)用的垃圾收集器辜荠,它有以下幾個特點(diǎn):

  • 并行與并發(fā):G1重復(fù)利用硬件資源優(yōu)勢汽抚,使用多個CPU核心來縮短Stop-The-World停頓時間
  • 分代收集:分代的概念依然在G1中保留
  • 空間整合:G1從整體上看采用了“標(biāo)記-整理”的算法,局部(連個Region)來看是基于復(fù)制算法侨拦,這樣保證了G1運(yùn)行期間不會產(chǎn)生內(nèi)存碎片
  • 可預(yù)測停頓:G1除了最求低停頓外,還能建立可預(yù)測的停頓模型辐宾。能讓使用明確指定在一個長度為M毫秒的時間片段內(nèi)狱从,消耗在垃圾收集上的時間不超過N毫秒。

G1收集器Java堆的布局:將整Java堆劃分多個大小相等的獨(dú)立區(qū)域(Region),雖然還保留有新生代和老年代的概念叠纹,但新生代和老年代不再是物理隔離的了季研,他們都是一部分Region(不需要連續(xù))的集合。

G1創(chuàng)建可預(yù)測的停頓時間模型:G1跟蹤各個Region里面的垃圾堆積的價值大杏臁(回收所獲得的空間大小及回收所需要時間的經(jīng)驗(yàn)值)与涡,在后臺維護(hù)一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先回收價值最大的Region驼卖,這也是Garbage-First名稱的來由氨肌。

G1如何避免全堆掃描:使用Remembered Set來避免全堆掃描。G1中的每個Region都有一個與之對應(yīng)的Remembered Set,虛擬機(jī)發(fā)現(xiàn)程序在對Reference類型的數(shù)據(jù)進(jìn)行寫操作時酌畜,會產(chǎn)生一個Write Barrier暫停中斷寫操作怎囚,檢查Reference引用的對象是否處于不同的Region之中(在分代的例子中就是是否有老年代的對象引用了新生代的對象)。如果是桥胞,便通過CardTable把相關(guān)引用信息記錄到被引用對象所屬的Region的Remembered Set之中恳守。當(dāng)進(jìn)行內(nèi)存回收時,在GC根節(jié)點(diǎn)的枚舉范圍假如Remembered Set即可贩虾。

G1收集器的回收步驟可分為以下步驟:

  • 初始標(biāo)記(Initial Marking):僅僅標(biāo)記GC Roots能直接關(guān)聯(lián)到的對象催烘,并且修改TAMS(Next Top at Mark Start)的值,讓下一個階段用戶程序并發(fā)運(yùn)行時缎罢,能在正確的Region中創(chuàng)建新對象伊群,這個階段需要停頓用戶線程。
  • 并發(fā)標(biāo)記(Concurrent Marking):從堆的GC RootS開始對堆的對象進(jìn)行可達(dá)性分析屁使,找出存活的對象在岂,這個階段用戶線程可并發(fā)執(zhí)行
  • 最終標(biāo)記(Final Marking):修正由于并發(fā)階段用戶線程執(zhí)行運(yùn)行導(dǎo)致標(biāo)志產(chǎn)生變動的那一部分標(biāo)記記錄。虛擬機(jī)將這段時間對象變化記錄在線程Remembered Set Logs里面蛮寂,最終標(biāo)記階段需要把Remembered Set Logs的數(shù)據(jù)合并到Remembered Set中蔽午。這階段需要停頓用戶線程,當(dāng)標(biāo)記線程可以并行執(zhí)行酬蹋。
  • 篩選回收(Live Data Counting and Evacuating ):首先對各個Region的回收價值和成本進(jìn)行排序及老,根據(jù)用戶所期望的GC停頓時間來指定回收計(jì)劃。

內(nèi)存的分配與回收策略

對象優(yōu)先在Eden分配

  • 新生代GC(Minor GC):指發(fā)生在新生代的垃圾收集動作范抓,因?yàn)镴ava對象大多數(shù)具備朝生夕滅的特征骄恶,所以Minor GC非常頻繁,一般回收速度也很快匕垫。
  • 老年代(Major GC/Full GC): 指發(fā)生在老年代的GC僧鲁,出現(xiàn)了Major GC,經(jīng)常會伴隨至少一次的Minor GC(Parallel Scavenge收集器例外)象泵,Major GC 一般比Minor GC慢10倍以上寞秃。

大對象直接進(jìn)入老年代

大對象:需要大量連續(xù)空間的Java對象,比如:長的字符串和數(shù)組偶惠。對大對象春寿,我們可以通過參數(shù)設(shè)置,讓它直接在老年代分配忽孽,從而避免頻繁的Minor GC绑改。

-XX:PretenureSizeThreshold:可以讓對象直接在老年代分配

長期存活的對象進(jìn)入老年代

對象年齡技術(shù)器:虛擬機(jī)給每個對象定義了一個對象年齡計(jì)數(shù)器谢床。如果對象在Eden出生并經(jīng)過第一次Minor GC后仍然存活,并且能被Survivor容納的話厘线,將被移動到Survivor空間识腿,并且對象的年齡設(shè)定為1。對象在Survivor區(qū)每熬過一次Minor GC皆的,年齡就增加1覆履。當(dāng)它的年齡增加到一定程度(默認(rèn)為15),就將會晉升到老年代费薄。對象晉升到老年代的閥值硝全,可以通過參數(shù)-XX:MaxTenuringThreshold設(shè)置。

動態(tài)對象年齡判斷

虛擬機(jī)并不是永遠(yuǎn)要求對象的年齡必須達(dá)到MaxTenuringThreshold才能晉升老年代楞抡。如果在Survivor空間中相同年齡的所有對象大小的總和大于Survivor空間的一半伟众,年齡大于或者等于該年齡的對象就可以直接進(jìn)入老年代。

空間分配擔(dān)保

在發(fā)生Minor GC之前召廷,虛擬機(jī)會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間凳厢,如果條件成立,那么Minor GC可以確保是安全的竞慢。如果不成立先紫,則虛擬機(jī)會查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗。如果允許筹煮,那么繼續(xù)檢查老年代最大可用連續(xù)空間是否大于歷次晉升老年代對象的平均大小遮精,如果大于,將嘗試進(jìn)行一次Minor GC败潦;如果小于本冲,或者HandlePromotionFailure設(shè)置不允許,需要進(jìn)行一次Full GC劫扒。

但是檬洞,在JDK1.6 Update24之后,規(guī)則變?yōu)橹灰夏甏倪B續(xù)空間大于新生代對象總大小或者歷次晉升的平均大小就會進(jìn)行Minor GC沟饥,否則將進(jìn)行Full GC添怔。

理解GC日志

打印GC日志:-XX:PrintGCDetails

GC日志 待補(bǔ)充……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贤旷,隨后出現(xiàn)的幾起案子广料,更是在濱河造成了極大的恐慌,老刑警劉巖遮晚,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件性昭,死亡現(xiàn)場離奇詭異拦止,居然都是意外死亡县遣,警方通過查閱死者的電腦和手機(jī)糜颠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萧求,“玉大人其兴,你說我怎么就攤上這事】湔” “怎么了元旬?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長守问。 經(jīng)常有香客問我匀归,道長,這世上最難降的妖魔是什么耗帕? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任穆端,我火速辦了婚禮,結(jié)果婚禮上仿便,老公的妹妹穿的比我還像新娘体啰。我一直安慰自己,他們只是感情好嗽仪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布荒勇。 她就那樣靜靜地躺著,像睡著了一般闻坚。 火紅的嫁衣襯著肌膚如雪沽翔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天鲤氢,我揣著相機(jī)與錄音搀擂,去河邊找鬼。 笑死卷玉,一個胖子當(dāng)著我的面吹牛哨颂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播相种,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼威恼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寝并?” 一聲冷哼從身側(cè)響起箫措,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衬潦,沒想到半個月后斤蔓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镀岛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年弦牡,在試婚紗的時候發(fā)現(xiàn)自己被綠了友驮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡驾锰,死狀恐怖卸留,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椭豫,我是刑警寧澤耻瑟,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站赏酥,受9級特大地震影響喳整,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裸扶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一算柳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姓言,春花似錦瞬项、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至餐塘,卻和暖如春妥衣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戒傻。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工税手, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人需纳。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓芦倒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親不翩。 傳聞我的和親對象是個殘疾皇子兵扬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

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