Java 虛擬機(jī)(六):Java 虛擬機(jī)總述

這是我們 Java 虛擬機(jī)系列文章的第六篇,Java 虛擬機(jī)總述

Java 虛擬機(jī)子所以被稱(chēng)為”虛擬“的澜搅,就是因?yàn)樗鼉H僅是由一個(gè)規(guī)范來(lái)定義的抽象計(jì)算機(jī)。

1.Java虛擬機(jī)是什么

  • 抽象規(guī)范
  • 一個(gè)具體的實(shí)現(xiàn)
  • 一個(gè)運(yùn)行中的虛擬機(jī)實(shí)例

2.虛擬機(jī)的生命周期

在 Java 虛擬機(jī)內(nèi)部有兩種線(xiàn)程: 守護(hù)線(xiàn)程 和 非守護(hù)線(xiàn)程

守護(hù)線(xiàn)程
由虛擬機(jī)自己使用的邪锌,例如執(zhí)行垃圾回收任務(wù)的線(xiàn)程

非守護(hù)線(xiàn)程
守護(hù)線(xiàn)程之外的其他線(xiàn)程都是非守護(hù)線(xiàn)程

只要還有非守護(hù)線(xiàn)程在運(yùn)行勉躺,虛擬機(jī)就不會(huì)自動(dòng)退出。

結(jié)束虛擬機(jī)的方式 有兩種

  • System.exit() 方法退出
  • 非守護(hù)線(xiàn)程執(zhí)行完

3.虛擬機(jī)的體系結(jié)構(gòu)

jvm_all_01.png

Java 虛擬機(jī)的內(nèi)部體系結(jié)構(gòu)圖

方法區(qū)和堆都是線(xiàn)程共享的

圖5-3 線(xiàn)程專(zhuān)有的運(yùn)行時(shí)數(shù)據(jù)區(qū)

當(dāng)一個(gè)線(xiàn)程被創(chuàng)建時(shí)秃流,它將得到一個(gè)屬于自己的 PC 寄存器(程序計(jì)數(shù)器)已經(jīng)一個(gè) Java 棧赂蕴。當(dāng)線(xiàn)程執(zhí)行一個(gè) Java 方法時(shí), PC 寄存器的值總是指示下一條將被執(zhí)行的指令舶胀, 它的 Java 棧存儲(chǔ)該線(xiàn)程中 Java 方法調(diào)用的狀態(tài)概说,包含它局部變量、被調(diào)用時(shí)傳進(jìn)來(lái)的參數(shù)嚣伐、它的返回值糖赔、以及運(yùn)算的中間結(jié)果。

Java 棧是由許多棧幀(stack frame)組成的轩端,一個(gè)棧幀包含一個(gè) Java 方法調(diào)用的狀態(tài)放典。當(dāng)線(xiàn)程調(diào)用一個(gè) Java 方法時(shí),虛擬機(jī)壓入一個(gè)新的棧幀到該線(xiàn)程的 Java 棧中基茵;當(dāng)方法返回時(shí)奋构,這個(gè)棧幀被從 Java 棧中彈出并拋棄。

Java 虛擬機(jī)沒(méi)有寄存器拱层,其指令集使用 Java 棧來(lái)存儲(chǔ)中間數(shù)據(jù)弥臼。這樣設(shè)計(jì)的原因是保持 Java 虛擬機(jī)的指令集盡量緊湊,同事也便于 Java 虛擬機(jī)在那些只有很少通用寄存器的平臺(tái)上實(shí)現(xiàn)根灯。
這樣基于棧的體系結(jié)構(gòu)径缅,也有助于某些虛擬機(jī)實(shí)現(xiàn)的動(dòng)態(tài)編譯和即時(shí)編譯器的代碼優(yōu)化。

3.1 數(shù)據(jù)類(lèi)型

jvm_all_2.png

數(shù)據(jù)類(lèi)型分為兩種:

  • 基本類(lèi)型
  • 引用類(lèi)型
    • 類(lèi)類(lèi)型引用 -- 對(duì)類(lèi)實(shí)例的引用
    • 接口類(lèi)型引用 -- 對(duì)實(shí)現(xiàn)了該接口的某個(gè)類(lèi)實(shí)例的引用
    • 數(shù)組類(lèi)型引用 -- 對(duì)數(shù)組對(duì)象的引用

