class文件結(jié)構(gòu)解析

從學(xué)習(xí)Java語言的第一天起辩昆,我們就被告知與其他語言相比阅酪,Java的一大特點(diǎn)在于它的平臺無關(guān)性,即Write Once, Run Everywhere. 而構(gòu)成平臺無關(guān)性的基石就在于所有JVM都采用了字節(jié)碼作為它們的程序存儲格式卤材,因此今天主要就分析一下class文件的結(jié)構(gòu)遮斥。

知識準(zhǔn)備

在詳細(xì)分析class文件結(jié)構(gòu)之前峦失,我們需要了解一些基本概念:

  • class文件以8字節(jié)為基本單位來進(jìn)行存儲扇丛,中間沒有任何分隔符;
  • 當(dāng)數(shù)據(jù)項(xiàng)需要占用的空間大于8字節(jié)時尉辑,會按照高位在前的方式來進(jìn)行分割帆精;
  • class文件只有兩種數(shù)據(jù)類型:無符號數(shù)、表隧魄;
  • 無符號數(shù)屬于基本數(shù)據(jù)類型卓练,以u1、u2购啄、u4襟企、u8分別代表1個字節(jié)、2個字節(jié)狮含、4個字節(jié)和8個字節(jié)的無符號數(shù)顽悼;
  • 表是由多個無符號數(shù)或者其它表作為數(shù)據(jù)項(xiàng)構(gòu)成的符合數(shù)據(jù)類型,表名習(xí)慣性都以 _info 結(jié)尾几迄。

因此本質(zhì)上整個class文件就是一張表蔚龙,它由以下數(shù)據(jù)項(xiàng)構(gòu)成:

類型 名稱 數(shù)量 描述
u4 magic 1 魔數(shù)
u2 minor_version 1 次版本號
u2 major_version 1 主版本號
u2 constant_pool_count 1 常量個數(shù)
cp_info constant_pool constant_pool_count - 1 具體常量
u2 access_flags 1 訪問標(biāo)志
u2 this_class 1 類索引
u2 super_class 1 父類索引
u2 interfaces_count 1 接口索引
u2 interfaces interfaces_count 具體接口
u2 fields_count 1 字段個數(shù)
field_info fields fields_count 具體字段
u2 methods_count 1 方法個數(shù)
method_info methods methods_count 具體方法
u2 attributes_count 1 屬性個數(shù)
attribute_info attributes attributes_count 具體屬性

可以看到炉菲,這16種數(shù)據(jù)項(xiàng)大致可以分為3類:

  • 3個描述文件屬性的數(shù)據(jù)項(xiàng):魔數(shù)和主次版本號
  • 11個描述類屬性的數(shù)據(jù)項(xiàng):類嗦枢、字段、方法等信息
  • 2個描述代碼屬性的數(shù)據(jù)xiang:

接下來我們就逐一來看看這些數(shù)據(jù)項(xiàng)的含義峰锁。整個分析過程我們將以下面這段代碼對應(yīng)的class文件為基礎(chǔ):

public class JavaTest {

    private static String name = "JVM";

    public static void main(String[] args) {
        System.out.println("Hello " + name);
    }
}
圖1 JavaTest class文件結(jié)構(gòu).png

1.魔數(shù)與版本

每個class文件的頭4個字節(jié)稱為魔數(shù)解孙,用于確定這個文件是否能被虛擬機(jī)所接受坑填。class文件的魔數(shù)值為CAFEBABE。

第5弛姜、6字節(jié)為次版本號脐瑰,7、8字節(jié)為主版本號娱据。Java的主版本號從45開始蚪黑,JDK1.1之后每個大版本發(fā)布盅惜,主版本號加1。高版本的jdk能前向兼容之前版本的class文件忌穿,但不能運(yùn)行以后版本的class文件抒寂。

從圖1可以看到,次版本號為0000掠剑,主版本號為0031屈芜,這說明該class文件可以被1.5及以后版本的jdk運(yùn)行。

2.常量池

緊接著主版本號之后的是常量池入口朴译,由于常量池中常量數(shù)量不固定井佑,因此入口使用第一個u2類型的數(shù)據(jù)代表常量池計(jì)數(shù)值,該計(jì)數(shù)器從1開始眠寿。圖1中常量池計(jì)數(shù)值為0034躬翁,代表常量池中一共有51個常量。

常量池中每一個常量都是一個表盯拱,jdk1.7之后一共有14種類型的常量盒发,他們對應(yīng)著14個不同結(jié)構(gòu)的表,但這14個表都有一個共同特點(diǎn):那就是表開始的第一位是一個u1類型的標(biāo)志位狡逢,代表當(dāng)前常量屬于哪種常量類型宁舰。其取值和含義如下表所示:

