理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域枪萄,看這一篇文章就夠了

一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域

  • 相應(yīng)腦圖

程序計(jì)數(shù)器

記錄正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址(如果正在執(zhí)行的是本地方法則為空)猫妙。

Java 虛擬機(jī)棧

每個(gè) Java 方法在執(zhí)行的同時(shí)會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表操作數(shù)棧聚凹、常量池引用等信息割坠。 從方法調(diào)用直至執(zhí)行完成的過程,就對(duì)應(yīng)著一個(gè)棧幀在 Java 虛擬機(jī)棧中入棧和出棧的過程妒牙。 對(duì)于執(zhí)行引擎來說彼哼,活動(dòng)線程中,只有棧頂?shù)臈怯行У南娼瘢Q為當(dāng)前棧幀敢朱,這個(gè)棧幀所關(guān)聯(lián)的方法稱為當(dāng)前方法。 執(zhí)行引擎所運(yùn)行的所有字節(jié)碼指令都只針對(duì)當(dāng)前棧幀進(jìn)行操作摩瞎。

操作數(shù)棧:
一個(gè)后進(jìn)先出(Last-In-First-Out)的操作數(shù)棧拴签,也可以稱之為表達(dá)式棧(Expression Stack)。
操作數(shù)棧和局部變量表在訪問方式上存在著較大差異旗们,操作數(shù)棧并非采用訪問索引的方式來進(jìn)行數(shù)據(jù)訪問的蚓哩,
而是通過標(biāo)準(zhǔn)的入棧和出棧操作來完成一次數(shù)據(jù)訪問
每一個(gè)操作數(shù)棧都會(huì)擁有一個(gè)明確的棧深度用于存儲(chǔ)數(shù)值上渴,一個(gè)32bit的數(shù)值可以用一個(gè)單位的棧深度來存儲(chǔ)岸梨,而2個(gè)單位的棧深度則可以保存一個(gè)64bit的數(shù)值喜颁,
當(dāng)然操作數(shù)棧所需的容量大小在編譯期就可以被完全確定下來,并保存在方法的Code屬性中曹阔。
</pre>

可以通過 -Xss 這個(gè)虛擬機(jī)參數(shù)來指定每個(gè)線程的 Java 虛擬機(jī)棧內(nèi)存大邪肟:

該區(qū)域可能拋出以下異常:

  • 當(dāng)線程請求的棧深度超過最大值,會(huì)拋出 StackOverflowError 異常赃份;
  • 棧進(jìn)行動(dòng)態(tài)擴(kuò)展時(shí)如果無法申請到足夠內(nèi)存寂拆,會(huì)拋出 OutOfMemoryError 異常。

本地方法棧

本地方法棧與 Java 虛擬機(jī)棧類似芥炭,它們之間的區(qū)別只不過是本地方法棧為本地方法服務(wù)漓库。

本地方法一般是用其它語言(C、C++ 或匯編語言等)編寫的园蝠,并且被編譯為基于本機(jī)硬件和操作系統(tǒng)的程序渺蒿,對(duì)待這些方法需要特別處理。

理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域彪薛,看這一篇文章就夠了

所有對(duì)象都在這里分配內(nèi)存茂装,是垃圾收集的主要區(qū)域("GC 堆")。

現(xiàn)代的垃圾收集器基本都是采用分代收集算法善延,其主要的思想是針對(duì)不同類型的對(duì)象采取不同的垃圾回收算法少态,可以將堆分成兩塊:

  • 新生代(Young Generation)
  • 老年代(Old Generation)

堆不需要連續(xù)內(nèi)存,并且可以動(dòng)態(tài)增加其內(nèi)存易遣,增加失敗會(huì)拋出 OutOfMemoryError 異常彼妻。

可以通過 -Xms 和 -Xmx 兩個(gè)虛擬機(jī)參數(shù)來指定一個(gè)程序的堆內(nèi)存大小,第一個(gè)參數(shù)設(shè)置初始值豆茫,第二個(gè)參數(shù)設(shè)置最大值侨歉。

方法區(qū)

用于存放已被加載的類信息、常量揩魂、靜態(tài)變量幽邓、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

