深入理解Java虛擬機(jī)(一):自動內(nèi)存管理機(jī)制

Java虛擬機(jī)

Oracle有兩款實(shí)現(xiàn)了 Java SE 的產(chǎn)品:Java SE Development Kit(JDK)Java SE Runtime Environment(JRE)瑞侮。
JDKJRE 的超集,包含了 JRE 的所有內(nèi)容明未,以及開發(fā)應(yīng)用程序所需的編譯器和調(diào)試器等工具弄跌。 JRE 提供了函數(shù)庫峻呛、Java Virtual Machine(JVM) 和其它用來運(yùn)行Java應(yīng)用程序的組件畔规。

Java SE8產(chǎn)品組件概念圖

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

Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)

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

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間鲫寄,他的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器瓜喇。由于 JVM 的多線程是通過線程輪流切換并分配處理器執(zhí)行時(shí)間來實(shí)現(xiàn)的,因此每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器乒融,用于線程切換后能恢復(fù)到正確的執(zhí)行位置掰盘。如果線程執(zhí)行的是Java方法摄悯,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址赞季。如果正在執(zhí)行的是 Native方法,這個(gè)計(jì)數(shù)器的值為 undefined奢驯。此區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒有規(guī)定 OutOfMemoryError 情況的區(qū)域申钩。

Java虛擬機(jī)棧

  • 虛擬機(jī)棧描述的是Java方法執(zhí)行的動態(tài)內(nèi)存模型,調(diào)用方法即創(chuàng)建棧幀并入棧瘪阁,方法執(zhí)行完畢棧幀出棧撒遣。
  • 棧幀:每個(gè)方法執(zhí)行,都會創(chuàng)建一個(gè)棧幀管跺,用于存儲局部變量表义黎,操作數(shù)棧,動態(tài)鏈接豁跑,方法出口等廉涕。每一個(gè)方法從調(diào)用到執(zhí)行完成的過程,就是一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過程艇拍。
  • 局部變量表:存放編譯器可知的各種基本數(shù)據(jù)類型狐蜕,引用類型,returnAddress類型卸夕。對象是在堆內(nèi)存中創(chuàng)建的层释,局部變量表存放的是對象的引用,其大小是不會改變的贡羔。因此局部變量表的內(nèi)存空間在編譯期完成分配后廉白,方法需要在幀分配多少內(nèi)存是固定的乖寒。
  • 虛擬機(jī)棧異常:如果線程請求的棧深度超過虛擬機(jī)允許的深度,將拋出 StackOverFlowError 異常宵统;如果虛擬機(jī)棧允許擴(kuò)展,在擴(kuò)展時(shí)無法申請到足夠的內(nèi)存马澈,就會拋出 OutOfMemoryError 異常。

本地方法棧

Java虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法服務(wù)痊班,本地方法棧則為虛擬機(jī)使用到的 Native方法 服務(wù)。在 Hotspot虛擬機(jī) 的實(shí)現(xiàn)中是把本地方法棧和虛擬機(jī)棧合二為一的涤伐。與虛擬機(jī)棧一樣馒胆,本地方法棧也會拋出 StackOverFlowError 異常和 OutOfMemoryError 異常。

Java堆

堆是線程共享的數(shù)據(jù)運(yùn)行時(shí)區(qū)域凝果,幾乎所有的對象實(shí)例以及數(shù)組都要在堆上分配內(nèi)存祝迂。堆是垃圾收集器管理的主要區(qū)域。Java堆可以處于物理上不連續(xù)的內(nèi)存空間中器净。如果在堆中沒有內(nèi)存完成實(shí)例分配型雳,并且堆也無法再擴(kuò)展時(shí),將會拋出 OutOfMemoryError 異常山害。

方法區(qū)

方法區(qū)存儲虛擬機(jī)加載的類信息(類的版本纠俭、字段、方法浪慌、接口)冤荆、常量、靜態(tài)變量权纤、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)钓简。于 Hotspot虛擬機(jī) 來說,將方法區(qū)納入GC管理范圍妖碉,這樣就不必單獨(dú)管理方法區(qū)的內(nèi)存涌庭,所以就有了相對于新生代和老年代的永久代一說。

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

