【Java基礎(chǔ)】類(lèi)加載過(guò)程

要點(diǎn):
1庸疾、類(lèi)加載機(jī)制的原理
2蛛株、程序初始化的順序
3砰诵、類(lèi)加載的代理模式(雙親委托機(jī)制)

一摊欠、類(lèi)加載機(jī)制

JVM把class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)俱箱、準(zhǔn)備国瓮、解析、初始化,最終形成JVM可以直接使用的Java類(lèi)型的過(guò)程乃摹〕Р疲‘

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

1、加載

將class字節(jié)碼文件加載到內(nèi)存中峡懈,并將這些數(shù)據(jù)轉(zhuǎn)換成方法區(qū)中的運(yùn)行時(shí)數(shù)據(jù)(靜態(tài)變量璃饱、靜態(tài)代碼塊、常量池等)肪康,在堆中生成一個(gè)Class類(lèi)對(duì)象代表這個(gè)類(lèi)(反射原理)荚恶,作為方法區(qū)類(lèi)數(shù)據(jù)的訪(fǎng)問(wèn)入口。

類(lèi)的加載原理

2磷支、鏈接

將Java類(lèi)的二進(jìn)制代碼合并到JVM的運(yùn)行狀態(tài)之中谒撼。
? 驗(yàn)證
確保加載的類(lèi)信息符合JVM規(guī)范,沒(méi)有安全方面的問(wèn)題雾狈。
? 準(zhǔn)備
正式為類(lèi)變量(static變量)分配內(nèi)存并設(shè)置類(lèi)變量初始值的階段廓潜,這些內(nèi)存都將在方法區(qū)中進(jìn)行分配。注意此時(shí)的設(shè)置初始值為默認(rèn)值善榛,具體賦值在初始化階段完成辩蛋。
? 解析
虛擬機(jī)常量池內(nèi)的符號(hào)引用替換為直接引用(地址引用)的過(guò)程。

3移盆、初始化

初始化階段是執(zhí)行類(lèi)構(gòu)造器<clinit>()方法的過(guò)程悼院。類(lèi)構(gòu)造器<clinit>()方法是由編譯器自動(dòng)收集類(lèi)中的所有類(lèi)變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊(static塊)中的語(yǔ)句合并產(chǎn)生的。

  • 當(dāng)初始化一個(gè)類(lèi)的時(shí)候咒循,如果發(fā)現(xiàn)其父類(lèi)還沒(méi)有進(jìn)行過(guò)初始化据途、則需要先初始化其父類(lèi)。
  • 虛擬機(jī)會(huì)保證一個(gè)類(lèi)的<clinit>()方法在多線(xiàn)程環(huán)境中被正確加鎖和同步叙甸。

二颖医、Java程序初始化順序

1、父類(lèi)的靜態(tài)變量
2裆蒸、父類(lèi)的靜態(tài)代碼塊
3熔萧、子類(lèi)的靜態(tài)變量
4、子類(lèi)的靜態(tài)代碼塊
5光戈、父類(lèi)的非靜態(tài)變量
6哪痰、父類(lèi)的非靜態(tài)代碼塊
7、父類(lèi)的構(gòu)造方法
8久妆、子類(lèi)的非靜態(tài)變量
9、子類(lèi)的非靜態(tài)代碼塊
10跷睦、子類(lèi)的構(gòu)造方法

/**
 * @ClassName Demo01
 * @Description 測(cè)試程序初始化順序
 * @Author xwd
 * @Date 2018/10/23 21:50
 */
public class Demo01 {
    public static void main(String[] args) {
        B b = new B();
    }
}

class A{

    static String str1 = "父類(lèi)A的靜態(tài)變量";
    String str2 = "父類(lèi)A的非靜態(tài)變量";

    static {
        System.out.println("執(zhí)行了父類(lèi)A的靜態(tài)代碼塊");
    }

    {
        System.out.println("執(zhí)行了父類(lèi)A的非靜態(tài)代碼塊");
    }