Java 語(yǔ)言中的所有基本類(lèi)型同樣也都是 Java 虛擬機(jī)中的基本類(lèi)型烙肺。
只是 boolean 類(lèi)型不一樣纳猪,編譯器吧 Java 源碼編譯為字節(jié)碼時(shí),它用 int 或者 byte 表示 boolean.

returnAddress 只是 Java 虛擬機(jī)中內(nèi)部使用的基本類(lèi)型

3.2 字的長(zhǎng)度

在 Java 虛擬機(jī)中桃笙,最基本的數(shù)據(jù)單元就是字(word), 它的大小是有每個(gè)虛擬機(jī)實(shí)現(xiàn)的設(shè)計(jì)者來(lái)決定的氏堤。

3.3 類(lèi)加載器子系統(tǒng)

負(fù)責(zé)查找并加載類(lèi)型的那部分被稱(chēng)為類(lèi)加載子系統(tǒng)。也就是我們所說(shuō)的類(lèi)加載器部分

Java 虛擬機(jī)有兩種類(lèi)加載器:?jiǎn)?dòng)類(lèi)加載器和用戶(hù)定義類(lèi)加載器怎栽。如果按更詳細(xì)的來(lái)分丽猬,就是啟動(dòng)類(lèi)加載器宿饱、應(yīng)用類(lèi)加載器、拓展類(lèi)加載器和用戶(hù)自定義類(lèi)加器脚祟。

類(lèi)加載器子系統(tǒng)要定位和導(dǎo)入二進(jìn)制 class 文件谬以,還必須負(fù)責(zé)驗(yàn)證被導(dǎo)入類(lèi)的正確性,為類(lèi)變量分配并初始化內(nèi)存由桌,以及幫助解析符號(hào)引用为黎。

執(zhí)行的順序:

  1. 裝載 -- 查找并加載類(lèi)型的二進(jìn)制數(shù)據(jù)
  2. 連接 -- 執(zhí)行驗(yàn)證,準(zhǔn)備行您,以及解析(可選)
  • 驗(yàn)證铭乾,確保被導(dǎo)入類(lèi)型的正確性
  • 準(zhǔn)備,為類(lèi)變量分配內(nèi)存娃循,并將其初始化為默認(rèn)值
  • 解析炕檩,把類(lèi)型中的符號(hào)引用轉(zhuǎn)換為直接引用

3.初始化 -- 把類(lèi)變量初始化為正確初始值

命名空間
每個(gè)類(lèi)加載器都有自己的命名空間,其中維護(hù)著由它加載的類(lèi)型

3.4 方法區(qū)

方法區(qū)是存儲(chǔ)關(guān)于被加載類(lèi)型的信息

方法區(qū)是線(xiàn)程共享的捌斧,需要對(duì)方法區(qū)數(shù)據(jù)的訪(fǎng)問(wèn)設(shè)計(jì)為線(xiàn)程安全

方法區(qū)也被稱(chēng)為垃圾收集笛质,因?yàn)樘摂M機(jī)允許通過(guò)用戶(hù)定義的類(lèi)加載器來(lái)加載 Java 程序,當(dāng)一些類(lèi)不要被引用是捞蚂,Java 虛擬機(jī)可以卸載這些不再被引用的類(lèi)妇押,從而使方法區(qū)占據(jù)的內(nèi)存保存最小。