運(yùn)行時(shí)常量池(JDK6在方法區(qū)欧宜,JDK7在Java堆)用來存放編譯器生成的各種字面量以及符號引用(類加載之后進(jìn)入運(yùn)行時(shí)常量池)坐榆。運(yùn)行期間也能將新的常量放入池中。當(dāng)常量池?zé)o法再申請到內(nèi)存時(shí)冗茸,將會拋出 OutOfMemoryError 異常席镀。

直接內(nèi)存

Java NIO 使用 Native函數(shù)庫 直接分配堆外內(nèi)存匹中,然后通過一個(gè)存儲在Java堆中的 DirectByteBuffer 對象作為這塊內(nèi)存的引用進(jìn)行操作。通過避免在 Java堆Native堆 中來回復(fù)制數(shù)據(jù)來提高性能豪诲。直接內(nèi)存大小不受虛擬機(jī)參數(shù)控制顶捷,如果各個(gè)內(nèi)存區(qū)域總和大于物理內(nèi)存限制,就會出現(xiàn) OutOfMemoryError 異常屎篱。

對象

對象的創(chuàng)建

對象的創(chuàng)建過程

內(nèi)存分配策略

根據(jù) Java 堆 是否規(guī)整可以判斷使用哪種內(nèi)存分配策略服赎。

  • 指針碰撞:堆內(nèi)存中的空閑空間十分的規(guī)整,使用與未使用的空間全部為連續(xù)重虑,分配內(nèi)存只需移動指針秦士。
  • 空閑列表:針對堆內(nèi)存中的空間零散的存在,虛擬機(jī)維護(hù)著一個(gè)列表隧土,記錄那些內(nèi)存未使用曹傀。

線程安全性

對象創(chuàng)建在虛擬機(jī)中是十分頻繁的行為,在并發(fā)環(huán)境下需要考慮線程安全揖曾。

  • CAS失敗重試:通過樂觀鎖實(shí)現(xiàn)線程安全亥啦。
  • TLAB(Thread Local Allocation Buffer):本地線程分配緩沖练链,內(nèi)存為每個(gè)線程分配一個(gè) TLAB區(qū)域,每個(gè)線程要?jiǎng)?chuàng)建對象時(shí)先在這個(gè)區(qū)域中創(chuàng)建届吁,當(dāng)原來的空間不足時(shí)再通過線程同步獲取一塊新的區(qū)域绿鸣。

對象設(shè)置

將對象的哈希嗎、GC年齡信息等存放在對象頭中亮蛔,執(zhí)行 <init> 方法擎厢。

對象的結(jié)構(gòu)

對象頭(Header)

  • 自身運(yùn)行時(shí)數(shù)據(jù):哈希碼、GC分代年齡芬探、鎖狀態(tài)標(biāo)志、線程持有的鎖哩簿、偏向線程ID酝静、偏向時(shí)間戳等。
  • 類型指針:對象指向它的類的元數(shù)據(jù)的指針全跨,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對象是哪個(gè)類的實(shí)例亿遂。如果對象是一個(gè)數(shù)組,對象頭中還必須有一塊記錄數(shù)組長度的數(shù)據(jù)挪钓。

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

實(shí)例數(shù)據(jù)是對象真正存儲的有效信息耳舅,也是程序代碼中所定義的各種類型的字段內(nèi)容。

對齊填充(Padding)

HotSpot虛擬機(jī) 要求對象的起始地址必須是8字節(jié)的整數(shù)倍馏予,也就是對象的大小必須是8字節(jié)的整數(shù)倍盔性。而對象頭部分正好是8字節(jié)的倍數(shù)(1倍或者2倍),因此蛹尝,當(dāng)對象實(shí)例數(shù)據(jù)部分沒有對齊的時(shí)候突那,就需要通過對齊填充來補(bǔ)全构眯。

對象的訪問定位

Java程序通過棧上的 reference 數(shù)據(jù)來操作堆上的具體對象,由于 reference 類型在Java虛擬機(jī)規(guī)范中只規(guī)定了一個(gè)指向?qū)ο蟮囊梦皲觯唧w用何種方式去定位、引用堆中對象的具體位置翘悉,取決于虛擬機(jī)的實(shí)現(xiàn)居触,目前主要有 使用句柄直接指針 兩種方式。

  • 使用句柄:引用類型指向堆中一塊區(qū)域(句柄池)制市,此區(qū)域保存了實(shí)例對象的地址(對象被移動時(shí)維護(hù)句柄中的指針數(shù)據(jù)弊予,無需改變 reference 本身)。
  • 直接指針:從引用類型直接指向內(nèi)存區(qū)域(速度更快误褪,節(jié)省了一次指針定位帶來的開銷)碾褂。