類型 標(biāo)志 描述
CONSTANT_Utf8_info 1 UTF-8編碼的字符串
CONSTANT_Integer_info 3 整形字面量
CONSTANT_Float_info 4 浮點(diǎn)型字面量
CONSTANT_Long_info 5 長整型字面量
CONSTANT_Double_info 6 雙精度浮點(diǎn)型字面量
CONSTANT_Class_info 7 類或接口的符號引用
CONSTANT_String_info 8 字符串類型字面量
CONSTANT_Fieldref_info 9 字段的符號引用
CONSTANT_Methodref_info 10 類方法的符號引用
CONSTANT_InterfaceMehtodref_info 11 接口方法的符號引用
CONSTANT_NameAndType_info 12 字段或方法的部分符號引用
CONSTANT_MethodHandle_info 15 方法句柄
CONSTANT_MethodType_info 16 方法類型
CONSTANT_InvokeDynamic_info 18 動態(tài)方法調(diào)用點(diǎn)

這14種常量的結(jié)構(gòu)如下表所示:

常量池變量結(jié)構(gòu)

有了這些基礎(chǔ),我們繼續(xù)分析前面提到的class文件:

image.png

第一個u1類型的變量代表常量類型為0A奢浑,對應(yīng)的表為CONSTANT_Methodref_info蛮艰,表示方法引用,緊接著一個u2類型的變量000C,它表示聲明該方法的類描述符為常量池匯中的第12個常量雀彼,第二個u2類型的變量001D表示指向該方法名稱及類型的描述符為常量池中的第29個常量壤蚜。
按照同樣的方式,下圖給出了前面14個常量的字節(jié)碼详羡,其中前面12個都是指向了常量池中的其它常量仍律,第13、14個常量是兩個類型為1(即UTF-8編碼的常量)实柠,對應(yīng)的英文字符分別為name水泉、Ljava/lang/String.

前14個常量劃分.png
第13個常量.png
第14個常量.png

剩下其他常量的劃分方式是類似的,事實(shí)上窒盐,jdk已經(jīng)為我們提供了專門用于分析class文件的工具javap草则,利用javap -v JavaTest.class得到常量池中的52個常量如下,可以看到蟹漓,前面14個常量的劃分與我們之前分析的完全一致炕横。

bogon:Downloads shiyangsheng$ javap -v JavaTest.class
Classfile /Users/shiyangsheng/Downloads/JavaTest.class
  Last modified 2018-3-17; size 842 bytes
  MD5 checksum fbb2370c6b7413a0636806a0e492224a
  Compiled from "JavaTest.java"
public class com.youzan.shys.advice.JavaTest
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #12.#29        // java/lang/Object."<init>":()V
   #2 = Fieldref           #30.#31        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Class              #32            // java/lang/StringBuilder
   #4 = Methodref          #3.#29         // java/lang/StringBuilder."<init>":()V
   #5 = String             #33            // Hello
   #6 = Methodref          #3.#34         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = Fieldref           #11.#35        // com/youzan/shys/advice/JavaTest.name:Ljava/lang/String;
   #8 = Methodref          #3.#36         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Methodref          #37.#38        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #10 = String             #39            // JVM
  #11 = Class              #40            // com/youzan/shys/advice/JavaTest
  #12 = Class              #41            // java/lang/Object
  #13 = Utf8               name
  #14 = Utf8               Ljava/lang/String;
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               LocalVariableTable
  #20 = Utf8               this
  #21 = Utf8               Lcom/youzan/shys/advice/JavaTest;
  #22 = Utf8               main
  #23 = Utf8               ([Ljava/lang/String;)V
  #24 = Utf8               args
  #25 = Utf8               [Ljava/lang/String;
  #26 = Utf8               <clinit>
  #27 = Utf8               SourceFile
  #28 = Utf8               JavaTest.java
  #29 = NameAndType        #15:#16        // "<init>":()V
  #30 = Class              #42            // java/lang/System
  #31 = NameAndType        #43:#44        // out:Ljava/io/PrintStream;
  #32 = Utf8               java/lang/StringBuilder
  #33 = Utf8               Hello
  #34 = NameAndType        #45:#46        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #35 = NameAndType        #13:#14        // name:Ljava/lang/String;
  #36 = NameAndType        #47:#48        // toString:()Ljava/lang/String;
  #37 = Class              #49            // java/io/PrintStream
  #38 = NameAndType        #50:#51        // println:(Ljava/lang/String;)V
  #39 = Utf8               JVM
  #40 = Utf8               com/youzan/shys/advice/JavaTest
  #41 = Utf8               java/lang/Object
  #42 = Utf8               java/lang/System
  #43 = Utf8               out
  #44 = Utf8               Ljava/io/PrintStream;
  #45 = Utf8               append
  #46 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #47 = Utf8               toString
  #48 = Utf8               ()Ljava/lang/String;
  #49 = Utf8               java/io/PrintStream
  #50 = Utf8               println
  #51 = Utf8               (Ljava/lang/String;)V