存儲(chǔ)的類(lèi)型信息:

  • 這個(gè)類(lèi)型的全限定名

  • 這個(gè)類(lèi)型的直接超類(lèi)的全限定名(除了 java.lang.Object姓迅, 它沒(méi)有超類(lèi))

  • 這個(gè)類(lèi)型的訪(fǎng)問(wèn)修飾符(public , abstract 或 final 的某個(gè)子集)

  • 任何直接超類(lèi)的接口的全限定名的有序列表
    在 Java Class 文件和虛擬機(jī)匯總敲霍, 類(lèi)型名稱(chēng)是以全限定名出現(xiàn)的,例如 java/lang/Object

  • 這類(lèi)型的常量池

  • 字段信息
    包含:

    • 字段名
    • 字段的類(lèi)型
    • 字段的修飾符(public, private, protected, static, final, volatile, transient 的某個(gè)子集)
  • 方法信息
    包含:

    • 方法名
    • 方法的返回類(lèi)型(或 void)
    • 方法參數(shù)的數(shù)量和類(lèi)型(按聲明順序)
    • 方法的修飾符(public, private, protected, static, fianl, synchronized, native, abstract 的某個(gè)子集)
    • 方法的字節(jié)碼(bytecodes)
    • 操作數(shù)棧和該方法的棧幀中局部變量區(qū)的大小
    • 異常表
  • 除了常量以為的所有類(lèi)(靜態(tài))變量
    類(lèi)變量是由所有類(lèi)實(shí)例共享的丁存,即使沒(méi)有任何類(lèi)實(shí)例肩杈,它都可以被訪(fǎng)問(wèn)。
    而編譯時(shí)常量(那些 final 聲明及用編譯時(shí)已知的值初始化的類(lèi)變量)會(huì)復(fù)制它的所有常量到自己的常量池中或嵌入到它的字節(jié)碼中解寝。

  • 一個(gè)到類(lèi) ClassLoader 的引用

  • 一個(gè)到 Class 類(lèi)的引用
    對(duì)于被加載的類(lèi)型(類(lèi)或接口)锋恬,虛擬機(jī)都會(huì)相應(yīng)地為它創(chuàng)建一個(gè) java.lang.Class 類(lèi)的實(shí)例,而且虛擬機(jī)以某種方式把這個(gè)實(shí)例和存在在方法區(qū)中的類(lèi)型數(shù)據(jù)關(guān)聯(lián)起來(lái)编丘。
    在 java 程序中,可以得到并使用指向 Class 對(duì)象的引用彤悔。 Class 類(lèi)中的一個(gè)靜態(tài)方法可以讓用戶(hù)得到任何已加載的類(lèi)的 Class 實(shí)例的引用

3.5 堆 heap

Java 虛擬機(jī)實(shí)例中只有一個(gè)堆空間嘉抓,所有線(xiàn)程都將共享這個(gè)堆。 需要考慮多線(xiàn)程訪(fǎng)問(wèn)對(duì)象(堆數(shù)據(jù))的同步問(wèn)題

Java 程序在運(yùn)行時(shí)創(chuàng)建的所有類(lèi)型實(shí)例或數(shù)組都放在同一個(gè)堆中

Java 虛擬機(jī)有一條在堆中分配新對(duì)象的指令晕窑,卻沒(méi)有釋放內(nèi)存的指令抑片,所以釋放內(nèi)存的任務(wù)就交給了垃圾回收機(jī)器處理。

垃圾回收器的主要工作是自動(dòng)回收不再被運(yùn)行的程序引用的對(duì)象所占用的內(nèi)存杨赤。也可能去移動(dòng)那些還在使用的對(duì)象敞斋,以此減少堆碎片截汪。

堆空間可以是不連續(xù)的內(nèi)存空間,可以動(dòng)態(tài)擴(kuò)展或收縮植捎。

3.5.1 堆空間的設(shè)計(jì)

Java 虛擬機(jī)規(guī)范沒(méi)有規(guī)定 Java 對(duì)象在堆中是如何實(shí)現(xiàn)的衙解,它由虛擬機(jī)的實(shí)現(xiàn)者決定。

Java 對(duì)象中包含的基本數(shù)據(jù)由它所屬的類(lèi)及其超類(lèi)聲明的實(shí)例變量組成焰枢。虛擬機(jī)能夠通過(guò)對(duì)象實(shí)例的引用訪(fǎng)問(wèn)相應(yīng)的類(lèi)數(shù)據(jù)(存儲(chǔ)在方法區(qū)的類(lèi)型信息)蚓峦。因此對(duì)象中會(huì)有一個(gè)指向方法區(qū)的指針。

設(shè)計(jì)一:

jvm_all_3.png

把堆分成兩部分:句柄池 和 對(duì)象池

一個(gè)對(duì)象引用就是一個(gè)指向方法區(qū)句柄池的本地指針

句柄池包含兩部分:一個(gè)是指向?qū)ο蟪氐闹羔樇贸粋€(gè)指向方法區(qū)類(lèi)型數(shù)據(jù)的指針

優(yōu)點(diǎn):
有利于堆碎片的整理
當(dāng)移動(dòng)對(duì)象池中的對(duì)象時(shí)暑椰,句柄部分只需要更改一下指針指向?qū)ο蟮男碌刂肪涂梢粤?/p>