垃圾回收

在Java堆上分配一個(gè)內(nèi)存給實(shí)例對象時(shí),此時(shí)在虛擬機(jī)棧上引用型變量就會存放這個(gè)實(shí)例對象的起始地址嘀略。當(dāng)線程銷毀后乓诽,其在虛擬機(jī)棧上的內(nèi)存自然會被回收,也就是說虛擬機(jī)棧上的這塊內(nèi)存不在虛擬機(jī)GC范圍內(nèi)逮壁。

垃圾對象判定算法

  • 引用計(jì)數(shù)法:在對象中添加一個(gè)引用計(jì)數(shù)器粮宛,當(dāng)有地方引用這個(gè)對象時(shí)巍杈,引用計(jì)數(shù)器的值+1扛伍,當(dāng)引用失效時(shí),計(jì)數(shù)器的值-1鳖宾。垃圾回收器遇到計(jì)數(shù)器為0的對象時(shí)就會回收。但是當(dāng)堆內(nèi)存中的對象相互引用渔肩,而外部不存在對這些對象的引用時(shí)拇惋,計(jì)數(shù)器值不為0,無法判定回收蓉坎。
  • 可達(dá)性分析法:通過一系列名為 GC Roots 的對象(虛擬機(jī)棧蛉艾、方法區(qū)類屬性所引用的對象衷敌、方法區(qū)中常量所引用的對象、本地方法棧中引用的對象)作為起始點(diǎn)罐监,從這些節(jié)點(diǎn)開始向下搜索瞒爬,搜索所走過的路徑稱為 引用鏈(Reference Chain),當(dāng)一個(gè)對象到GC Roots沒有任何引用鏈相連時(shí)矢空,則此對象證明是不可用的禀横,將被判定為可回收對象。

Java引用

  • 強(qiáng)引用:類似 Obejct obj = new Object()酿箭,只要強(qiáng)引用還在趾娃,垃圾收集器就永遠(yuǎn)不會收集被引用的對象。
  • 軟引用:還有用但并非必須的對象妇蛀。在系統(tǒng)發(fā)生內(nèi)存溢出之前,會將軟引用關(guān)聯(lián)的對象進(jìn)行回收评架,如果回收后還沒有足夠的內(nèi)存,才會拋出內(nèi)存異常上祈。
  • 弱引用:垃圾收集器工作時(shí)挣磨,無論當(dāng)前內(nèi)存是否足夠,都會回收被弱引用關(guān)聯(lián)的對象塘砸。
  • 虛引用:一個(gè)對象是否有虛引用的存在晤锥,完全不會對其生產(chǎn)時(shí)間構(gòu)成影響。也無法通過虛引用來取得一個(gè)對象實(shí)例女轿。為一個(gè)對象設(shè)置虛引用關(guān)聯(lián)的唯一目的是能在這個(gè)對象被垃圾收集時(shí)收到一個(gè)系統(tǒng)通知壕翩。

finalize()

將對象回收至少要經(jīng)歷兩次標(biāo)記過程,如果在可達(dá)性分析中發(fā)現(xiàn)對象沒有與 GC Roots 的引用鏈北救,那它將會被第一次標(biāo)記并被進(jìn)行一次篩選珍策,篩選的條件是此對象是否有必要執(zhí)行 finalize() 方法(當(dāng)前對象沒有覆蓋此方法或者已經(jīng)執(zhí)行過此方法宅倒,則虛擬機(jī)認(rèn)為“沒有必要執(zhí)行”),虛擬機(jī)不會承諾等待此方法執(zhí)行結(jié)束蹭劈。如果在 finalize() 方法中成功與引用鏈上的人一個(gè)對象建立關(guān)聯(lián)唠亚,則對象不會被回收。

如何回收

