24. java虛擬機總結-垃圾回收器 (七)

關于 JVM 垃圾回收機制面試中主要涉及這三個考題:

    JVM 中有哪些垃圾回收算法鹿驼?它們各自有什么優(yōu)劣欲低?

    CMS 垃圾回收器是怎么工作的?有哪些階段?

    服務卡頓的元兇到底是誰?

JVM 是有專門的線程在做這件事情版述。當我們的內(nèi)存空間達到一定條件時娇澎,會自動觸發(fā)。這個過程就叫作 GC跳昼,負責 GC 的組件碌廓,就叫作垃圾回收器机蔗。

JVM 規(guī)范并沒有規(guī)定垃圾回收器怎么實現(xiàn)闰非,它只需要保證不要把正在使用的對象給回收掉就可以膘格。在現(xiàn)在的服務器環(huán)境中,經(jīng)常被使用的垃圾回收器有`CMS 和 G1河胎,但 JVM 還有其他幾個常見的垃圾回收器闯袒。

按照語義上的意思,垃圾回收游岳,首先就需要找到這些垃圾政敢,然后回收掉。但是 GC 過程正好相反胚迫,它是先找到活躍的對象喷户,然后把其他不活躍的對象判定為垃圾,然后刪除访锻。所以垃圾回收只與活躍的對象有關褪尝,和堆的大小無關。

首先介紹幾種非常重要的回收算法

標記(Mark)

根據(jù) GC Roots 遍歷所有的可達對象期犬,這個過程河哑,就叫作標記。


標記.png

如圖所示龟虎,圓圈代表的是對象璃谨。綠色的代表 GC Roots,紅色的代表可以追溯到的對象鲤妥〖淹蹋可以看到標記之后,仍然有多個灰色的圓圈棉安,它們都是被回收的對象底扳。

清除(Sweep)

清除階段就是把未被標記的對象回收掉。

清除.png

這種簡單的清除方式贡耽,有一個明顯的弊端衷模,那就是內(nèi)存碎片問題。比如我申請了 1k蒲赂、2k阱冶、3k、4k凳宙、5k 的內(nèi)存熙揍。
申請內(nèi)存.jpg

由于某種原因 职祷,2k 和 4k 的內(nèi)存氏涩,我不再使用届囚,就需要交給垃圾回收器回收。
清理內(nèi)存.jpg

這個時候是尖,我應該有足足 6k 的空閑空間意系。接下來,我打算申請另外一個 5k 的空間饺汹,結果系統(tǒng)告訴我內(nèi)存不足了蛔添。系統(tǒng)運行時間越長,這種碎片就越多兜辞。

在很久之前使用 Windows 系統(tǒng)時迎瞧,有一個非常有用的功能,就是內(nèi)存整理和磁盤整理逸吵,運行之后有可能會顯著提高系統(tǒng)性能凶硅。這個出發(fā)點是一樣的。

復制(Copy)

解決碎片問題只有進行內(nèi)存整理扫皱。比較好的思路可以完成這個整理過程足绅,就是提供一個對等的內(nèi)存空間,將存活的對象復制過去韩脑,然后清除原內(nèi)存空間氢妈。復制算法是非常有效的。比如:HashMap 的擴容也是使用同樣的思路

整個過程如圖所示:

復制.jpg

它的弊端也非常明顯段多。它浪費了幾乎一半的內(nèi)存空間來做這個事情首量。

整理(Compact)

不用分配一個對等的額外空間,也是可以完成內(nèi)存的整理工作衩匣。
你可以把內(nèi)存想象成一個非常大的數(shù)組蕾总,根據(jù)隨機的 index 刪除了一些數(shù)據(jù)。那么對整個數(shù)組的清理琅捏,其實是不需要另外一個數(shù)組來進行支持的生百,繼續(xù)使用這個數(shù)組就可以實現(xiàn)。
它的主要思路柄延,就是移動所有存活的對象蚀浆,且按照內(nèi)存地址順序依次排列,然后將末端內(nèi)存地址以后的內(nèi)存全部回收搜吧。

整理.png

從效率上來說市俊,一般整理算法是要低于復制算法的。

這幾種算法的特點

    復制算法(Copy)復制算法是所有算法里面效率最高的滤奈,缺點是會造成一定的空間浪費摆昧。
    標記-清除(Mark-Sweep)效率一般,缺點是會造成內(nèi)存碎片問題蜒程。
    標記-整理(Mark-Compact)效率比前兩者要差绅你,但沒有空間浪費伺帘,也消除了內(nèi)存碎片問題。

分代

JVM 是計算節(jié)點忌锯,而不是存儲節(jié)點伪嫁。最理想的情況,就是對象在用完之后偶垮,它的生命周期立馬就結束了张咳。而那些被頻繁訪問的資源,我們希望它能夠常駐在內(nèi)存里似舵。

研究表明脚猾,大部分對象,可以分為兩類:

    大部分對象的生命周期都很短砚哗;
    其他對象則很可能會存活很長時間婚陪。

大部分死的快,其他的活的長频祝。這個假設我們稱之為弱代假設(weak generational hypothesis)泌参。


分代.jpg

從圖中可以看到,大部分對象是朝生夕滅的常空,其他的則活的很久沽一。

現(xiàn)在的垃圾回收器,都會在物理上或者邏輯上漓糙,把這兩類對象進行區(qū)分铣缠。我們把死的快的對象所占的區(qū)域,叫作年輕代(Young generation)昆禽。把其他活的長的對象所占的區(qū)域蝗蛙,叫作老年代(Old generation)。


年輕代老年代.jpg
年輕代

年輕代使用的垃圾回收算法是復制算法醉鳖。因為年輕代發(fā)生 GC 后捡硅,只會有非常少的對象存活,復制這部分對象是非常高效的盗棵。

我們前面也了解到復制算法會造成一定的空間浪費壮韭,所以年輕代中間也會分很多區(qū)域。


年輕代分區(qū).jpg

如圖所示纹因,年輕代分為:一個伊甸園空間(Eden )喷屋,兩個幸存者空間(Survivor )。

當年輕代中的 Eden 區(qū)分配滿的時候瞭恰,就會觸發(fā)年輕代的 GC(Minor GC)屯曹。具體過程如下:

在 Eden 區(qū)執(zhí)行了第一次 GC 之后,存活的對象會被移動到其中一個 Survivor 分區(qū)(以下簡稱from);

Eden 區(qū)再次 GC恶耽,這時會采用復制算法僵井,將 Eden 和 from 區(qū)一起清理。存活的對象會被復制到 to 區(qū)驳棱;接下來,只需要清空 from 區(qū)就可以了农曲。

所以在這個過程中社搅,總會有一個 Survivor 分區(qū)是空置的。Eden乳规、from形葬、to 的默認比例是 8:1:1,所以只會造成 10% 的空間浪費暮的。這個比例笙以,是由參數(shù) -XX:SurvivorRatio進行配置的(默認為 8)。

一般情況下冻辩,我們只需要了解到這一層面就 OK 了猖腕。但是在平常的面試中,還有一個點會經(jīng)常提到恨闪,雖然頻率不太高倘感,它就是 TLAB,我們在這里也簡單介紹一下咙咽。
這個道理和 Java 語言中的 ThreadLocal 類似老玛,避免了對公共區(qū)的操作,以及一些鎖競爭钧敞。
TLAB 的全稱是 Thread Local Allocation Buffer蜡豹,JVM 默認給每個線程開辟一個 buffer 區(qū)域,用來加速對象分配溉苛。這個 buffer 就放在 Eden 區(qū)中镜廉。

對象的分配優(yōu)先在 TLAB上 分配,但 TLAB 通常都很小愚战,所以對象相對比較大的時候桨吊,會在 Eden 區(qū)的共享區(qū)域進行分配。

TLAB 是一種優(yōu)化技術凤巨,類似的優(yōu)化還有對象的棧上分配(這可以引出逃逸分析的話題视乐,默認開啟)。這屬于非常細節(jié)的優(yōu)化敢茁,不做過多介紹佑淀,但偶爾面試也會被問到。

Java對象分配流程

截屏2021-07-21 上午7.58.20.png

棧上分配

將線程私有的對象打散分配在棧上,優(yōu)點是可以在函數(shù)調(diào)用結束后自行銷毀對象彰檬,不需要垃圾回收器的介入伸刃,并且棧上分配速度快谎砾,提高系統(tǒng)性能,但缺點是椗趼空間小景图,對于大對象無法實現(xiàn)棧上分配。棧上分配的前提條件是開啟了逃逸分析(-XX:+DoEscapeAnalysis):判斷對象的作用域是否超出函數(shù)體,只有作用域沒有超出函數(shù)體的對象才能棧上分配碉哑。如下挚币,user的作用域超出了函數(shù)setUser的范圍,是逃逸對象,不能進行棧上分配扣典。棧上分配還有一個前提是開啟標量替換 (-XX:-EliminateAllocations),逃逸分析和標量替換都是jvm默認開啟的

標量替換:簡單地說妆毕,就是用標量替換聚合量。標量是指不可分割的量贮尖,如java中基本數(shù)據(jù)類型和reference類型笛粘,相對的一個數(shù)據(jù)可以繼續(xù)分解,稱為聚合量湿硝;如果把一個對象拆散薪前,將其成員變量恢復到基本類型來訪問就叫做標量替換;如果逃逸分析發(fā)現(xiàn)一個對象不會被外部訪問关斜,并且該對象可以被拆散序六,那么經(jīng)過優(yōu)化之后,并不直接生成該對象蚤吹,而是在棧上創(chuàng)建若干個成員變量例诀;

private User user;
public void setUser(){
    user = new User();
    user.setId(1);
    user.setName("blueStarWei");
}

TLAB 分配

Thread Local Allocation Buffer, 線程本地分配緩存。一塊線程專用的內(nèi)存分配區(qū)域裁着。TLAB占用的是eden區(qū)的空間(注意是堆上)繁涂。在TLAB啟用的情況下(默認開啟),JVM會為每一個線程分配一塊TLAB區(qū)域二驰。

優(yōu)點是可以加速對象的分配扔罪。因為TLAB是線程專有區(qū)域,會減少線程同步操作桶雀,使分配的效率提高矿酵。考慮到對象分配幾乎是Java中最常用的操作矗积,因此JVM使用了TLAB這樣的線程專有區(qū)域來避免多線程沖突全肮,提高對象分配的效率。

老年代

老年代一般使用“標記-清除”棘捣、“標記-整理”算法辜腺,因為老年代的對象存活率一般是比較高的,空間又比較大,拷貝起來并不劃算评疗,還不如采取就地收集的方式测砂。

那么,對象是怎么進入老年代的呢百匆?有多種途徑砌些。

1.提升(Promotion)

如果對象夠老,會通過“提升”進入老年代加匈。
關于對象老不老存璃,是通過它的年齡(age)來判斷的。每當發(fā)生一次 Minor GC矩动,存活下來的對象年齡都會加 1。直到達到一定的閾值释漆,就會把這些“老頑固”給提升到老年代
這些對象如果變的不可達悲没,直到老年代發(fā)生 GC 的時候,才會被清理掉男图。
這個閾值示姿,可以通過參數(shù) ‐XX:+MaxTenuringThreshold 進行配置,最大值是 15逊笆,因為它是用 4bit 存儲的(所以網(wǎng)絡上那些要把這個值調(diào)的很大的文章栈戳,是沒有什么根據(jù)的)。

2.分配擔保

看一下年輕代的圖难裆,每次存活的對象子檀,都會放入其中一個幸存區(qū),這個區(qū)域默認的比例是 10%乃戈。但是我們無法保證每次存活的對象都小于 10%褂痰,當 Survivor 空間不夠,就需要依賴其他內(nèi)存(指老年代)進行分配擔保症虑。這個時候缩歪,對象也會直接在老年代上分配。

3.大對象直接在老年代分配

超出某個大小的對象將直接在老年代分配谍憔。這個值是通過參數(shù)-XX:PretenureSizeThreshold進行配置的匪蝙。默認為 0,意思是全部首選 Eden 區(qū)進行分配习贫。

4.動態(tài)對象年齡判定

有的垃圾回收算法逛球,并不要求 age 必須達到 15 才能晉升到老年代,它會使用一些動態(tài)的計算方法苫昌。比如需忿,如果幸存區(qū)中相同年齡對象大小的和,大于幸存區(qū)的一半,大于或等于 age 的對象將會直接進入老年代屋厘。

這些動態(tài)判定一般不受外部控制涕烧,我們知道有這么回事就可以了。通過下圖可以看一下一個對象的分配邏輯汗洒。下圖中的SLAB改成TLAB


對象分配區(qū)域.jpg

卡片標記(card marking)

你可以看到议纯,對象的引用關系是一個巨大的網(wǎng)狀。有的對象可能在 Eden 區(qū)溢谤,有的可能在老年代瞻凤,那么這種跨代的引用是如何處理的呢?由于 Minor GC 是單獨發(fā)生的世杀,如果一個老年代的對象引用了它阀参,如何確保能夠讓年輕代的對象存活呢?

老年代是被分成眾多的卡頁(card page)的(一般數(shù)量是 2 的次冪)瞻坝。

卡表(Card Table)就是用于標記卡頁狀態(tài)的一個集合蛛壳,每個卡表項對應一個卡頁。

如果年輕代有對象分配所刀,而且老年代有對象指向這個新對象衙荐, 那么這個老年代對象所對應內(nèi)存的卡頁,就會標識為 dirty浮创,卡表只需要非常小的存儲空間就可以保留這些狀態(tài)忧吟。

垃圾回收時,就可以先讀這個卡表斩披,進行快速判斷溜族。

HotSpot 垃圾回收器

接下來介紹 HotSpot 的幾個垃圾回收器,每種回收器都有各自的特點垦沉。我們在平常的 GC 優(yōu)化時斩祭,一定要搞清楚現(xiàn)在用的是哪種垃圾回收器。

在此之前乡话,我們把上面的分代垃圾回收整理成一張大圖摧玫,在介紹下面的收集器時,你可以對應一下它們的位置绑青。


分代垃圾回收.jpg

年輕代垃圾回收器

(1)Serial 垃圾收集器

處理 GC 的只有一條線程诬像,并且在垃圾回收的過程中暫停一切用戶線程。
最簡單的垃圾回收器闸婴,因為簡單坏挠,所以高效,它通常用在客戶端應用上邪乍。因為客戶端應用不會頻繁創(chuàng)建很多對象降狠,用戶也不會感覺出明顯的卡頓对竣。相反,它使用的資源更少榜配,也更輕量級否纬。

(2)ParNew 垃圾收集器

ParNew 是 Serial 的多線程版本。由多條 GC 線程并行地進行垃圾清理蛋褥。清理過程依然要停止用戶線程临燃。
ParNew 追求“低停頓時間”,與 Serial 唯一區(qū)別就是使用了多線程進行垃圾收集烙心,在多 CPU 環(huán)境下性能比 Serial 會有一定程度的提升膜廊;但線程切換需要額外的開銷,因此在單 CPU 環(huán)境中表現(xiàn)不如 Serial淫茵。

(3)Parallel Scavenge 垃圾收集器

另一個多線程版本的垃圾回收器爪瓜。它與 ParNew 的主要區(qū)別是:
Parallel Scavenge:追求 CPU 吞吐量,能夠在較短時間內(nèi)完成指定任務匙瘪,適合沒有交互的后臺計算铆铆。弱交互強計算。
ParNew:追求降低用戶停頓時間辆苔,適合交互式應用算灸。強交互弱計算扼劈。

老年代垃圾收集器

(1)Serial Old 垃圾收集器

與年輕代的 Serial 垃圾收集器對應驻啤,都是單線程版本,同樣適合客戶端使用荐吵。
年輕代的 Serial骑冗,使用復制算法。
老年代的 Old Serial先煎,使用標記-整理算法贼涩。

(2)Parallel Old

Parallel Old 收集器是 Parallel Scavenge 的老年代版本,追求 CPU 吞吐量薯蝎。

(3)CMS 垃圾收集器

CMS(Concurrent Mark Sweep)收集器是以獲取最短 GC 停頓時間為目標的收集器遥倦,它在垃圾收集時使得用戶線程和 GC 線程能夠并發(fā)執(zhí)行,因此在垃圾收集過程中用戶也不會感到明顯的卡頓占锯。我們會在后面的課時詳細介紹它袒哥。

長期來看,CMS 垃圾回收器消略,是要被 G1 等垃圾回收器替換掉的堡称。在 Java8 之后,使用它將會拋出一個警告艺演。

Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was 
deprecated in version 9.0 and will likely be removed in a future release.
配置參數(shù)

除了上面幾個垃圾回收器却紧,我們還有 G1桐臊、ZGC 等更加高級的垃圾回收器,它們都有專門的配置參數(shù)來使其生效晓殊。
通過 -XX:+PrintCommandLineFlags 參數(shù)断凶,可以查看當前 Java 版本默認使用的垃圾回收器。你可以看下我的系統(tǒng)中 Java13 默認的收集器就是 G1挺物。

java  -XX:+PrintCommandLineFlags  -version
-XX:G1ConcRefinementThreads=4 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
java version "13.0.1" 2019-10-15
Java(TM) SE Runtime Environment (build 13.0.1+9)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.1+9, mixed mode, sharing)

以下是一些配置參數(shù):

-XX:+UseSerialGC 年輕代和老年代都用串行收集器

-XX:+UseParNewGC 年輕代使用 ParNew懒浮,老年代使用 Serial Old

-XX:+UseParallelGC 年輕代使用 ParallerGC,老年代使用 Serial Old

-XX:+UseParallelOldGC 新生代和老年代都使用并行收集器

-XX:+UseConcMarkSweepGC识藤,表示年輕代使用 ParNew砚著,老年代的用 CMS

-XX:+UseG1GC 使用 G1垃圾回收器

-XX:+UseZGC 使用 ZGC 垃圾回收器

為了讓你有個更好的印象,請看下圖痴昧。它們的關系還是比較復雜的稽穆。尤其注意 -XX:+UseParNewGC 這個參數(shù),已經(jīng)在 Java9 中就被拋棄了赶撰。很多程序(比如 ES)會報這個錯誤舌镶,不要感到奇怪。


垃圾回收器配置參數(shù).jpg

有這么多垃圾回收器和參數(shù)豪娜,那我們到底用什么餐胀?在什么地方優(yōu)化呢?

目前瘤载,雖然 Java 的版本比較高否灾,但是使用最多的還是 Java8。從 Java8 升級到高版本的 Java 體系鸣奔,是有一定成本的墨技,所以 CMS 垃圾回收器還會持續(xù)一段時間。

線上使用最多的垃圾回收器挎狸,就有 CMS 和 G1扣汪,以及 Java8 默認的 Parallel Scavenge。

CMS 的設置參數(shù):-XX:+UseConcMarkSweepGC锨匆。

Java8 的默認參數(shù):-XX:+UseParallelGC崭别。

Java13 的默認參數(shù):-XX:+UseG1GC。

STW(Stop the world)

你有沒有想過恐锣,如果在垃圾回收的時候(不管是標記還是整理復制)茅主,又有新的對象進入怎么辦?

為了保證程序不會亂套侥蒙,最好的辦法就是暫停用戶的一切線程暗膜。也就是在這段時間,你是不能 new 對象的鞭衩,只能等待学搜。表現(xiàn)在 JVM 上就是短暫的卡頓娃善,什么都干不了。這個頭疼的現(xiàn)象瑞佩,就叫作 Stop the world聚磺。簡稱 STW。
標記階段炬丸,大多數(shù)是要 STW 的瘫寝。如果不暫停用戶進程,在標記對象的時候稠炬,有可能有其他用戶線程會產(chǎn)生一些新的對象和引用焕阿,造成混亂。
現(xiàn)在的垃圾回收器首启,都會盡量去減少這個過程暮屡。但即使是最先進的 ZGC,也會有短暫的 STW 過程毅桃。我們要做的就是在現(xiàn)有基礎設施上褒纲,盡量減少 GC 停頓。
你可能對 STW 的影響沒有什么概念钥飞,我舉個例子來說明下莺掠。
某個高并發(fā)服務的峰值流量是 10 萬次/秒,后面有 10 臺負載均衡的機器读宙,那么每臺機器平均下來需要 1w/s彻秆。假如某臺機器在這段時間內(nèi)發(fā)生了 STW,持續(xù)了 1 秒论悴,那么本來需要 10ms 就可以返回的 1 萬個請求掖棉,需要至少等待 1 秒鐘墓律。

stw.jpg

在用戶那里的表現(xiàn)膀估,就是系統(tǒng)發(fā)生了卡頓。如果我們的 GC 非常的頻繁耻讽,這種卡頓就會特別的明顯察纯,嚴重影響用戶體驗。
雖然說 Java 為我們提供了非常棒的自動內(nèi)存管理機制针肥,但也不能濫用饼记,因為它是有 STW 硬傷的。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慰枕,一起剝皮案震驚了整個濱河市具则,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌具帮,老刑警劉巖博肋,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低斋,死亡現(xiàn)場離奇詭異,居然都是意外死亡匪凡,警方通過查閱死者的電腦和手機膊畴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門病游,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衬衬,“玉大人,你說我怎么就攤上這事。” “怎么了薛窥?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵众旗,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么郭脂? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮考抄,結果婚禮上,老公的妹妹穿的比我還像新娘贫途。我一直安慰自己吧彪,他們只是感情好,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布丢早。 她就那樣靜靜地躺著姨裸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怨酝。 梳的紋絲不亂的頭發(fā)上傀缩,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音农猬,去河邊找鬼赡艰。 笑死,一個胖子當著我的面吹牛盛险,可吹牛的內(nèi)容都是我干的瞄摊。 我是一名探鬼主播勋又,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼苦掘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了楔壤?” 一聲冷哼從身側響起鹤啡,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蹲嚣,沒想到半個月后递瑰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祟牲,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年抖部,在試婚紗的時候發(fā)現(xiàn)自己被綠了说贝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡慎颗,死狀恐怖乡恕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俯萎,我是刑警寧澤傲宜,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站夫啊,受9級特大地震影響函卒,放射性物質發(fā)生泄漏。R本人自食惡果不足惜撇眯,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一报嵌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧熊榛,春花似錦沪蓬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至营搅,卻和暖如春云挟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背转质。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工园欣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人休蟹。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓沸枯,卻偏偏與公主長得像赂弓,于是被迫代替她去往敵國和親绑榴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355