由此可見,常量池在class文件中占據(jù)了絕大部分內(nèi)容(中間用紅框框出來的就是常量池內(nèi)容):

常量池內(nèi)容.png

3.訪問標(biāo)志

緊接著常量池之后的兩個字節(jié)表示訪問標(biāo)志葡粒,主要是用來標(biāo)記類或者接口層次的一些屬性份殿。目標(biāo)之定義了16個標(biāo)志位中的8位膜钓,沒有使用到的一律為0。 具體標(biāo)志位如下表:

標(biāo)志名稱 標(biāo)志值 描述
ACC_PUBLIC 0x0001 是否為public類型
ACC_FINAL 0x0010 是否為final類型
ACC_SUPER 0x0020 是否允許使用invokespcial字節(jié)碼指令的新語義卿嘲,jdk1.0.2之后編譯出來的類颂斜,此標(biāo)志都為真
ACC_INTERFACE 0x0200 是否為接口
ACC_ABSTRACT 0x0400 是否為abstract類型(對接口和抽象類來說,此標(biāo)志都為真)
ACC_SYNTHETIC 0x1000 標(biāo)識這個類并非由用戶代碼產(chǎn)生
ACC_ANNOTATION 0x2000 是否是注解
ACC_ENUM 0x4000 是否是枚舉

顯然拾枣,對JavaTest類而言沃疮,只有ACC_PUBLIC、ACC_SUPER兩個標(biāo)志應(yīng)該為真梅肤,因此access_flags=0x0021.

4.類索引司蔬、父類索引和接口索引集合

在訪問標(biāo)志之后,有3個用來確定一個類的繼承關(guān)系的數(shù)據(jù)姨蝴,按先后順序分別是:

  • 類索引:用于確定類的全限定名
  • 父類索引:用于確定父類的全限定名
  • 接口索引:用于描述類實(shí)現(xiàn)了哪些接口
    它們在class文件中的位置如下:
image.png

可見俊啼,類索引為11,父類索引為12似扔,接口索引集合大小為0吨些,根據(jù)前面得到的常量池搓谆,可以知道第11炒辉、12個常量為:

...
#11 = Class              #40            // com/youzan/shys/advice/JavaTest
#12 = Class              #41            // java/lang/Object
...
#40 = Utf8               com/youzan/shys/advice/JavaTest
#41 = Utf8               java/lang/Object
...

5.字段表集合

在接口索引之后是字段表集合,字段表用來描述接口或者類中聲明的變量泉手。它包括類級變量和實(shí)例級變量黔寇,但是不包括局部變量以及從父類和接口中繼承而來的字段。字段表的格式如下:

類型 名稱 數(shù)量 含義
u2 access_flags 1 字段修飾符
u2 name_index 1 字段和方法簡單名稱在常量池中的引用
u2 descriptor_index 1 字段和方法描述符在常量池中的引用
u2 attributes_count 1 描述字段額外信息屬性的個數(shù)
attribute_info attributes attributes_count 具體描述字段的額外信息屬性
5.1字段修飾符

字段修飾符與類中的訪問標(biāo)志很類似斩萌,用來描述字段的一些屬性:

標(biāo)志名稱 標(biāo)志值 描述
ACC_PUBLIC 0x0001 是否為public類型
ACC_PRIVATE 0x0002 是否為private類型
ACC_PROTECTED 0x0004 是否為protected類型
ACC_STATIC 0x0008 是否為static類型
ACC_FINAL 0x0010 是否為final類型
ACC_VOLATILE 0x0040 是否volatile類型
ACC_TRANSIENT 0x0080 是否transient類型
ACC_SYNTHETIC 0x1000 是否由編譯器自動產(chǎn)生
ACC_ENUM 0x4000 是否enum類型
5.2全限定名

把類全路徑中的.替換為/缝裤,同時在最后加入一個;即可。

5.3簡單名稱

簡單名稱指的是沒有類型和修飾符的字段或者方法名稱颊郎。