回收策略

  • 標(biāo)記-清除算法:標(biāo)記可達(dá)對象,在清除階段回收并沒有被標(biāo)記為可達(dá)的對象所占用的內(nèi)存空間,并將原來的可達(dá)標(biāo)記刪除前酿。但是效率不高且會造成內(nèi)存碎片化鹏溯。
  • 復(fù)制算法:標(biāo)記待回收內(nèi)存和不需回收的內(nèi)存,將不需回收的內(nèi)存復(fù)制到新的內(nèi)存區(qū)域肺孵,這樣舊的內(nèi)存區(qū)域就可以全部回收颜阐,而新的內(nèi)存區(qū)域是連續(xù)的。其缺點(diǎn)是需要損失部分系統(tǒng)內(nèi)存用于復(fù)制,但是可以避免產(chǎn)生內(nèi)存碎片。實(shí)例創(chuàng)建時(shí)通常發(fā)生在 Eden空間项炼,發(fā)生 Minor GC 后芒率,會將Eden和其中一個(gè) Survivor空間 不需回收的對象內(nèi)存復(fù)制到另一個(gè) Survivor空間 中(HotSpot 虛擬機(jī)中 Eden空間Survivor空間 的比例為8:1)篙顺,如果反復(fù)幾次復(fù)制有對象一直存活,則會將相應(yīng)的對象內(nèi)存移至老年代腋寨。
Java垃圾回收管理
  • 標(biāo)記-整理算法:是老年代中的垃圾回收算法萄窜,標(biāo)記過后撒桨,將不用回收的對象內(nèi)存壓縮到空間的一端,再對另一端的內(nèi)存空間進(jìn)行垃圾回收穗泵。這樣既避免了復(fù)制算法帶來的效率問題谜疤,也避免了內(nèi)存碎片化的問題现诀。

垃圾收集器

垃圾收集器是垃圾回收算法的具體實(shí)現(xiàn)仔沿。

Serial垃圾收集器

Serial垃圾收集器 是最基本尺棋、發(fā)展歷史最悠久的收集器。

  • 采用復(fù)制算法成福,針對新生代
  • 單線程垃圾回收荆残,執(zhí)行時(shí)必須暫停所有工作線程,直到完成
Serial - Serial Old組合收集器

ParNew垃圾收集器

ParNew垃圾收集器 是Serial收集器的多線程版本握侧。

ParNew -Serial Old組合收集器

Parallel Scavenge垃圾收集器

Parallel Scavenge收集器 的目標(biāo)是達(dá)到一個(gè)可控制的吞吐量(CPU用于運(yùn)行用戶代碼的時(shí)間與CPU消耗的總時(shí)間的比值)品擎,即減少垃圾收集時(shí)間萄传,讓用戶代碼獲得更長的運(yùn)行時(shí)間蜜猾。

  • 采用復(fù)制算法,針對新生代
  • 多線程垃圾回收
    Parallel Scavenge收集器 提供兩個(gè)參數(shù)用于精確控制吞吐量:
  • -XX:MaxGCPauseMillis:最大垃圾收集停頓時(shí)間(ms)衍菱,設(shè)置稍小會縮短停頓時(shí)間肩豁,但也可能會造成頻繁發(fā)生垃圾回收,使得吞吐量下降琼锋。
  • -XX:GCTimeRatio:垃圾收集時(shí)間占總時(shí)間的比率祟昭,0 < n < 100的整數(shù)

CMS(Concurrent Mark Sweep)垃圾收集器

CMS收集器是一款真正意義上的并發(fā)收集器,實(shí)現(xiàn)了讓垃圾收集線程與用戶線程(基本上)同時(shí)工作谜叹。適用于與用戶交互較多的場景。

  • 針對老年代
  • 基于標(biāo)記-清除算法
  • 以獲取最短回收停頓時(shí)間為目標(biāo)

G1垃圾收集器

  • 充分利用多CPU叉谜、多核環(huán)境下的硬件優(yōu)勢踩萎,可以使垃圾收集和用戶程序同時(shí)進(jìn)行。
  • 分代收集董栽,能夠獨(dú)立管理整個(gè)GC堆企孩,采用不同方式處理不同時(shí)期的對象。整個(gè)堆被劃分為多個(gè)大小相等的 不連續(xù)獨(dú)立區(qū)域(Region)擒抛,新生代和老年代不再是物理隔離补疑,它們都是一部分Region的集合。
  • 從整體看基于標(biāo)記-整理算法诊胞,從局部看(兩個(gè)Region間)是基于復(fù)制算法锹杈,不會產(chǎn)生內(nèi)存碎片,有利于長時(shí)間運(yùn)行邪码。
  • 可預(yù)測的停頓咬清,可以明確指定M毫秒時(shí)間片內(nèi),垃圾收集消耗的時(shí)間不超過N毫秒喻圃。
  • 適用于服務(wù)端粪滤,針對大內(nèi)存,多處理器的機(jī)器肆汹。