缺點(diǎn):
每次訪(fǎng)問(wèn)對(duì)象的實(shí)例變量都要經(jīng)過(guò)兩次指針傳遞。

設(shè)計(jì)二

jvm_all_4.png

使對(duì)象指針直接指向一組數(shù)據(jù)荐绝,改數(shù)據(jù)包括對(duì)象實(shí)例數(shù)據(jù)以及指向方法區(qū)中的數(shù)據(jù)的指針一汽。

優(yōu)點(diǎn)
訪(fǎng)問(wèn)對(duì)象實(shí)例比較快,只有一次指針傳遞

缺點(diǎn)
整理堆中實(shí)例對(duì)象時(shí)低滩,變得復(fù)雜

3.5.2 虛擬機(jī)必須通過(guò)引用得到類(lèi)數(shù)據(jù)的原因

當(dāng)程序在運(yùn)行時(shí)需要轉(zhuǎn)換某個(gè)對(duì)象引用為另一種類(lèi)型時(shí)召夹,虛擬機(jī)必須要檢查這種是否被允許,被轉(zhuǎn)換的對(duì)象是否的確是被引用的對(duì)象或者它的超類(lèi)型委造。(強(qiáng)轉(zhuǎn)的時(shí)候)

當(dāng)程序在執(zhí)行 instanceof 操作時(shí)戳鹅,虛擬機(jī)也進(jìn)行了同樣的檢查。

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

每個(gè)線(xiàn)程都有一個(gè)屬于自己的 PC (程序計(jì)數(shù)器)寄存器昏兆, 它在線(xiàn)程啟動(dòng)的時(shí)候被創(chuàng)建枫虏。

PC 寄存器的大小是一個(gè)字長(zhǎng),它可以持有一個(gè)本地指針或持有一個(gè) returnAddress.

當(dāng)線(xiàn)程在執(zhí)行某個(gè) java 方法時(shí)爬虱, PC 寄存器的內(nèi)容是下一條將要被執(zhí)行指令的 “地址”隶债,這個(gè)地址可以是一個(gè)本地指針,也可以是方法字節(jié)碼中相對(duì)于該方法指令的偏移量跑筝。

當(dāng)線(xiàn)程在執(zhí)行一個(gè)本地方法是死讹, PC 寄存器的值是 “undefined”

3.7 Java 棧

Java 棧也是每個(gè)線(xiàn)程獨(dú)有的, Java 棧上的數(shù)據(jù)都是此線(xiàn)程獨(dú)有的

Java 棧以幀的為單位保存線(xiàn)程的運(yùn)行狀態(tài)曲梗。

虛擬機(jī)直接對(duì) Java 棧執(zhí)行兩種操作:以幀為單位的壓棧和出棧赞警。

某個(gè)線(xiàn)程正在執(zhí)行的方法被稱(chēng)為該線(xiàn)程的當(dāng)前方法,當(dāng)前方法使用的棧幀稱(chēng)為當(dāng)前幀虏两,當(dāng)前方法所屬的類(lèi)稱(chēng)為當(dāng)前類(lèi)愧旦,當(dāng)前類(lèi)的常量池被稱(chēng)為當(dāng)前常量池。

每當(dāng)線(xiàn)程調(diào)用一個(gè) Java 方法時(shí)定罢,虛擬機(jī)會(huì)在該線(xiàn)程的 Java 棧中壓入一個(gè)新棧笤虫,這個(gè)新棧就是當(dāng)前幀。

Java 方法通過(guò)兩種方式完成返回。一是通過(guò)正常的 return 返回琼蚯,另外是拋出異常而終止酬凳。無(wú)論是哪一方式返回,都會(huì)彈出當(dāng)前幀釋放遭庶。

棧幀
jvm_all_5.png

棧幀由三部分組成:局部變量表(Local variables), 操作棧(Operand) 和 棧數(shù)據(jù)區(qū)

局部變量表
局部變量表是以字長(zhǎng)為單位宁仔,從 0 開(kāi)始計(jì)數(shù)的數(shù)組。
類(lèi)型 int, float, reference 和 returnAddress 的值在數(shù)組中只占一個(gè)字長(zhǎng)度罚拟;
long 和 double 占兩個(gè)字長(zhǎng)度台诗。在訪(fǎng)問(wèn)時(shí)只需要范圍第一個(gè)字的索引值即可。