5.4描述符

描述符用來描述字段的數(shù)據(jù)類型憋飞、方法的參數(shù)列表和返回值。其中基本類型字段的描述符用一個大寫字母來表示姆吭,而對象類型則用字符L加上對象類型的全限定名來表示榛做。具體如下表:

描述符 含義
B 基本類型byte
C 基本類型char
D 基本類型double
F 基本類型float
I 基本類型int
J 基本類型long
S 基本類型short
Z 基本類型boolean
V 基本類型void
L 對象類型,如Ljava/lang/Object

對于數(shù)組類型内狸,每一個維度都是用一個前置的“[”來描述检眯,如java.lang.String[][]類型的二位數(shù)組將被記錄為[[java/lang/String;

描述方法時,將按照先參數(shù)列表昆淡、后返回值的順序來描述锰瘸。其中參數(shù)列表嚴(yán)格按照參數(shù)的順序放在一組小括號()之內(nèi)。例如方法java.lang.String.toString()的描述符為()Ljava/lang/String;

了解了這幾個概念之后昂灵,我們回到JavaTest的class文件:

image.png
  • fields_count=0x0001表明這個類只有一個字段表數(shù)據(jù)避凝;
  • access_flags=0x000A表明ACC_PRIVATE與ACC_STATIC標(biāo)志位為1真舞萄,其它標(biāo)志位為0;
  • name_index=0x000D表明字段簡單名稱為常量池中的第13個常量管削,也就是name鹏氧;
  • descriptor=0x000E表明字段描述符為常量池中的第14個常量,也就是Ljava/lang/String;
  • attributes_count=0x0000表明字段額外屬性個數(shù)為0佩谣;
    由此可以反過來得到該類的一個屬性為 private static String name;
6.方法表集合

對方法描述的方式與對字段描述的方式基本一致把还,方法表的結(jié)構(gòu)也與字段表的結(jié)構(gòu)完全一致,不同之處在于方法的訪問標(biāo)志與字段的訪問標(biāo)志有所區(qū)別茸俭。例如volatile與transient不能修飾方法吊履,但是方法卻有synchronized、native调鬓、strictfp和abstract等屬性艇炎。其具體訪問標(biāo)志如下:

標(biāo)志名稱 標(biāo)志值 描述
ACC_PUBLIC 0x0001 是否為public類型
ACC_PRIVATE 0x0002 是否為final類型
ACC_PROTECTED 0x0004 是否為protected類型
ACC_STATIC 0x0008 是否為static類型
ACC_FINAL 0x0010 是否為final類型
ACC_SYNCHRONIZED 0x0020 是否synchronized類型
ACC_BRIDGE 0x0040 是否橋接方法
ACC_VARARGS 0x0080 是否接收不定參數(shù)
ACC_NATIVE 0x0100 是否native方法
ACC_ABSTRACT 0x0400 是否abstract
ACC_STRICTFP 0x0800 是否strictfp
ACC_SYNTHETIC 0x1000 是否由編譯器自動產(chǎn)生

讓我們繼續(xù)回到class文件:

6.1 第一個方法
第一個方法表結(jié)構(gòu).png
  • methods_count=0x0003表明該類有3個方法;
  • 第一個方法的access_flags=0x0001表明只有ACC_PUBLIC標(biāo)志位為真腾窝;
  • name_index=0x000F表明方法簡單名稱為常量池中的第15個常量缀踪,也就是<init>;
  • descriptor=0x0010表明方法修飾符為常量池中的第16個常量虹脯,也就是()V驴娃;
  • attributes_count=0x0001表明第一個方法有一個額外屬性,且索引值就是其后的0x0011,也就是常量池中的第17個常量Code循集。
  • Code屬性是該方法的具體字節(jié)碼描述唇敞。

由此得到第一個方法為public void init(),這個方法是編譯器自動添加的實(shí)例構(gòu)造器方法咒彤。

Code屬性也是class文件中最重要的一個屬性疆柔,如果把一個Java程序中的信息分為代碼(方法體里的代碼)和元數(shù)據(jù)(描述類、字段镶柱、方法的其他信息)兩部分旷档,那么Code屬性描述的就是代碼的信息,其它所有數(shù)據(jù)都用于描述元數(shù)據(jù)歇拆。由于Code數(shù)據(jù)極其重要也相對復(fù)雜鞋屈,我將在另外一篇文章中單獨(dú)介紹,這里直接給出init()方法的Code屬性在class文件中的表示(簡單來說查吊,前面4個字節(jié)0000 002F表示屬性值的長度谐区,也就是47個字節(jié),也就是說后續(xù)47個字節(jié)都是Code屬性的內(nèi)容):

init方法Code屬性
6.2 第二個方法

第一個方法的Code屬性后面緊跟著的是第二個方法的描述逻卖,同樣的分析方法宋列,不難得出第二個方法為public static void main(String[]);其Code屬性值的長度為0000 004A,也就是74個字節(jié)评也。

第二個方法表結(jié)構(gòu).png
main方法Code屬性.png
6.3 第三個方法

同樣炼杖,很容易得到第三個方法為static clinit void();這個方法是編譯器自動添加的類構(gòu)造器方法灭返,其Code屬性值的長度為0000 001E,也就是30個字節(jié)坤邪。

第三個方法表結(jié)構(gòu).png
clinit方法Code屬性.png

實(shí)際上熙含,這個分析與javap得到的結(jié)果也是一致的。

{
  public com.youzan.shys.advice.JavaTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/youzan/shys/advice/JavaTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: new           #3                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: ldc           #5                  // String Hello
        12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: getstatic     #7                  // Field name:Ljava/lang/String;
        18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        24: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        27: return
      LineNumberTable:
        line 14: 0
        line 15: 27
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      28     0  args   [Ljava/lang/String;

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #10                 // String JVM
         2: putstatic     #7                  // Field name:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 11: 0
}

7.屬性表集合

屬性表集合用于描述某些場景的專有信息艇纺,它一共有21個屬性怎静,屬性表結(jié)構(gòu)如下:

類型 名稱 數(shù)量
u2 attribute_name_index 1
u4 attribute_length 1
u2 info attribute_length

由于涉及屬性太多,這里也不再展開黔衡,只是簡單說明下之類的屬性代表什么意思蚓聘。從class文件可以看出,該類的屬性表集合只有一個元素盟劫,001B表示常量池中的第27個常量夜牡,也就是SourceFile,001C表示常量池中的第28個常量侣签,也就是JavaTest.java塘装,也就是說,SourceFile屬性記錄了生成這個class文件的源碼文件的名稱影所。

屬性表集合.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蹦肴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子型檀,更是在濱河造成了極大的恐慌冗尤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胀溺,死亡現(xiàn)場離奇詭異,居然都是意外死亡皆看,警方通過查閱死者的電腦和手機(jī)仓坞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腰吟,“玉大人无埃,你說我怎么就攤上這事∶停” “怎么了嫉称?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長灵疮。 經(jīng)常有香客問我织阅,道長震捣,這世上最難降的妖魔是什么荔棉? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任闹炉,我火速辦了婚禮,結(jié)果婚禮上润樱,老公的妹妹穿的比我還像新娘渣触。我一直安慰自己,他們只是感情好壹若,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布嗅钻。 她就那樣靜靜地躺著,像睡著了一般店展。 火紅的嫁衣襯著肌膚如雪啊犬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天壁查,我揣著相機(jī)與錄音觉至,去河邊找鬼。 笑死睡腿,一個胖子當(dāng)著我的面吹牛语御,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播席怪,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼应闯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挂捻?” 一聲冷哼從身側(cè)響起碉纺,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刻撒,沒想到半個月后骨田,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡声怔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年态贤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醋火。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡悠汽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芥驳,到底是詐尸還是另有隱情柿冲,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布兆旬,位于F島的核電站假抄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜慨亲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一婚瓜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刑棵,春花似錦巴刻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碍舍,卻和暖如春柠座,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背片橡。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工妈经, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捧书。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓吹泡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親经瓷。 傳聞我的和親對象是個殘疾皇子爆哑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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

  • Java代碼必須要被編譯成class文件后,虛擬機(jī)才能夠加載運(yùn)行舆吮,要搞清楚Java的類加載機(jī)制揭朝,首先必須要理解Cl...
    云飛揚(yáng)1閱讀 9,389評論 2 61
  • 字節(jié)碼查看工具:WinHex 前言 Java虛擬機(jī)實(shí)現(xiàn)語言無關(guān)性的基石就是Class文件Java虛擬機(jī)提供的語言無...
    zlcook閱讀 7,133評論 4 18
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)色冀,斷路器潭袱,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 多少年來,你一直努力取悅別人呐伞、取悅你想要取悅的人敌卓、取悅這個世界,又要多少年後伶氢,你才懂得取悅自己?
    心交朋友錢交丶狗閱讀 77評論 0 1
  • 也許這個世界瘪吏,真的什么也不缺癣防,但是唯獨(dú)缺人!
    抹茶醬木子兮閱讀 138評論 0 0