JVM—【01】認(rèn)識(shí)JVM的內(nèi)存布局和運(yùn)行時(shí)數(shù)據(jù)區(qū)

1. Java 內(nèi)存區(qū)域

1.1. JVM 內(nèi)存布局 與 運(yùn)行時(shí)數(shù)據(jù)區(qū)

JVM 內(nèi)存布局 與 運(yùn)行時(shí)數(shù)據(jù)區(qū)

1.2. Heap 堆

  • 它的唯一目的就是存放對象實(shí)例器罐;幾乎所有對象實(shí)例和數(shù)組梢为,分配內(nèi)存的區(qū)域

  • 堆內(nèi)存區(qū)域是線程共享區(qū)域轰坊,并發(fā)編程時(shí)需要考慮線程安全問題铸董。

  • 可以通過-Xms256M -Xmx1024M 設(shè)置堆內(nèi)存大小。

    注意: Java程序在運(yùn)行中衰倦,堆空間會(huì)不斷擴(kuò)容與減少袒炉,會(huì)造成系統(tǒng)壓力旁理,所以一般設(shè)置為同樣大小

    -X: 表示運(yùn)行參數(shù)

    ms: 表示memory start樊零,即起始大小

    mx: 表示memory max ,即最大內(nèi)存

  • 堆分成:新生代老年代兩大塊,如名字一樣驻襟,對象初生在新夺艰,有一例外是新生代無法接納的超大對象會(huì)在老年代創(chuàng)建

  • 新生代:對象主要分配在新生代的Eden區(qū)域

    如果在新生代分配失敗且對象是一個(gè)不含任何對象引用的大數(shù)組则涯,可被直接分配到老年代月而。

  • 可以設(shè)置分配在老年代大對象的閾值:-XX:PretenureSizeThreshold

    默認(rèn)為0不生效,意味著任何對象都會(huì)現(xiàn)在新生代分配內(nèi)存页徐。

  • 可以通過-Xmn256M 設(shè)置新生代區(qū)域大小為256M豌习。此處的大小是(eden + 2 survivor space)存谎,

  • 可以通過-XX:ServivorRatio=8 決定eden與Survivor的內(nèi)存空間占比為8:1

  • 長期存活的對象會(huì)進(jìn)入老年代:虛擬機(jī)給每個(gè)初生對象都設(shè)置了一個(gè)age,當(dāng)age>=15時(shí)就會(huì)晉升到老年代肥隆。

    當(dāng)對象出現(xiàn)在Eden既荚,經(jīng)過YGC而存活,被移到Servivor區(qū)栋艳,此時(shí)年齡變?yōu)?。每次YGC過后吸占,存活的對象age就會(huì)+1.直到被回收或者晉升老年代晴叨。

    另外如果在YGC中,要移動(dòng)的對象大于Survivor的容量上限矾屯,則直接進(jìn)入老年代兼蕊。

  • 可以設(shè)置這個(gè)age的閾值:-XX:MaxTenuringThreshold,當(dāng)age達(dá)到這個(gè)值就會(huì)進(jìn)入到老年代件蚕。

    對象的年齡并不是必須達(dá)到了MaxTenuringThreshold才晉升老年代遍略,如果在Survivor中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代骤坐。

  • 堆的OutOfMemoryRrror(簡稱OOM)如果一個(gè)新生對象或者在晉升的對象绪杏,分配的區(qū)域放不下了就會(huì)拋出OOM。

    當(dāng)一個(gè)新生對象分配給Eden時(shí)纽绍,如果Eden不夠蕾久,則會(huì)觸發(fā)Minor GC。

    當(dāng)一個(gè)對象在晉升的時(shí)候JVM發(fā)現(xiàn)內(nèi)存空間不夠拌夏,如果Survivor區(qū)中無法放下僧著,或者是超大對象的閾值超過上限,則嘗試在老年代分配障簿,如果老年代也無法分配盹愚,則觸發(fā)Full Garbage Collection(FGC),如果依然無法放下站故,則拋出OOM皆怕。

    要分析OOM我們可以使用-XX:+HeapDumpOnOutOfMemory,讓JVM打印OOM信息毅舆。


