java類(lèi)加載過(guò)程

1. java類(lèi)加載器

類(lèi)加載器的任務(wù)是根據(jù)一個(gè)類(lèi)的全限定名來(lái)讀取此類(lèi)的二進(jìn)制字節(jié)流到JVM中凳鬓,然后轉(zhuǎn)換為一個(gè)與目標(biāo)類(lèi)對(duì)應(yīng)的java.lang.Class對(duì)象實(shí)例

在虛擬機(jī)提供了3種類(lèi)加載器,引導(dǎo)(Bootstrap)類(lèi)加載器邀摆、擴(kuò)展(Extension)類(lèi)加載器羔挡、系統(tǒng)(System)類(lèi)加載器(也稱(chēng)應(yīng)用類(lèi)加載器)

1.1 啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader)

  • 啟動(dòng)類(lèi)加載器主要加載的是JVM自身需要的類(lèi)洁奈,這個(gè)類(lèi)加載使用C++語(yǔ)言實(shí)現(xiàn)的,是虛擬機(jī)自身的一部分

  • 它負(fù)責(zé)將 <JAVA_HOME>/lib路徑下的核心類(lèi)庫(kù)或-Xbootclasspath參數(shù)指定的路徑下的jar包加載到內(nèi)存中绞灼,注意必由于虛擬機(jī)是按照文件名識(shí)別加載jar包的利术,如rt.jar,如果文件名不被虛擬機(jī)識(shí)別低矮,即使把jar包丟到lib目錄下也是沒(méi)有作用的(出于安全考慮印叁,Bootstrap啟動(dòng)類(lèi)加載器只加載包名為java、javax军掂、sun等開(kāi)頭的類(lèi))轮蜕。

1.2 擴(kuò)展類(lèi)加載器(Extension ClassLoader)

  • 擴(kuò)展類(lèi)加載器是指Sun公司(已被Oracle收購(gòu))實(shí)現(xiàn)的sun.misc.Launcher$ExtClassLoader類(lèi),由Java語(yǔ)言實(shí)現(xiàn)的蝗锥,是Launcher的靜態(tài)內(nèi)部類(lèi)跃洛,它負(fù)責(zé)加載<JAVA_HOME>/lib/ext目錄下或者由系統(tǒng)變量-Djava.ext.dir指定位路徑中的類(lèi)庫(kù),開(kāi)發(fā)者可以直接使用標(biāo)準(zhǔn)擴(kuò)展類(lèi)加載器终议。

1.3 系統(tǒng)類(lèi)加載器(也稱(chēng)應(yīng)用類(lèi)加載器)(Application ClassLoader)

也稱(chēng)應(yīng)用程序加載器是指 Sun公司實(shí)現(xiàn)的sun.misc.Launcher$AppClassLoader汇竭。它負(fù)責(zé)加載系統(tǒng)類(lèi)路徑j(luò)ava -classpath或-D java.class.path 指定路徑下的類(lèi)庫(kù)葱蝗,也就是我們經(jīng)常用到的classpath路徑,開(kāi)發(fā)者可以直接使用系統(tǒng)類(lèi)加載器细燎,一般情況下該類(lèi)加載是程序中默認(rèn)的類(lèi)加載器两曼,通過(guò)ClassLoader#getSystemClassLoader()方法可以獲取到該類(lèi)加載器。

應(yīng)用程序類(lèi)加載器找颓,該加載器是由sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)合愈,該類(lèi)加載器負(fù)責(zé)加載用戶(hù)類(lèi)路徑上所指定的類(lèi)庫(kù)叮贩。開(kāi)發(fā)者可通過(guò)ClassLoader.getSystemClassLoader()方法直接獲取击狮,故又稱(chēng)為系統(tǒng)類(lèi)加載器。當(dāng)應(yīng)用程序沒(méi)有自定義類(lèi)加載器時(shí)益老,默認(rèn)采用該類(lèi)加載器彪蓬。

java.lang.ClassLoader