    public A(){
        System.out.println("執(zhí)行了父類(lèi)A的構(gòu)造方法");
    }
}

class B extends A{

    static String str1 = "子類(lèi)B的靜態(tài)變量";
    String str2 = "子類(lèi)B的非靜態(tài)變量";

    static {
        System.out.println("執(zhí)行了子類(lèi)B的靜態(tài)代碼塊");
    }

    {
        System.out.println("執(zhí)行了子類(lèi)B的非靜態(tài)代碼塊");
    }

    public B(){
        System.out.println("執(zhí)行了子類(lèi)B的構(gòu)造方法");
    }
}

控制臺(tái)輸出:

程序初始化順序

三筷弦、類(lèi)的引用

1、主動(dòng)引用(一定會(huì)初始化)

  • new一個(gè)類(lèi)的對(duì)象。
  • 調(diào)用類(lèi)的靜態(tài)成員(除了final常量)和靜態(tài)方法烂琴。
  • 使用java.lang.reflect包的方法對(duì)類(lèi)進(jìn)行反射調(diào)用爹殊。
  • 當(dāng)虛擬機(jī)啟動(dòng),java Hello奸绷,則一定會(huì)初始化Hello類(lèi)梗夸。說(shuō)白了就是先啟動(dòng)main方法所在的類(lèi)。
  • 當(dāng)初始化一個(gè)類(lèi)号醉,如果其父類(lèi)沒(méi)有被初始化反症,則先會(huì)初始化他的父類(lèi)

2、被動(dòng)引用

  • 當(dāng)訪(fǎng)問(wèn)一個(gè)靜態(tài)域時(shí)畔派,只有真正聲明這個(gè)域的類(lèi)才會(huì)被初始化铅碍。例如:通過(guò)子類(lèi)引用父類(lèi)的靜態(tài)變量,不會(huì)導(dǎo)致子類(lèi)初始化线椰。
  • 通過(guò)數(shù)組定義類(lèi)引用胞谈,不會(huì)觸發(fā)此類(lèi)的初始化。
  • 引用常量不會(huì)觸發(fā)此類(lèi)的初始化(常量在編譯階段就存入調(diào)用類(lèi)的常量池中了)憨愉。
/**
 * @ClassName Demo02
 * @Description 測(cè)試類(lèi)的引用
 * @Author xwd
 * @Date 2018/10/23 21:58
 */
public class Demo02 {
    public static void main(String[] args) throws ClassNotFoundException {
        //主動(dòng)引用:new一個(gè)類(lèi)的對(duì)象
//        People people = new People();
        //主動(dòng)引用:調(diào)用類(lèi)的靜態(tài)成員(除了final常量)和靜態(tài)方法
//        People.getAge();
//        System.out.println(People.age);
        //主動(dòng)調(diào)用:使用java.lang.reflect包的方法對(duì)類(lèi)進(jìn)行反射調(diào)用
//        Class.forName("pri.xiaowd.classloader.People");


        //被動(dòng)引用:當(dāng)訪(fǎng)問(wèn)一個(gè)靜態(tài)域時(shí)烦绳,只有真正聲明這個(gè)域的類(lèi)才會(huì)被初始化。
//        System.out.println(WhitePeople.age);
        //被動(dòng)引用:通過(guò)數(shù)組定義引用配紫,不會(huì)初始化
//        People[] people = new People[10];
        //被動(dòng)引用:引用常量不會(huì)觸發(fā)此類(lèi)的初始化
        System.out.println(People.num);
    }
    //主動(dòng)調(diào)用:先啟動(dòng)main方法所在的類(lèi)
//    static {
//        System.out.println("main方法所在的類(lèi)在虛擬機(jī)啟動(dòng)時(shí)就加載");
//    }
}

class People{

    static int age = 3;
    static final int num = 20;

    static {
        System.out.println("People被初始化了爵嗅!");
    }

    public People() {
    }

    public static int getAge() {
        return age;
    }

    public static void setAge(int age) {
        People.age = age;
    }
}