1.2. 方法區(qū)Method Area(PermGen & Metaspace)

  • 方法區(qū)主要用于存放:類元信息、字段愈腾、靜態(tài)屬性憋活、方法、常量虱黄、JIT編譯后的代碼等數(shù)據(jù)悦即。

    永久帶(PerGen)和元空間(Metaspace)分別方法區(qū)的具體實(shí)現(xiàn)。

  • PermGen是Hotspot中(<=JDK1.7)特有的區(qū)域橱乱,稱為永久代辜梳。

    在該區(qū)域,如果動(dòng)態(tài)加載過多的類泳叠,容易產(chǎn)生Perm的OOM冗美。java.lang.OutOfMemory: PermGen space 錯(cuò)誤。

    上述錯(cuò)誤可以通過設(shè)置-XX:PermSize=1024M解決析二。

    另外還可以設(shè)置-XX:MaxPermSize=1024m 最大永久代大小粉洼。 默認(rèn)是64M

    但是JDK8及以后,由于用元空間替換了PermGen所以在JDK8及以后的版本中HotSpot會(huì)提示:Java Hotspot 64Bit Server VM warning ignoring option MaxPermSize=1024M; support was removed in 8.0叶摄。

  • Metaspace是為了解決永久帶的缺陷而優(yōu)化設(shè)計(jì)的新實(shí)現(xiàn)属韧,它分配內(nèi)存在本地內(nèi)存,并且它把以前Perm中的字符串常量全部移到了堆內(nèi)存蛤吓。而其他的包括類元信息宵喂、字段、靜態(tài)屬性会傲、方法锅棕、常量等移到了元空間。其實(shí)在1.7的某個(gè)版本就已經(jīng)把字符串常量移到了堆內(nèi)存中淌山。

    大部分類元數(shù)據(jù)都在本地內(nèi)存中分配裸燎。用于描述類元數(shù)據(jù)的“klasses”已經(jīng)被移除。默認(rèn)情況下泼疑,類元數(shù)據(jù)只受可用的本地內(nèi)存限制德绿。可以通過-XX:MaxDirectMemorySize=50m設(shè)置直接內(nèi)存退渗。

    因?yàn)槭潜镜貎?nèi)存中存儲(chǔ)移稳,所以如果程序存在內(nèi)存泄露,不停的擴(kuò)展Metaspace的空間会油,會(huì)導(dǎo)致機(jī)器的內(nèi)存不足个粱,所以還是要有必要的調(diào)試和監(jiān)控。

  • Metaspace可以通過-XX:MetaspaceSize=10m-XX:MaxMetaspaceSize=50m 設(shè)置初始空間大小和最大空間


1.3. 虛擬機(jī)棧 JVM Stack