和堆一樣不需要連續(xù)的內(nèi)存火脉,并且可以動(dòng)態(tài)擴(kuò)展牵舵,動(dòng)態(tài)擴(kuò)展失敗一樣會(huì)拋出 OutOfMemoryError 異常。

對(duì)這塊區(qū)域進(jìn)行垃圾回收的主要目標(biāo)是對(duì)常量池的回收和對(duì)類的卸載倦挂,但是一般比較難實(shí)現(xiàn)畸颅。

HotSpot 虛擬機(jī)把它當(dāng)成永久代來進(jìn)行垃圾回收。但是很難確定永久代的大小妒峦,因?yàn)樗艿胶芏嘁蛩赜绊懼匕撸⑶颐看?Full GC 之后永久代的大小都會(huì)改變,所以經(jīng)常會(huì)拋出 OutOfMemoryError 異常肯骇。為了更容易管理方法區(qū)窥浪,從 JDK 1.8 開始祖很,移除永久代,并把方法區(qū)移至元空間漾脂,它位于本地內(nèi)存中假颇,而不是虛擬機(jī)內(nèi)存中。

運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池是方法區(qū)的一部分骨稿。

Class 文件中的常量池(編譯器生成的各種字面量和符號(hào)引用)會(huì)在類加載后被放入這個(gè)區(qū)域笨鸡。

除了在編譯期生成的常量,還允許動(dòng)態(tài)生成坦冠,例如 String 類的 intern()形耗。

直接內(nèi)存

在 JDK 1.4 中新加入了 NIO 類,它可以使用 Native 函數(shù)庫直接分配堆外內(nèi)存(Native 堆)辙浑,然后通過一個(gè)存儲(chǔ)在 Java 堆里的 DirectByteBuffer 對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作激涤。

這樣能在一些場景中顯著提高性能,因?yàn)楸苊饬嗽?Java 堆和 Native 堆中來回復(fù)制數(shù)據(jù)判呕。

二倦踢、HotSpot虛擬機(jī)對(duì)象

對(duì)象的創(chuàng)建

對(duì)象的創(chuàng)建步驟:

理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域,看這一篇文章就夠了
  1. 類加載檢查

虛擬機(jī)遇到一條 new 指令時(shí)侠草,首先將去檢查這個(gè)指令的參數(shù)是否能在常量池中定位到這個(gè)類的符號(hào)引用辱挥, 并且檢查這個(gè)符號(hào)引用代表的類是否已被加載過、解析和初始化過边涕。 如果沒有晤碘,那必須先執(zhí)行相應(yīng)的類加載過程。

  1. 分配內(nèi)存

在類加載檢查通過后功蜓,接下來虛擬機(jī)將為新生對(duì)象分配內(nèi)存哼蛆。 對(duì)象所需的內(nèi)存大小在類加載完成后便可確定,為對(duì)象分配空間的任務(wù)等同于把一塊確定大小的內(nèi)存從 Java 堆中劃分出來霞赫。分配方式有 “指針碰撞” 和 “空閑列表” 兩種,選擇那種分配方式由 Java 堆是否規(guī)整決定肥矢, 而Java堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定端衰。

  • 內(nèi)存分配的兩種方式
理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域,看這一篇文章就夠了
  • 內(nèi)存分配并發(fā)問題

在創(chuàng)建對(duì)象的時(shí)候有一個(gè)很重要的問題甘改,就是線程安全旅东,因?yàn)樵趯?shí)際開發(fā)過程中,創(chuàng)建對(duì)象是很頻繁的事情十艾, 作為虛擬機(jī)來說抵代,必須要保證線程是安全的,通常來講忘嫉,虛擬機(jī)采用兩種方式來保證線程安全:

(1)CAS+失敗重試: CAS 是樂觀鎖的一種實(shí)現(xiàn)方式荤牍。所謂樂觀鎖就是案腺, 每次不加鎖而是假設(shè)沒有沖突而去完成某項(xiàng)操作, 如果因?yàn)闆_突失敗就重試康吵,直到成功為止劈榨。 虛擬機(jī)采用CAS配上失敗重試的方式保證更新操作的原子性。