內(nèi)存分配

HotSpot一般的年代內(nèi)存劃分

對象的內(nèi)存分配主要在堆上分配(JIT編譯優(yōu)化后可能在棧上分配),在新生代的Eden空間中分配昂勉,如果啟用了本地線程分配緩沖,則線程優(yōu)先在TLAB上分配村象。少數(shù)情況下對象會直接分配在老年代中厚者。

內(nèi)存分配策略

  • 優(yōu)先分配到Eden空間:大多數(shù)情況下迫吐,對象在新生代 Eden區(qū)域 中分配。當(dāng) Eden區(qū)域 沒有足夠空間時(shí)將會發(fā)起一次 Minor GC熙宇。
  • 大對象直接分配到老年代:所謂大對象是指需要大量連續(xù)空間的Java對象溉浙,直接在老年代分配空間就避免了大對象在新生代各個(gè)區(qū)域間反復(fù)復(fù)制。
  • 長期存活的對象分配到老年代:虛擬機(jī)給每個(gè)對象定義了一個(gè)對象年齡計(jì)數(shù)器烈拒,如果對象在 Eden區(qū)域 出生且經(jīng)過一次 Minor GC 后仍然存活广鳍,并且能被 Survivor空間 容納,對象年齡就會被設(shè)為1吨铸,此后對象每熬過一次 Minor GC祖秒,其年齡就會增加1,當(dāng)年齡增加到一定程度(默認(rèn)為15歲)房维,就會晉升到老年代中抬纸。
  • 動態(tài)對象年齡判斷:Survivor空間 中相同年齡的所有對象大小的總和大于 Survivor空間 的一半,則年齡大于等于該年齡的對象可以直接進(jìn)入老年代阿趁。
  • 空間分配擔(dān)保:有可能在 Minor GC 執(zhí)行后仍有大量對象在新生代存活,就需要老年代進(jìn)行分配擔(dān)保脖阵,將 Survivor空間 無法容納的對象晉升到老年代,老年代要進(jìn)行這樣的擔(dān)保呜呐,前提是老年代中有容納這些對象的足夠空間纷铣。因此在進(jìn)行 Minor GC 前,虛擬機(jī)會檢查老年代最大連續(xù)可用內(nèi)存是否大于新生代所有對象總空間,如果條件成立槐秧,則 Minor GC 可以確保是安全的,如果不成立虛擬機(jī)則查看 HandlePromotionFailure 參數(shù)判斷是否允許擔(dān)保失敗颠通。如果允許顿锰,則會繼續(xù)檢查老年代的最大連續(xù)空間是否大于歷次晉升到老年代對象的平均大小启搂,如果大于將嘗試一次 Minor GC,如果小于或 HandlePromotionFailure 參數(shù)不允許則改為進(jìn)行一次 Full GC牢撼,發(fā)生擔(dān)保失敗也會重新進(jìn)行一次 Full GC疑苫。空間分配擔(dān)焙扯蹋可以避免 Full GC 過于頻繁挺勿。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市胜榔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夭织,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讲竿,死亡現(xiàn)場離奇詭異题禀,居然都是意外死亡膀捷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門秀仲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壶笼,“玉大人,你說我怎么就攤上這事保礼≡鹩铮” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵铝阐,是天一觀的道長徘键。 經(jīng)常有香客問我,道長吹害,這世上最難降的妖魔是什么虚青? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮纵穿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淆院。我一直安慰自己句惯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布拷淘。 她就那樣靜靜地躺著指孤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逝嚎。 梳的紋絲不亂的頭發(fā)上详恼,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天昧互,我揣著相機(jī)與錄音伟桅,去河邊找鬼。 笑死玖雁,一個(gè)胖子當(dāng)著我的面吹牛盖腕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播溃列,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼听隐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了风范?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤锌半,失蹤者是張志新(化名)和其女友劉穎加酵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冗澈,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亚亲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年腐缤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惜索。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剃浇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出角塑,到底是詐尸還是另有隱情淘讥,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布窒朋,位于F島的核電站嫉嘀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拭宁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一兵怯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧媒区,春花似錦掸犬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至溢陪,卻和暖如春睛廊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背没酣。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工卵迂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留见咒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓改览,卻偏偏與公主長得像缤言,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子庆揩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

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