class WhitePeople extends People{

    static {
        System.out.println("WhitePeople被初始化了!");
    }
}

四笨蚁、類(lèi)加載器的原理

1睹晒、類(lèi)緩存

標(biāo)準(zhǔn)的Java SE類(lèi)加載器可以按要求查找類(lèi),一旦某個(gè)類(lèi)被加載到類(lèi)加載器中括细,它將維持加載(緩存)一段時(shí)間伪很。不過(guò),JVM垃圾收集器可以回收這些Class對(duì)象奋单。

2锉试、類(lèi)加載器的分類(lèi)

類(lèi)加載器的分類(lèi)

引導(dǎo)類(lèi)加載器(bootstrap class loader)
(1)它用來(lái)加載 Java 的核心庫(kù)(JAVA_HOME/jre/lib/rt.jar,sun.boot.class.path路徑下的內(nèi)容),是用原生代碼(C語(yǔ)言)來(lái)實(shí)現(xiàn)的览濒,并不繼承自 java.lang.ClassLoader呆盖。
(2)加載擴(kuò)展類(lèi)和應(yīng)用程序類(lèi)加載器。并指定他們的父類(lèi)加載器贷笛。

擴(kuò)展類(lèi)加載器(extensions class loader)
(1)用來(lái)加載 Java 的擴(kuò)展庫(kù)(JAVA_HOME/jre/ext/*.jar应又,或java.ext.dirs路徑下的內(nèi)容) 。Java 虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄乏苦。該類(lèi)加載器在此目錄里面查找并加載 Java類(lèi)株扛。
(2)由sun.misc.Launcher$ExtClassLoader實(shí)現(xiàn)尤筐。

應(yīng)用程序類(lèi)加載器(application class loader)
(1)它根據(jù) Java 應(yīng)用的類(lèi)路徑(classpath,java.class.path 路徑下的內(nèi)容)來(lái)加載 Java 類(lèi)洞就。一般來(lái)說(shuō)盆繁,Java 應(yīng)用的類(lèi)都是由它來(lái)完成加載的。
(2)由sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)旬蟋。

自定義類(lèi)加載器
(1)開(kāi)發(fā)人員可以通過(guò)繼承 java.lang.ClassLoader類(lèi)的方式實(shí)現(xiàn)自己的類(lèi)加載器油昂,以滿(mǎn)足一些特殊的需求。

3倾贰、java.class.ClassLoader類(lèi)

(1)作用:

  • java.lang.ClassLoader類(lèi)的基本職責(zé)就是根據(jù)一個(gè)指定的類(lèi)的名稱(chēng)冕碟,找到或者生成其對(duì)應(yīng)的字節(jié)代碼,然后從這些字節(jié)代碼中定義出一個(gè)Java類(lèi)躁染,即java.lang.Class類(lèi)的一個(gè)實(shí)例鸣哀。

  • ClassLoader還負(fù)責(zé)加載 Java 應(yīng)用所需的資源,如圖像文件和配置文件等吞彤。
    (2)常用方法:

  • getParent() 返回該類(lèi)加載器的父類(lèi)加載器我衬。

  • loadClass(String name) 加載名稱(chēng)為 name的類(lèi),返回的結(jié)果是java.lang.Class類(lèi)的實(shí)例饰恕。
    此方法負(fù)責(zé)加載指定名字的類(lèi)挠羔,首先會(huì)從已加載的類(lèi)中去尋找,如果沒(méi)有找到埋嵌;從parent ClassLoader[ExtClassLoader]中加載破加;如果沒(méi)有加載到,則從Bootstrap ClassLoader中嘗試加載(findBootstrapClassOrNull方法), 如果還是加載失敗雹嗦,則自己加載范舀。如果還不能加載,則拋出異常ClassNotFoundException了罪。

  • findClass(String name) 查找名稱(chēng)為 name的類(lèi)锭环,返回的結(jié)果是java.lang.Class類(lèi)的實(shí)例。

  • findLoadedClass(String name) 查找名稱(chēng)為 name的已經(jīng)被加載過(guò)的類(lèi)泊藕,返回的結(jié)果是 java.lang.Class類(lèi)的實(shí)例辅辩。

  • defineClass(String name, byte[] b, int off, int len) 把字節(jié)數(shù)組 b中的內(nèi)容轉(zhuǎn)換成 Java 類(lèi),返回的結(jié)果是java.lang.Class類(lèi)的實(shí)例娃圆。這個(gè)方法被聲明為 final的玫锋。

  • resolveClass(Class<?> c) 鏈接指定的 Java 類(lèi)。

五讼呢、類(lèi)加載器的代理模式

代理模式即是將指定類(lèi)的加載交給其他的類(lèi)加載器撩鹿。常用雙親委托機(jī)制。

1吝岭、雙親委托機(jī)制

某個(gè)特定的類(lèi)加載器接收到類(lèi)加載的請(qǐng)求時(shí)三痰,會(huì)將加載任務(wù)委托給自己的父類(lèi)吧寺,直到最高級(jí)父類(lèi)引導(dǎo)類(lèi)加載器(bootstrap class loader)窜管,如果父類(lèi)能夠加載就加載散劫,不能加載則返回到子類(lèi)進(jìn)行加載。如果都不能加載則報(bào)錯(cuò)幕帆。ClassNotFoundException

雙親委托機(jī)制

雙親委托機(jī)制是為了保證 Java 核心庫(kù)的類(lèi)型安全获搏。這種機(jī)制保證不會(huì)出現(xiàn)用戶(hù)自己能定義java.lang.Object類(lèi)等的情況。例如失乾,用戶(hù)定義了java.lang.String常熙,那么加載這個(gè)類(lèi)時(shí)最高級(jí)父類(lèi)會(huì)首先加載,發(fā)現(xiàn)核心類(lèi)中也有這個(gè)類(lèi)碱茁,那么就加載了核心類(lèi)庫(kù)裸卫,而自定義的永遠(yuǎn)都不會(huì)加載。

值得注意是纽竣,雙親委托機(jī)制是代理模式的一種墓贿,但并不是所有的類(lèi)加載器都采用雙親委托機(jī)制。在tomcat服務(wù)器類(lèi)加載器也使用代理模式蜓氨,所不同的是它是首先嘗試去加載某個(gè)類(lèi)聋袋,如果找不到再代理給父類(lèi)加載器。這與一般類(lèi)加載器的順序是相反的穴吹。

六幽勒、自定義類(lèi)加載器

自定義類(lèi)加載器的流程

(1)首先檢查請(qǐng)求的類(lèi)型是否已經(jīng)被這個(gè)類(lèi)裝載器裝載到命名空間中了,如果已經(jīng)裝載港令,直接返回啥容;否則轉(zhuǎn)入步驟2。
(2)委派類(lèi)加載請(qǐng)求給父類(lèi)加載器顷霹,如果父類(lèi)加載器能夠完成咪惠,則返回父類(lèi)加載器加載的Class實(shí)例;否則轉(zhuǎn)入步驟3泼返。
(3)調(diào)用本類(lèi)加載器的findClass(…)方法硝逢,試圖獲取對(duì)應(yīng)的字節(jié)碼,如果獲取的到绅喉,則調(diào)用defineClass(…)導(dǎo)入類(lèi)型到方法區(qū)渠鸽;如果獲取不到對(duì)應(yīng)的字節(jié)碼或者其他原因失敗,返回異常給loadClass(…)柴罐, loadClass(…)轉(zhuǎn)拋異常徽缚,終止加載過(guò)程(注意:這里的異常種類(lèi)不止一種)。
- 注意:被兩個(gè)類(lèi)加載器加載的同一個(gè)類(lèi)革屠,JVM認(rèn)為是不相同的類(lèi)凿试。

import java.io.*;

/**
 * @ClassName FileSystemClassLoader
 * @Description 自定義文件類(lèi)加載器
 * @Author xwd
 * @Date 2018/10/24 9:23
 */
public class FileSystemClassLoader extends ClassLoader {
    private String rootDir;//根目錄

    public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /**
     * @MethodName findClass
     * @Descrition 加載類(lèi)
     * @Param [name]
     * @return java.lang.Class<?>
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> loadedClass = findLoadedClass(name);//查詢(xún)?cè)擃?lèi)是否已經(jīng)被加載過(guò)
        if(loadedClass != null){  //該類(lèi)已經(jīng)被加載過(guò)了,直接返回
            return loadedClass;
        }else{  //該類(lèi)還沒(méi)有被加載過(guò)
            ClassLoader classLoader = this.getParent();//委派給父類(lèi)加載
            try {
                loadedClass = classLoader.loadClass(name);
            } catch (ClassNotFoundException e) {
//                e.printStackTrace();
            }
            if(loadedClass != null){  //父類(lèi)加載成功,返回
                return loadedClass;
            }else{
                byte[] classData = getClassData(name);
                if(classData == null){
                    throw new ClassNotFoundException();
                }else{
                    loadedClass = defineClass(getName(),classData,0,classData.length);
                }
            }
        }
        return loadedClass;
    }

    /**
     * @MethodName getClassData
     * @Descrition 根據(jù)類(lèi)名獲得對(duì)應(yīng)的字節(jié)數(shù)組
     * @Param [name]
     * @return byte[]
     */
    private byte[] getClassData(String name) {
        //pri.xiaowd.test.A  -->  D:/myjava/pei/xiaowd/test/A.class
        String path = rootDir + "/" + name.replace('.','/') + ".class";
//        System.out.println(path);
        InputStream is = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {
            is = new FileInputStream(path);

            byte[] bytes = new byte[1024];
            int temp = 0;
            while((temp = is.read(bytes)) != -1){
                baos.write(bytes,0,temp);
            }
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if(baos != null){
                    baos.close();
                }
                if(is != null){
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

七排宰、線(xiàn)程上下文類(lèi)加載器

通常當(dāng)你需要?jiǎng)討B(tài)加載資源的時(shí)候 , 你至少有三個(gè) ClassLoader 可以選擇 :
1.系統(tǒng)類(lèi)加載器或叫作應(yīng)用類(lèi)加載器 (system classloader or application classloader)
2.當(dāng)前類(lèi)加載器
3.當(dāng)前線(xiàn)程類(lèi)加載器

? 當(dāng)前線(xiàn)程類(lèi)加載器是為了拋棄雙親委派加載鏈模式。
每個(gè)線(xiàn)程都有一個(gè)關(guān)聯(lián)的上下文類(lèi)加載器那婉。如果你使用new Thread()方式生成新的線(xiàn)程板甘,新線(xiàn)程將繼承其父線(xiàn)程的上下文類(lèi)加載器。如果程序?qū)€(xiàn)程上下文類(lèi)加載器沒(méi)有任何改動(dòng)的話(huà)详炬,程序中所有的線(xiàn)程將都使用系統(tǒng)類(lèi)加載器作為上
下文類(lèi)加載器盐类。
? Thread.currentThread().getContextClassLoader()

八、Tomcat服務(wù)器的類(lèi)加載器

每個(gè) Web 應(yīng)用都有一個(gè)對(duì)應(yīng)的類(lèi)加載器實(shí)例呛谜。該類(lèi)加載器也使用代理模式(不同于前面說(shuō)的雙親委托機(jī)制)在跳,所不同的是它是首先嘗試去加載某個(gè)類(lèi),如果找不到再代理給父類(lèi)加載器隐岛。這與一般類(lèi)加載器的順序是相反的猫妙。但也是為了保證安全,這樣核心庫(kù)就不在查詢(xún)范圍之內(nèi)聚凹。

最后編輯于
?著作權(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
  • 文/不壞的土叔 我叫張陵杖剪,是天一觀的道長(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

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