(2)TLAB: 每一個(gè)線程預(yù)先在Java堆中分配一塊內(nèi)存晦嵌,稱為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB)同辣。 哪個(gè)線程要分配內(nèi)存,就在哪個(gè)線程的TLAB上分配惭载,只有TLAB用完并分配新的TLAB時(shí)旱函,才采用上述的CAS進(jìn)行內(nèi)存分配。

  1. 初始化零值

內(nèi)存分配完成后描滔,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭)棒妨, 這一步操作保證了對(duì)象的實(shí)例字段在 Java 代碼中可以不賦初始值就直接使用, 程序能訪問到這些字段的數(shù)據(jù)類型所對(duì)應(yīng)的零值伴挚。

  1. 設(shè)置對(duì)象頭

初始化零值完成之后靶衍,虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置, 例如這個(gè)對(duì)象是那個(gè)類的實(shí)例茎芋、如何才能找到類的元數(shù)據(jù)信息颅眶、對(duì)象的哈希嗎、對(duì)象的 GC 分代年齡等信息田弥。 這些信息存放在對(duì)象頭中涛酗。 另外,根據(jù)虛擬機(jī)當(dāng)前運(yùn)行狀態(tài)的不同偷厦,如是否啟用偏向鎖等商叹,對(duì)象頭會(huì)有不同的設(shè)置方式。

  1. 執(zhí)行init方法

在上面工作都完成之后只泼,從虛擬機(jī)的視角來看剖笙,一個(gè)新的對(duì)象已經(jīng)產(chǎn)生了, 但從 Java 程序的視角來看请唱,對(duì)象創(chuàng)建才剛開始弥咪,<init> 方法還沒有執(zhí)行,所有的字段都還為零十绑。 所以一般來說聚至,執(zhí)行 new 指令之后會(huì)接著執(zhí)行 <init > 方法, 把對(duì)象按照程序員的意愿進(jìn)行初始化本橙,這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來扳躬。

對(duì)象的內(nèi)存布局

在 Hotspot 虛擬機(jī)中,對(duì)象在內(nèi)存中的布局可以分為3塊區(qū)域:

(1)對(duì)象頭

(2)實(shí)例數(shù)據(jù)

(3)對(duì)齊填充

  1. 對(duì)象頭

Hotspot虛擬機(jī)的對(duì)象頭包括兩部分信息:

一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù)(哈希碼、GC分代年齡贷币、鎖狀態(tài)標(biāo)志等等)击胜,

另一部分是類型指針,即對(duì)象指向它的類元數(shù)據(jù)的指針片择,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對(duì)象是那個(gè)類的實(shí)例潜的。

  1. 實(shí)例數(shù)據(jù)

實(shí)例數(shù)據(jù)部分是對(duì)象真正存儲(chǔ)的有效信息,也是在程序中所定義的各種類型的字段內(nèi)容字管。

  1. 對(duì)齊填充

對(duì)齊填充部分不是必然存在的啰挪,也沒有什么特別的含義,僅僅起占位作用嘲叔。 因?yàn)镠otspot虛擬機(jī)的自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象起始地址必須是8字節(jié)的整數(shù)倍亡呵, 換句話說就是對(duì)象的大小必須是8字節(jié)的整數(shù)倍。而對(duì)象頭部分正好是8字節(jié)的倍數(shù)(1倍或2倍)硫戈, 因此锰什,當(dāng)對(duì)象實(shí)例數(shù)據(jù)部分沒有對(duì)齊時(shí),就需要通過對(duì)齊填充來補(bǔ)全丁逝。

對(duì)象的訪問定位

建立對(duì)象就是為了使用對(duì)象汁胆,我們的Java程序通過棧上的 reference 數(shù)據(jù)來操作堆上的具體對(duì)象。 對(duì)象的訪問方式視虛擬機(jī)的實(shí)現(xiàn)而定霜幼,目前主流的訪問方式有兩種:

(1)使用句柄

(2)直接指針

  1. 使用句柄

如果使用句柄的話嫩码,那么Java堆中將會(huì)劃分出一塊內(nèi)存來作為句柄池, reference中存儲(chǔ)的就是對(duì)象的句柄地址罪既,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址信息