public static ClassLoader getSystemClassLoader() {

    initSystemClassLoader(); //初始化系統(tǒng)類(lèi)加載器 【見(jiàn)下文】

    if (scl == null) {

        return null;

    }

    SecurityManager sm = System.getSecurityManager();

    if (sm != null) {

        ClassLoader ccl = getCallerClassLoader();

        if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {

            sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);

        }

    }

    return scl;

}

1.4 兩個(gè)class對(duì)象是否為同一個(gè)類(lèi)對(duì)象

在JVM中表示兩個(gè)class對(duì)象是否為同一個(gè)類(lèi)對(duì)象存在兩個(gè)必要條件

  • 類(lèi)的完整類(lèi)名必須一致,包括包名捺萌。

  • 加載這個(gè)類(lèi)的ClassLoader(指ClassLoader實(shí)例對(duì)象)必須相同档冬。

也就是說(shuō),在JVM中桃纯,即使這個(gè)兩個(gè)類(lèi)對(duì)象(class對(duì)象)來(lái)源同一個(gè)Class文件酷誓,被同一個(gè)虛擬機(jī)所加載,但只要加載它們的ClassLoader實(shí)例對(duì)象不同态坦,那么這兩個(gè)類(lèi)對(duì)象也是不相等的盐数,這是因?yàn)椴煌腃lassLoader實(shí)例對(duì)象都擁有不同的獨(dú)立的類(lèi)名稱(chēng)空間,所以加載的class對(duì)象也會(huì)存在不同的類(lèi)名空間中伞梯,

1.5 顯示加載與隱式加載

所謂class文件的顯示加載與隱式加載的方式是指JVM加載class文件到內(nèi)存的方式玫氢,

  • 顯示加載指的是在代碼中通過(guò)調(diào)用ClassLoader加載class對(duì)象,如直接使用Class.forName(name)或this.getClass().getClassLoader().loadClass()加載class對(duì)象谜诫。

  • 隱式加載則是不直接在代碼中調(diào)用ClassLoader的方法加載class對(duì)象漾峡,而是通過(guò)虛擬機(jī)自動(dòng)加載到內(nèi)存中,如在加載某個(gè)類(lèi)的class文件時(shí)喻旷,該類(lèi)的class文件中引用了另外一個(gè)類(lèi)的對(duì)象生逸,此時(shí)額外引用的類(lèi)將通過(guò)JVM自動(dòng)加載到內(nèi)存中。

2. 類(lèi)加載的幾個(gè)階段

2.1 類(lèi)加載簡(jiǎn)述

  • 虛擬機(jī)把描述類(lèi)的數(shù)據(jù)從class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的Java類(lèi)型,這就是虛擬機(jī)類(lèi)的加載機(jī)制

  • 在Java語(yǔ)言里面,類(lèi)型的加載,連接,初始化都是在程序運(yùn)行期間完成的.這種策略雖然稍微增加一點(diǎn)性能開(kāi)銷(xiāo),但是會(huì)為Java應(yīng)用程序提供高度的靈活性,Java天生可以動(dòng)態(tài)擴(kuò)展語(yǔ)言的特性就是依賴(lài)運(yùn)行期間動(dòng)態(tài)加載和動(dòng)態(tài)連接這個(gè)特點(diǎn)實(shí)現(xiàn)的

類(lèi)加載過(guò)程:
java文件編譯過(guò)程.jpeg

從上圖可以看且预,java文件通過(guò)編譯器變成了.class文件槽袄,接下來(lái)類(lèi)加載器又將這些.class文件加載到JVM中。其中類(lèi)裝載器的作用其實(shí)就是類(lèi)的加載辣之。今天我們要討論的就是這個(gè)環(huán)節(jié)掰伸。有了這個(gè)印象之后我們?cè)賮?lái)看類(lèi)的加載的概念:


其實(shí)可以一句話來(lái)解釋?zhuān)侯?lèi)的加載指的是將類(lèi)的.class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中,將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi)怀估,然后在堆區(qū)創(chuàng)建一個(gè) java.lang.Class對(duì)象狮鸭,用來(lái)封裝類(lèi)在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)合搅。

2.2 類(lèi)加載的幾個(gè)階段