JVM Stack
  • Stack 是一個(gè)先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)翻翩。JVM中的棧是描述Java方法執(zhí)行的內(nèi)存區(qū)域都许,它是線程私有的稻薇。每個(gè)方法從開始調(diào)用到結(jié)束調(diào)用就是棧幀從入棧到出棧的結(jié)果。

  • 活動(dòng)線程中梭稚,只有棧頂?shù)臈攀怯行У模Q為當(dāng)前棧幀絮吵。正在執(zhí)行的方法稱為當(dāng)前方法弧烤,棧幀是方法運(yùn)行的基本結(jié)構(gòu)。在執(zhí)行引擎運(yùn)行時(shí)蹬敲,所有指令都只能針對當(dāng)前棧幀操作暇昂。

  • 棧幀(Stack Frame)用于存儲(chǔ)局部變量表、操作棧伴嗡、動(dòng)態(tài)鏈接急波、方法返回地址等信息。

    局部變量表:存放方法參數(shù)瘪校,編譯期可知的基本數(shù)據(jù)類型澄暮、對象引用類型(reference)和returnAddress類型(指向一條字節(jié)碼指令地址)。局部變量表所需的內(nèi)存空間是在編譯期確定阱扬,方法在局部變量表中分配多少空間是完全確定的泣懊。在運(yùn)行期間不會(huì)改變局部變量表的大小。局部變量沒有準(zhǔn)備階段麻惶,必須顯示初始化馍刮。

    操作棧是一個(gè)初始狀態(tài)為空的桶式結(jié)構(gòu)棧。方法執(zhí)行過程中窃蹋,會(huì)有各種指令往棧寫入和提取信息卡啰。JVM的執(zhí)行引擎就是基于操作棧的執(zhí)行引擎。

    動(dòng)態(tài)連接: 在Class文件中的常量持中存有大量的符號引用警没。字節(jié)碼中的方法調(diào)用指令就以常量池中指向方法的符號引用作為參數(shù)匈辱。這些符號引用一部分在類的加載階段或第一次使用的時(shí)候就轉(zhuǎn)化為了直接引用,稱為靜態(tài)鏈接杀迹。而相反的梅誓,另一部分在運(yùn)行期間轉(zhuǎn)化為直接引用,就稱為動(dòng)態(tài)鏈接佛南。

    方法返回地址:方法執(zhí)行時(shí)有兩種退出情況:一是正常退出梗掰,正常執(zhí)行到方法的返回字節(jié)碼指令;二是異常退出嗅回。兩種退出都會(huì)返回當(dāng)前被調(diào)用的位置及穗。方法退出相當(dāng)于彈出當(dāng)前棧幀,退出的方式有三種:1.返回值壓入上層調(diào)用棧幀绵载。2.異常信息拋給能夠處理的棧幀埂陆。3.PC計(jì)數(shù)器指向方法調(diào)用后的下一條指令苛白。

  • StackOverflowError:當(dāng)棧深度超過虛擬機(jī)分配給線程的棧大小時(shí)就會(huì)出現(xiàn)此error。

    最常見的就是遞歸深度超出了限定焚虱,然后拋出這個(gè)錯(cuò)誤

  • OutOfMemoryError:虛擬機(jī)擴(kuò)展時(shí)無法申請到足夠的內(nèi)存空間购裙,多線程下的內(nèi)存溢出,與椌樵裕空間是否足夠大并不存在任何聯(lián)系躏率。

    為每個(gè)線程的棧分配的內(nèi)存越大(參數(shù)-Xss),那么可以建立的線程數(shù)量就越少民鼓,建立線程時(shí)就越容易把剩下的內(nèi)存耗盡薇芝,越容易內(nèi)存溢出。

  • 可以通過-Xss2m設(shè)置棧內(nèi)存大小,設(shè)置每個(gè)線程的棧內(nèi)存丰嘉,默認(rèn)1M夯到,一般來說是不需要改的。-XX:ThreadStackSize線程堆棧大小

    如果把-Xss或者-XX:ThreadStackSize設(shè)為0饮亏,就是使用“系統(tǒng)默認(rèn)值”耍贾。而在Linux x64上HotSpot VM給Java棧定義的“系統(tǒng)默認(rèn)”大小也是1MB。

    JDK1.6以前路幸,誰設(shè)置在后面逼争,誰就生效;JDK1.6以后劝赔,-Xss設(shè)置在后面誓焦,則以-Xss為準(zhǔn),-XXThreadStackSize設(shè)置在后面着帽,則主線程-Xss為準(zhǔn)杂伟,其它線程以-XX:ThreadStackSize為準(zhǔn)。