理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域铸题,看這一篇文章就夠了
  1. 直接指針

如果使用直接指針訪問,那么Java 堆對(duì)象的布局中就必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息琢感, 而reference中存儲(chǔ)的直接就是對(duì)象的地址丢间。

理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域,看這一篇文章就夠了

這兩種對(duì)象訪問方式各有優(yōu)勢:

(1)使用句柄來訪問的最大好處是 reference 中存儲(chǔ)的是穩(wěn)定的句柄地址驹针, 在對(duì)象被移動(dòng)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針烘挫,而reference本身不需要修改

(2)使用直接指針訪問方式最大的好處就是速度快柬甥,它節(jié)省了一次指針定位的時(shí)間開銷墙牌。

三、String類和常量池

  1. String對(duì)象的兩種創(chuàng)建方式
String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false

這兩種不同的創(chuàng)建方法是有差別的:

第一種方式是在常量池中獲取對(duì)象("abcd" 屬于字符串字面量暗甥,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象),

第二種方式一共會(huì)創(chuàng)建兩個(gè)字符串對(duì)象(前提是 String Pool 中還沒有 "abcd" 字符串對(duì)象)捉捅。

  • "abcd" 屬于字符串字面量撤防,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象,指向這個(gè) "abcd" 字符串字面量棒口;
  • 使用 new 的方式會(huì)在堆中創(chuàng)建一個(gè)字符串對(duì)象寄月。
理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域辜膝,看這一篇文章就夠了
  1. String類型的常量池比較特殊。它的主要使用方法有兩種:
  • 直接使用雙引號(hào)聲明出來的String對(duì)象會(huì)直接存儲(chǔ)在常量池中漾肮。
  • 如果不是用雙引號(hào)聲明的String對(duì)象,可以使用 String 提供的 intern 方法厂抖。 String.intern() 是一個(gè) Native 方法,它的作用是: 如果運(yùn)行時(shí)常量池中已經(jīng)包含一個(gè)等于此 String 對(duì)象內(nèi)容的字符串克懊,則返回常量池中該字符串的引用忱辅; 如果沒有,則在常量池中創(chuàng)建與此 String 內(nèi)容相同的字符串谭溉,并返回常量池中創(chuàng)建的字符串的引用墙懂。
String s1 = new String("計(jì)算機(jī)");
String s2 = s1.intern();
String s3 = "計(jì)算機(jī)";
System.out.println(s2);//計(jì)算機(jī)
System.out.println(s1 == s2);//false,因?yàn)橐粋€(gè)是堆內(nèi)存中的String對(duì)象一個(gè)是常量池中的String對(duì)象扮念,
System.out.println(s2 == s3);//true损搬,因?yàn)閮蓚€(gè)都是常量池中的String對(duì)象
  1. 字符串拼接:
String str1 = "str";
String str2 = "ing";

String str3 = "str" + "ing";//常量池中的對(duì)象
String str4 = str1 + str2; //TODO:在堆上創(chuàng)建的新的對(duì)象     
String str5 = "string";//常量池中的對(duì)象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域,看這一篇文章就夠了

注意:盡量避免多個(gè)字符串拼接柜与,因?yàn)檫@樣會(huì)重新創(chuàng)建對(duì)象巧勤。 如果需要改變字符串的話,可以使用 StringBuilder 或者 StringBuffer弄匕。

面試題:String s1 = new String("abc");問創(chuàng)建了幾個(gè)對(duì)象颅悉?

創(chuàng)建2個(gè)字符串對(duì)象(前提是 String Pool 中還沒有 "abcd" 字符串對(duì)象)。

  • "abc" 屬于字符串字面量粘茄,因此編譯時(shí)期會(huì)在常量池中創(chuàng)建一個(gè)字符串對(duì)象签舞,指向這個(gè) "abcd" 字符串字面量;
  • 使用 new 的方式會(huì)在堆中創(chuàng)建一個(gè)字符串對(duì)象柒瓣。

(字符串常量"abc"在編譯期就已經(jīng)確定放入常量池儒搭,而 Java 堆上的"abc"是在運(yùn)行期初始化階段才確定)。