類(lèi)從被加載到虛擬機(jī)內(nèi)存中開(kāi)始,到卸載出內(nèi)存為止歧蕉,它的整個(gè)生命周期包括:加載灾部、驗(yàn)證、準(zhǔn)備惯退、解析赌髓、初始化、使用和卸載七個(gè)階段催跪。

它們的順序如下圖所示:
類(lèi)加載階段.jpeg

其中類(lèi)加載的過(guò)程包括了加載锁蠕、驗(yàn)證、準(zhǔn)備懊蒸、解析荣倾、初始化五個(gè)階段。在這五個(gè)階段中骑丸,加載舌仍、驗(yàn)證、準(zhǔn)備和初始化這四個(gè)階段發(fā)生的順序是確定的通危,而解析階段則不一定铸豁,它在某些情況下可以在初始化階段之后開(kāi)始。另外注意這幾個(gè)階段是按順序開(kāi)始菊碟,而不是按順序進(jìn)行或完成节芥,因?yàn)檫@些階段通常都是互相交叉地混合進(jìn)行的,通常在一個(gè)階段執(zhí)行的過(guò)程中調(diào)用或激活另一個(gè)階段框沟。

2.2.1 加載

”加載“是”類(lèi)加機(jī)制”的第一個(gè)過(guò)程藏古,在加載階段,虛擬機(jī)主要完成三件事:

  • (1)通過(guò)一個(gè)類(lèi)的全限定名來(lái)獲取其定義的二進(jìn)制字節(jié)流

  • (2)將這個(gè)字節(jié)流所代表的的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)

  • (3)在堆中生成一個(gè)代表這個(gè)類(lèi)的Class對(duì)象忍燥,作為方法區(qū)中這些數(shù)據(jù)的訪問(wèn)入口拧晕。

相對(duì)于類(lèi)加載的其他階段而言,加載階段是可控性最強(qiáng)的階段梅垄,因?yàn)槌绦騿T可以使用系統(tǒng)的類(lèi)加載器加載厂捞,還可以使用自己的類(lèi)加載器加載。我們?cè)谧詈笠徊糠謺?huì)詳細(xì)介紹這個(gè)類(lèi)加載器队丝。在這里我們只需要知道類(lèi)加載器的作用就是上面虛擬機(jī)需要完成的三件事靡馁,僅此而已就好了。

2.2.2 驗(yàn)證

驗(yàn)證的主要作用就是確保被加載的類(lèi)的正確性机久。也是連接階段的第一步臭墨。說(shuō)白了也就是我們加載好的.class文件不能對(duì)我們的虛擬機(jī)有危害,所以先檢測(cè)驗(yàn)證一下膘盖。他主要是完成四個(gè)階段的驗(yàn)證:

  • (1)文件格式的驗(yàn)證:驗(yàn)證.class文件字節(jié)流是否符合class文件的格式的規(guī)范胧弛,并且能夠被當(dāng)前版本的虛擬機(jī)處理尤误。這里面主要對(duì)魔數(shù)、主版本號(hào)结缚、常量池等等的校驗(yàn)(魔數(shù)损晤、主版本號(hào)都是.class文件里面包含的數(shù)據(jù)信息、在這里可以不用理解)红竭。

  • (2)元數(shù)據(jù)驗(yàn)證:主要是對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析尤勋,以保證其描述的信息符合java語(yǔ)言規(guī)范的要求,比如說(shuō)驗(yàn)證這個(gè)類(lèi)是不是有父類(lèi)茵宪,類(lèi)中的字段方法是不是和父類(lèi)沖突等等最冰。

  • (3)字節(jié)碼驗(yàn)證:這是整個(gè)驗(yàn)證過(guò)程最復(fù)雜的階段,主要是通過(guò)數(shù)據(jù)流和控制流分析眉厨,確定程序語(yǔ)義是合法的锌奴、符合邏輯的兽狭。在元數(shù)據(jù)驗(yàn)證階段對(duì)數(shù)據(jù)類(lèi)型做出驗(yàn)證后憾股,這個(gè)階段主要對(duì)類(lèi)的方法做出分析,保證類(lèi)的方法在運(yùn)行時(shí)不會(huì)做出威海虛擬機(jī)安全的事箕慧。

  • (4)符號(hào)引用驗(yàn)證:它是驗(yàn)證的最后一個(gè)階段服球,發(fā)生在虛擬機(jī)將符號(hào)引用轉(zhuǎn)化為直接引用的時(shí)候。主要是對(duì)類(lèi)自身以外的信息進(jìn)行校驗(yàn)颠焦。目的是確保解析動(dòng)作能夠完成斩熊。