1.4. 本地方法棧 Native Method Stacks

  • 本地方法棧為Native方法服務(wù)

  • 本地方法通過JNI(Java Native Interface)來訪問虛擬機(jī)運(yùn)行時(shí)的數(shù)據(jù)區(qū)仍翰,甚至是調(diào)用寄存器赫粥,具有和JVM相同的能力和權(quán)限。

  • 本地方法棧也會(huì)拋出:OutOfMemoryError和StackOverflowError

  • JNI

    JNI深度使用操作系統(tǒng)的特性功能予借。復(fù)用非Java代碼越平。如果大量使用其他語言來實(shí)現(xiàn)JNI,會(huì)失去跨平臺(tái)特性灵迫。

    如果對執(zhí)行效率要求高秦叛,偏底層的跨進(jìn)程的操作等,可以考慮設(shè)計(jì)為JNI調(diào)用方式瀑粥。


1.5. 程序計(jì)數(shù)器 Program Counter Register

  • 每個(gè)線程創(chuàng)建后都會(huì)產(chǎn)生自己的程序計(jì)數(shù)器和棧幀挣跋,程序計(jì)數(shù)器用來存放執(zhí)行指令的偏移量和行號指示器等,線程執(zhí)行或恢復(fù)都依賴程序計(jì)數(shù)器狞换。
  • 程序計(jì)數(shù)器是線程獨(dú)占避咆,在各個(gè)線程直接互不影響舟肉,在此區(qū)域也不會(huì)有內(nèi)存溢出異常。
  • 線程如果在執(zhí)行一個(gè)Java方法則記錄虛擬機(jī)字節(jié)碼指令的地址查库,如果代碼執(zhí)行到了Native方法計(jì)數(shù)器就為undefined路媚。