String s1 = new String("abc");// 堆內(nèi)存的地址值
String s2 = "abc";
System.out.println(s1 == s2);// 輸出false
//因?yàn)橐粋€(gè)是堆內(nèi)存芙贫,一個(gè)是常量池的內(nèi)存搂鲫,故兩者是不同的。
System.out.println(s1.equals(s2));// 輸出true

四磺平、8種基本類型的包裝類和常量池

  • Java基本類型的包裝類的大部分都實(shí)現(xiàn)了常量池技術(shù)魂仍, 即Byte,Short,Integer,Long,Character,Boolean; 這5種包裝類默認(rèn)創(chuàng)建了數(shù)值[-128拣挪,127]的相應(yīng)類型的緩存數(shù)據(jù)擦酌, 但是超出此范圍仍然會(huì)去創(chuàng)建新的對(duì)象。
  • 兩種浮點(diǎn)數(shù)類型的包裝類Float,Double 并沒有實(shí)現(xiàn)常量池技術(shù)菠劝。

valueOf() 方法的實(shí)現(xiàn)比較簡單赊舶,就是先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內(nèi)容。

Integer的部分源碼:

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

在 Java 8 中笼平,Integer 緩存池的大小默認(rèn)為 -128~127园骆。、

理解JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域寓调,看這一篇文章就夠了
  • 示例1:
Integer i1=40;
//Java 在編譯的時(shí)候會(huì)直接將代碼封裝成 Integer i1=Integer.valueOf(40);從而使用常量池中的對(duì)象锌唾。
Integer i2 = new Integer(40);
//創(chuàng)建新的對(duì)象。
System.out.println(i1==i2);//輸出false
  • 示例2:Integer有自動(dòng)拆裝箱功能
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);

System.out.println("i1=i2 " + (i1 == i2)); //輸出 i1=i2 true
System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //輸出 i1=i2+i3 true
//i2+i3得到40,比較的是數(shù)值
System.out.println("i1=i4 " + (i1 == i4)); //輸出 i1=i4 false
System.out.println("i4=i5 " + (i4 == i5)); //輸出 i4=i5 false
//i5+i6得到40夺英,比較的是數(shù)值
System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //輸出 i4=i5+i6 true
System.out.println("40=i5+i6 " + (40 == i5 + i6)); //輸出 40=i5+i6 true

在此我向大家推薦一個(gè)Java群 :219571750 里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:(有Spring晌涕,MyBatis,Netty源碼分析秋麸,高并發(fā)渐排、高性能、分布式灸蟆、微服務(wù)架構(gòu)的原理驯耻,JVM性能優(yōu)化、分布式架構(gòu)炒考、面試資料)等這些成為架構(gòu)師必備的知識(shí)體系 進(jìn)群馬上免費(fèi)領(lǐng)取可缚,目前受益良多!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斋枢,一起剝皮案震驚了整個(gè)濱河市帘靡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓤帚,老刑警劉巖描姚,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異戈次,居然都是意外死亡轩勘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門怯邪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绊寻,“玉大人,你說我怎么就攤上這事悬秉〕尾剑” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵和泌,是天一觀的道長村缸。 經(jīng)常有香客問我,道長武氓,這世上最難降的妖魔是什么梯皿? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任搪柑,我火速辦了婚禮,結(jié)果婚禮上索烹,老公的妹妹穿的比我還像新娘。我一直安慰自己弱睦,他們只是感情好莽使,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布侠畔。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矿咕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天春锋,我揣著相機(jī)與錄音累贤,去河邊找鬼。 笑死屹耐,一個(gè)胖子當(dāng)著我的面吹牛尸疆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惶岭,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼寿弱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了按灶?” 一聲冷哼從身側(cè)響起症革,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸯旁,沒想到半個(gè)月后噪矛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铺罢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年艇挨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畏铆。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雷袋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辞居,到底是詐尸還是另有隱情楷怒,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布瓦灶,位于F島的核電站鸠删,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏贼陶。R本人自食惡果不足惜刃泡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一巧娱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧烘贴,春花似錦禁添、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锻离,卻和暖如春铺峭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汽纠。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工卫键, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虱朵。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓莉炉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卧秘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呢袱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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