byte, short, char 和 boolean 在局部變量表中用 int 赐俗。

  
   public static int runClassMethod(int i, long l, float f, double d,
                                     Object o, byte b){
        return 0;
    }

    public int runInstanceMethod(char c, double d, short s, boolean b){
        return 0;
    }
    
jvm_all_6.png

注意上圖中拉队, runInstanceMethod 方法第一個(gè)變量是 reference ,指向 this ,代表對(duì)象

操作棧
操作棧也是以字為單位的數(shù)組阻逮。

它通過(guò)壓棧和出棧來(lái)訪(fǎng)問(wèn)粱快。

存儲(chǔ)時(shí) byte, short, char 和 boolean 用 int 表示

Java 虛擬機(jī)運(yùn)行方式是基于棧而不是寄存器的。它的指令是從操作棧中取得叔扼。

虛擬機(jī)把操作棧作為它的工作區(qū)事哭,大多數(shù)指令在操作棧中彈出數(shù)據(jù),執(zhí)行運(yùn)算瓜富,然后把結(jié)果壓回操作棧鳍咱。

幀數(shù)據(jù)區(qū)
幀數(shù)據(jù)區(qū)用來(lái)處理支持常量池解析、正常方法返回已經(jīng)異常派發(fā)機(jī)制的數(shù)據(jù)与柑。

3.8 本地方法接口

本地接口方法也就是 JNI

3.9 本地方法棧

本地方法棧是運(yùn)行本地方法的相關(guān)的數(shù)據(jù)區(qū)

jvm_all_7.png

3.10 執(zhí)行引擎

執(zhí)行引擎是 Java 虛擬機(jī)的核心谤辜。

執(zhí)行引擎可以理解為一個(gè)抽象的規(guī)范,一個(gè)具體的實(shí)現(xiàn)价捧,一個(gè)正在運(yùn)行的實(shí)例丑念。

運(yùn)行中的 Java 程序每一個(gè)線(xiàn)程都是一個(gè)獨(dú)立的虛擬機(jī)執(zhí)行器引擎的實(shí)例。

執(zhí)行引擎包含指令集结蟋,執(zhí)行技術(shù)脯倚,線(xiàn)程等方法的內(nèi)容構(gòu)成。

指令集
指令集是指 Java 虛擬機(jī)中的指令序列構(gòu)成的方法的字節(jié)碼流嵌屎。

執(zhí)行技術(shù)
執(zhí)行技術(shù)包含:解析推正、即時(shí)編譯,自適應(yīng)優(yōu)化

線(xiàn)程
線(xiàn)程模型也屬于執(zhí)行引擎的一部分宝惰。

至此舔稀,我們 Java 虛擬機(jī)系列文章基本完成了,后面會(huì)是垃圾回收機(jī)制的文章

參考

《深入 Java 虛擬機(jī)》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掌测,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汞斧,老刑警劉巖夜郁,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粘勒,居然都是意外死亡竞端,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)庙睡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)事富,“玉大人,你說(shuō)我怎么就攤上這事乘陪⊥程ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵啡邑,是天一觀(guān)的道長(zhǎng)贱勃。 經(jīng)常有香客問(wèn)我,道長(zhǎng)谤逼,這世上最難降的妖魔是什么贵扰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮流部,結(jié)果婚禮上戚绕,老公的妹妹穿的比我還像新娘。我一直安慰自己枝冀,他們只是感情好舞丛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著宾茂,像睡著了一般瓷马。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跨晴,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天欧聘,我揣著相機(jī)與錄音,去河邊找鬼端盆。 笑死怀骤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焕妙。 我是一名探鬼主播蒋伦,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼焚鹊!你這毒婦竟也來(lái)了痕届?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎研叫,沒(méi)想到半個(gè)月后锤窑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嚷炉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年渊啰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片申屹。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绘证,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哗讥,到底是詐尸還是另有隱情嚷那,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布忌栅,位于F島的核電站车酣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏索绪。R本人自食惡果不足惜湖员,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瑞驱。 院中可真熱鬧娘摔,春花似錦、人聲如沸唤反。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)彤侍。三九已至肠缨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盏阶,已是汗流浹背晒奕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留名斟,地道東北人脑慧。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像砰盐,于是被迫代替她去往敵國(guó)和親闷袒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353