對(duì)整個(gè)類(lèi)加載機(jī)制而言,驗(yàn)證階段是一個(gè)很重要但是非必需的階段伐庭,如果我們的代碼能夠確保沒(méi)有問(wèn)題粉渠,那么我們就沒(méi)有必要去驗(yàn)證,畢竟驗(yàn)證需要花費(fèi)一定的的時(shí)間圾另。當(dāng)然我們可以使用-Xverfity:none來(lái)關(guān)閉大部分的驗(yàn)證霸株。

2.2.3 準(zhǔn)備

準(zhǔn)備階段主要為類(lèi)變量分配內(nèi)存并設(shè)置初始值。這些內(nèi)存都在方法區(qū)分配集乔。在這個(gè)階段我們只需要注意兩點(diǎn)就好了去件,也就是類(lèi)變量和初始值兩個(gè)關(guān)鍵詞:

  • (1)類(lèi)變量(static)會(huì)分配內(nèi)存,但是實(shí)例變量不會(huì)扰路,實(shí)例變量主要隨著對(duì)象的實(shí)例化一塊分配到j(luò)ava堆中尤溜,

  • (2)這里的初始值指的是數(shù)據(jù)類(lèi)型默認(rèn)值,而不是代碼中被顯示賦予的值汗唱。比如

public static int value = 1; //在這里準(zhǔn)備階段過(guò)后的value值為0宫莱,而不是1。賦值為1的動(dòng)作在初始化階段哩罪。

當(dāng)然還有其他的默認(rèn)值授霸。

注意肥印,在上面value是被static所修飾的準(zhǔn)備階段之后是0,但是如果同時(shí)被final和static修飾準(zhǔn)備階段之后就是1了绝葡。我們可以理解為static final在編譯器就將結(jié)果放入調(diào)用它的類(lèi)的常量池中了深碱。

2.2.4 解析

解析階段主要是虛擬機(jī)將常量池中的符號(hào)引用轉(zhuǎn)化為直接引用的過(guò)程。什么是符號(hào)應(yīng)用和直接引用呢藏畅?

  • 符號(hào)引用:以一組符號(hào)來(lái)描述所引用的目標(biāo)敷硅,可以是任何形式的字面量,只要是能無(wú)歧義的定位到目標(biāo)就好愉阎,就好比在班級(jí)中绞蹦,老師可以用張三來(lái)代表你,也可以用你的學(xué)號(hào)來(lái)代表你榜旦,但無(wú)論任何方式這些都只是一個(gè)代號(hào)(符號(hào))幽七,這個(gè)代號(hào)指向你(符號(hào)引用)

  • 直接引用:直接引用是可以指向目標(biāo)的指針、相對(duì)偏移量或者是一個(gè)能直接或間接定位到目標(biāo)的句柄溅呢。和虛擬機(jī)實(shí)現(xiàn)的內(nèi)存有關(guān)澡屡,不同的虛擬機(jī)直接引用一般不同。


解析動(dòng)作主要針對(duì)類(lèi)或接口咐旧、字段驶鹉、類(lèi)方法、接口方法铣墨、方法類(lèi)型室埋、方法句柄和調(diào)用點(diǎn)限定符7類(lèi)符號(hào)引用進(jìn)行。

2.2.5 初始化

這是類(lèi)加載機(jī)制的最后一步伊约,在這個(gè)階段姚淆,java程序代碼才開(kāi)始真正執(zhí)行。我們知道屡律,在準(zhǔn)備階段已經(jīng)為類(lèi)變量賦過(guò)一次值腌逢。在初始化階端,程序員可以根據(jù)自己的需求來(lái)賦值了疹尾。一句話描述這個(gè)階段就是執(zhí)行類(lèi)構(gòu)造器< clinit >()方法的過(guò)程上忍。