1.6. 直接內(nèi)存 Direct Memory

  • 直接內(nèi)存,即本機(jī)使用的堆外的系統(tǒng)內(nèi)存樊销。該部分內(nèi)存可被JVM使用整慎,不會(huì)被JVM堆內(nèi)存限制,但是動(dòng)態(tài)拓展時(shí)也會(huì)出現(xiàn)OutOfMemory现柠,可用-XX:MaxDirectMemorySize=50m來限制使用內(nèi)存空間的最大值最大值

  • DirectByteBuffer可以直接操作DirectMemory院领,它通過JNI調(diào)用native方法直接分配堆外內(nèi)存弛矛,通過DirectByteBuffer對象對這塊內(nèi)存對象進(jìn)行操作

    這個(gè)調(diào)用够吩,實(shí)際上是從系統(tǒng)的用戶態(tài)切換到了內(nèi)核態(tài)使用系統(tǒng)調(diào)用來完成這個(gè)操作。

    為什么要切換到內(nèi)核態(tài)丈氓?用戶態(tài)沒有權(quán)限去操作內(nèi)核態(tài)的資源周循,它只能通過系統(tǒng)調(diào)用外完成用戶態(tài)到內(nèi)核態(tài)的切換,然后在完成相關(guān)操作后再有內(nèi)核態(tài)切換回用戶態(tài)万俗。

    DirectByteBuffer該類本身還是位于Java內(nèi)存模型的堆中湾笛。堆內(nèi)內(nèi)存是JVM可以直接管控、操縱闰歪。

    由于DirectByteBuffer的權(quán)限修飾符是空的也就是默認(rèn)的嚎研,所以在我們編程中是無法直接new,只允許同包創(chuàng)建库倘,我們可以通過ByteBuffer中的靜態(tài)方法allocateDirect(int)方法來創(chuàng)建對象临扮。
    java public static ByteBuffer allocateDirect(int capacity) { return new DirectByteBuffer(capacity); }
    > 而 DirectByteBuffer 類中調(diào)用了native的unsafe.allocateMemory(size)來分配空間,實(shí)際上是使用了c語言的malloc方法教翩。
    ```java
    // Primary constructor
    //
    DirectByteBuffer(int cap) { // package-private

     super(-1, 0, cap, cap);
     boolean pa = VM.isDirectMemoryPageAligned();
     int ps = Bits.pageSize();
     long size = Math.max(1L, (long)cap + (pa ? ps : 0));
     Bits.reserveMemory(size, cap);
    
     long base = 0;
     try { // 這里是重點(diǎn)8擞隆!饱亿!掉黑板
         base = unsafe.allocateMemory(size);
     } catch (OutOfMemoryError x) {
         Bits.unreserveMemory(size, cap);
         throw x;
     }
     unsafe.setMemory(base, size, (byte) 0);
     if (pa && (base % ps != 0)) {
         // Round up to page boundary
         address = base + ps - (base & (ps - 1));
     } else {
         address = base;
     } // 這里記錄分配空間的信息蚜退。
     cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
     att = null;
    

    }

     // 記錄分分配空間信息的類
     private Deallocator(long address, long size, int capacity) {
         assert (address != 0);
         this.address = address;
         this.size = size;
         this.capacity = capacity;
     }
    

2. 對象創(chuàng)建與內(nèi)存分配

2.1 對象創(chuàng)建

  • 對象使用new創(chuàng)建的簡單過程
創(chuàng)建對象過程
  • 指針碰撞:

    假設(shè)Java堆中內(nèi)存是絕對規(guī)整的,所有用過的內(nèi)存都被放在一邊彪笼,空閑的內(nèi)存被放在另一邊钻注,中間放著一個(gè)指針作 為分界點(diǎn)的指示器,那所分配內(nèi)存就僅僅是把那個(gè)指針向空閑空間那邊挪動(dòng)一段與對象大小相等的距離配猫,這種分配方式稱為“指針碰撞”(Bump The Pointer)
    【帶Compact過程的Serial队寇、ParNew等采用指針碰撞≌滦眨】

  • 空閑列表

    如果Java堆中的內(nèi)存并不是規(guī)整的佳遣,已使用的和空閑的內(nèi)存相互交錯(cuò)识埋,就無法進(jìn)行指針碰撞了,JVM就必須維護(hù)一個(gè)列表零渐,記錄可用內(nèi)存區(qū)域窒舟,在分配的時(shí)候從列表中找到一塊足夠大的空間劃分給對象實(shí)例,并更新列表上的記錄诵盼,這種分配方式稱為“空閑列表”(Free List)
    【CMS這種基于Mark-Sweep算法的使用空閑列表】

  • 不難想到惠豺,分配內(nèi)存時(shí)如果多個(gè)線程同時(shí)創(chuàng)建對象,就會(huì)出現(xiàn)并發(fā)問題风宁。JVM實(shí)際采用:

    一種是CAS(Compare And Swap)加上失敗重試機(jī)制來保證更新操作的原子性洁墙;

    另一種是本地線程緩沖(TLAB,Thread Local Allocation Buffer.)戒财,即把內(nèi)存分配的動(dòng)作按照線程劃分在不同的空間之中進(jìn)行热监,每個(gè)線程都預(yù)先分配一小塊內(nèi)存。線程在自己的TLAB中分配饮寞,只有TLAB用完才需要同步加鎖孝扛。虛擬機(jī)是否用TLAB,可以通過-XX:+/-UseTLAB參數(shù)設(shè)定幽崩。


2.2 對象內(nèi)存

  • 對象頭(Header)包含兩部分:一是自身運(yùn)行時(shí)數(shù)據(jù)苦始;二是類型指針

    運(yùn)行時(shí)數(shù)據(jù): 32位和64位JVM分別對應(yīng)32位和64位長度(未開啟指正壓縮),存儲(chǔ)包括:哈希碼慌申、GC分帶年齡陌选、鎖狀態(tài)標(biāo)志、線程池持有鎖蹄溉、偏向鎖ID咨油、偏向時(shí)間戳等。(Mark Word)类缤。

    類型指針: 即對象指向它的類元數(shù)據(jù)的指針臼勉,虛擬機(jī)通過這個(gè)指針確定是哪個(gè)對象的實(shí)例。查找對象的元數(shù)據(jù)信息不一定要經(jīng)過對象本身餐弱。對象是Java數(shù)組宴霸,則對象頭中則會(huì)有一塊記錄數(shù)組長度的數(shù)據(jù);普通Java類可以通過元數(shù)據(jù)信息確定Java類大小膏蚓,但數(shù)組還需要需要對象頭中的長度數(shù)據(jù)才能確定瓢谢。

  • 實(shí)例數(shù)據(jù)(Instance Data)

    就是對象存儲(chǔ)的真正的有效信息,也就是程序代碼中定義的所有字段內(nèi)容驮瞧。

  • 對齊填充(Padding)

    因?yàn)镠otSpot VM的自動(dòng)內(nèi)存管理系統(tǒng)要求對象起始地址必須是8字節(jié)的整數(shù)倍氓扛,對象頭部分正好是8字節(jié)的倍數(shù),當(dāng)對象實(shí)例數(shù)據(jù)部分沒有對齊時(shí),就需要通過對齊填充來補(bǔ)全采郎。


2.3 對象訪問

  • Java通過棧上的reference數(shù)據(jù)來操作堆上的具體對象千所,而reference是一個(gè)指向?qū)ο蟮囊茫ㄟ^reference去定位和訪問對象蒜埋,目前主流的使用兩種方式:一是使用句柄淫痰,二是使用直接指針

    句柄: JVM堆會(huì)專門劃分內(nèi)存作為句柄池,而reference中存的就是對象的句柄地址整份;句柄中包含了對象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址待错。

    句柄

    直接指針: 如果是直接指針,Java堆中就會(huì)防止訪問類型數(shù)據(jù)相關(guān)的信息烈评。而reference中存儲(chǔ)的直接就是對象地址火俄。

    直接指針

關(guān)于我

  • 坐標(biāo)杭州,普通本科在讀讲冠,計(jì)算機(jī)科學(xué)與技術(shù)專業(yè)瓜客,20年畢業(yè),目前處于實(shí)習(xí)階段沟启。
  • 主要做Java開發(fā)忆家,會(huì)寫點(diǎn)Golang犹菇、Shell德迹。對微服務(wù)、大數(shù)據(jù)比較感興趣揭芍,預(yù)備做這個(gè)方向胳搞。
  • 目前處于菜鳥階段,各位大佬輕噴称杨,小弟正在瘋狂學(xué)習(xí)肌毅。
  • 歡迎大家和我交流鴨!9迷悬而!
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锭汛,隨后出現(xiàn)的幾起案子笨奠,更是在濱河造成了極大的恐慌,老刑警劉巖唤殴,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件般婆,死亡現(xiàn)場離奇詭異,居然都是意外死亡朵逝,警方通過查閱死者的電腦和手機(jī)蔚袍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來配名,“玉大人啤咽,你說我怎么就攤上這事晋辆。” “怎么了宇整?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵栈拖,是天一觀的道長。 經(jīng)常有香客問我没陡,道長涩哟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任盼玄,我火速辦了婚禮贴彼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘埃儿。我一直安慰自己器仗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布童番。 她就那樣靜靜地躺著精钮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剃斧。 梳的紋絲不亂的頭發(fā)上轨香,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音幼东,去河邊找鬼臂容。 笑死,一個(gè)胖子當(dāng)著我的面吹牛根蟹,可吹牛的內(nèi)容都是我干的脓杉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼简逮,長吁一口氣:“原來是場噩夢啊……” “哼球散!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起散庶,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蕉堰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后督赤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘁灯,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年躲舌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丑婿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖羹奉,靈堂內(nèi)的尸體忽然破棺而出秒旋,到底是詐尸還是另有隱情,我是刑警寧澤诀拭,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布迁筛,位于F島的核電站,受9級特大地震影響耕挨,放射性物質(zhì)發(fā)生泄漏细卧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一筒占、第九天 我趴在偏房一處隱蔽的房頂上張望贪庙。 院中可真熱鬧,春花似錦翰苫、人聲如沸止邮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽导披。三九已至,卻和暖如春埃唯,著一層夾襖步出監(jiān)牢的瞬間撩匕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工筑凫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滑沧,地道東北人并村。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓巍实,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哩牍。 傳聞我的和親對象是個(gè)殘疾皇子棚潦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

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