在初始化階段,主要為類(lèi)的靜態(tài)變量賦予正確的初始值纳本,JVM負(fù)責(zé)對(duì)類(lèi)進(jìn)行初始化窍蓝,主要對(duì)類(lèi)變量進(jìn)行初始化。在Java中對(duì)類(lèi)變量進(jìn)行初始值設(shè)定有兩種方式:

  • ①聲明類(lèi)變量是指定初始值

  • ②使用靜態(tài)代碼塊為類(lèi)變量指定初始值

JVM初始化步驟

  • 1繁成、假如這個(gè)類(lèi)還沒(méi)有被加載和連接吓笙,則程序先加載并連接該類(lèi)

  • 2、假如該類(lèi)的直接父類(lèi)還沒(méi)有被初始化巾腕,則先初始化其直接父類(lèi)

  • 3面睛、假如類(lèi)中有初始化語(yǔ)句絮蒿,則系統(tǒng)依次執(zhí)行這些初始化語(yǔ)句

類(lèi)初始化時(shí)機(jī):只有當(dāng)對(duì)類(lèi)的主動(dòng)使用的時(shí)候才會(huì)導(dǎo)致類(lèi)的初始化,類(lèi)的主動(dòng)使用包括以下六種:

創(chuàng)建類(lèi)的實(shí)例叁鉴,也就是new的方式

訪問(wèn)某個(gè)類(lèi)或接口的靜態(tài)變量土涝,或者對(duì)該靜態(tài)變量賦值

調(diào)用類(lèi)的靜態(tài)方法

反射(如 Class.forName(“com.shengsiyuan.Test”))

初始化某個(gè)類(lèi)的子類(lèi),則其父類(lèi)也會(huì)被初始化

Java虛擬機(jī)啟動(dòng)時(shí)被標(biāo)明為啟動(dòng)類(lèi)的類(lèi)( JavaTest)幌墓,直接使用 java.exe命令來(lái)運(yùn)行某個(gè)主類(lèi)

好了但壮,到目前為止就是類(lèi)加載機(jī)制的整個(gè)過(guò)程,但是還有一個(gè)重要的概念常侣,那就是類(lèi)加載器蜡饵。在加載階段其實(shí)我們提到過(guò)類(lèi)加載器,說(shuō)是在后面詳細(xì)說(shuō)胳施,在這就好好地介紹一下類(lèi)加載器溯祸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市舞肆,隨后出現(xiàn)的幾起案子焦辅,更是在濱河造成了極大的恐慌,老刑警劉巖胆绊,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氨鹏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡压状,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)跟继,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)种冬,“玉大人,你說(shuō)我怎么就攤上這事舔糖∮榱剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵金吗,是天一觀的道長(zhǎng)十兢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)摇庙,這世上最難降的妖魔是什么旱物? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮卫袒,結(jié)果婚禮上宵呛,老公的妹妹穿的比我還像新娘。我一直安慰自己夕凝,他們只是感情好宝穗,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布户秤。 她就那樣靜靜地躺著,像睡著了一般逮矛。 火紅的嫁衣襯著肌膚如雪鸡号。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天须鼎,我揣著相機(jī)與錄音膜蠢,去河邊找鬼。 笑死莉兰,一個(gè)胖子當(dāng)著我的面吹牛挑围,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播糖荒,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼杉辙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捶朵?” 一聲冷哼從身側(cè)響起蜘矢,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎综看,沒(méi)想到半個(gè)月后品腹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡红碑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年舞吭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片析珊。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡羡鸥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忠寻,到底是詐尸還是另有隱情惧浴,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布奕剃,位于F島的核電站衷旅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纵朋。R本人自食惡果不足惜柿顶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望倡蝙。 院中可真熱鬧九串,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至烤低,卻和暖如春肘交,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扑馁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工涯呻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腻要。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓复罐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親雄家。 傳聞我的和親對(duì)象是個(gè)殘疾皇子效诅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361