Java虛擬機(jī)之Class類文件結(jié)構(gòu)

歡迎關(guān)注微信公眾號(hào): JueCode

正如有一句名言:代碼編譯的結(jié)果從本地機(jī)器碼變?yōu)樽止?jié)碼,是存儲(chǔ)格式發(fā)展的一小步,卻是編程語言發(fā)展的一大步。 Java語言為什么能write once, run anywhere? 這個(gè)其實(shí)是因?yàn)楹透鞣N不同平臺(tái)相關(guān)的虛擬機(jī),這些虛擬機(jī)都可以載入和執(zhí)行同平臺(tái)無關(guān)的字節(jié)碼。今天我們就來學(xué)習(xí)下Class類文件結(jié)構(gòu)的一些知識(shí)。

1.類文件結(jié)構(gòu)

Class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進(jìn)制流,各個(gè)數(shù)據(jù)項(xiàng)目嚴(yán)格按照順序緊湊地排列在Class文件中,中間沒有添加任何分隔符。Class文件中只有兩種數(shù)據(jù)類型:無符號(hào)數(shù)和表。

無符號(hào)數(shù)屬于基本的數(shù)據(jù)類型,有u1, u2, u4, u8,分別代表1個(gè)字節(jié)、2個(gè)字節(jié)、4個(gè)字節(jié)和8個(gè)字節(jié)的無符號(hào)數(shù)。

表則是由多個(gè)無符號(hào)數(shù)或者其他表復(fù)合而成的數(shù)據(jù)類型。所有表都習(xí)慣以_info結(jié)尾。目前有14個(gè)表格類型:

名稱 解釋
CONSTANT_utf8_info utf-8編碼的字符串
CONSTANT_Integer_info 整形字面量
CONSTANT_Float_info 浮點(diǎn)型字面量
CONSTANT_Long_info 長(zhǎng)整型字面量
CONSTANT_Double_info 雙精度浮點(diǎn)型字面量
CONSTANT_Class_info 類或接口的符號(hào)引用
CONSTANT_String_info 字符串類型字面量
CONSTANT_Fieldref_info 字段的符號(hào)引用
CONSTANT_Methodref_info 類中方法的符號(hào)引用
CONSTANT_Interface_Methodref_info 接口中方法的符號(hào)引用
CONSTANT_NameAndType_info 字段或方法的部分符號(hào)引用
CONSTANT_MethodHandle_info 表示方法句柄
CONSTANT_MethodType_info 表示方法類型
CONSTANT_InvokeDynamic_info 表示一個(gè)動(dòng)態(tài)方法調(diào)用點(diǎn)

整個(gè)Class文件是有順序的,整個(gè)格式如下面的表格:

類型 名稱 數(shù)量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attribute_count

Class文件格式都是嚴(yán)格按照上面順序,當(dāng)然有的類型可能沒有,比如一個(gè)類沒有實(shí)現(xiàn)接口,那么interfaces_count 的數(shù)值就為0,后面的interfaces就沒有,以此類推。

下面我們看一個(gè)簡(jiǎn)單的栗子來分析Class文件結(jié)構(gòu)。

package org.fenixsoft.clazz;

public class TestClass{
    private int m;
    public int inc(){
        return m + 1;
    }
}

通過javac TestClass 可以編譯得到TestClass.class文件:

cafe babe 0000 0034 0013 0a00 0400 0f09 0003 0010 
0700 1107 0012 0100 016d 0100 0149 0100 063c 696e 
6974 3e01 0003 2829 5601 0004 436f 6465 0100 0f4c 
696e 654e 756d 6265 7254 6162 6c65 0100 0369 6e63 
0100 0328 2949 0100 0a53 6f75 7263 6546 696c 6501 
000e 5465 7374 436c 6173 732e 6a61 7661 0c00 0700 
080c 0005 0006 0100 1d6f 7267 2f66 656e 6978 736f 
6674 2f63 6c61 7a7a 2f54 6573 7443 6c61 7373 0100 
106a 6176 612f 6c61 6e67 2f4f 626a 6563 7400 2100 
0300 0400 0000 0100 0200 0500 0600 0000 0200 0100 
0700 0800 0100 0900 0000 1d00 0100 0100 0000 052a 
b700 01b1 0000 0001 000a 0000 0006 0001 0000 0003 
0001 000b 000c 0001 0009 0000 001f 0002 0001 0000 
0007 2ab4 0002 0460 ac00 0000 0100 0a00 0000 0600 
0100 0000 0600 0100 0d00 0000 0200 0e

現(xiàn)在看這個(gè)十六進(jìn)制class文件肯定一臉懵*,按照格式來劃分:

//TestCalss.class
cafe babe //MagicNumber
0000 //minor_version
0034 //major_version  52 --- jdk 1.8   (50 --- jdk 1.6)
0013 //constant_pool_count 19(從1開始)
0a00 0400 0f09 0003 0010 0700 1107 0012 0100 016d 0100 0149 0100 063c 696e 6974 
3e01 0003 2829 5601 0004 436f 6465 0100 0f4c 696e 654e 756d 6265 7254 6162 6c65 
0100 0369 6e63 0100 0328 2949 0100 0a53 6f75 7263 6546 696c 6501 000e 5465 7374 
436c 6173 732e 6a61 7661 0c00 0700 080c 0005 0006 0100 1d6f 7267 2f66 656e 6978 
736f 6674 2f63 6c61 7a7a 2f54 6573 7443 6c61 7373 0100 106a 6176 612f 6c61 6e67 
2f4f 626a 6563 74 //常量池 18個(gè)
0021 //access_flags
0003 //this_class
0004 //super_class
0000 //interfaces_count
0001 //fields_count
0002 0005 0006 0000 //fields
0002 //methods_count
0001 0007 0008 0001 0009    //methods
0000001d 00 01 00 01 00 00 00 05 2a b7 00 01 b1 00 00 00 01 00 0a 00 00 00 06 00 
01 00 00 00 03 0001 000b 000c 0001 0009 0000 001f 0002 0001 0000 0007 2ab4 0002 
0460 ac00 0000 0100 0a00 0000 0600 0100 0000 0600 0100 0d00 0000 0200 0e//Code

接下來對(duì)照著這個(gè)十六進(jìn)制class文件和上面的文件格式來挨個(gè)拆解。

2.MagicNumber/version

首先看到前面三個(gè)選項(xiàng),分別是MagicNumber minor_version major_version
其中MagicNumber是固定4個(gè)字節(jié)的常量0xcafebabe.

//TestCalss.class
cafe babe //MagicNumber
0000 //minor_version
0034 //major_version  52 --- jdk 1.8   (50 --- jdk 1.6)

minor_version和major_version描述的是jdk的版本,十六進(jìn)制的34轉(zhuǎn)化為十進(jìn)制就是52,也就是對(duì)應(yīng)jdk 1.8版本,50對(duì)應(yīng)的是jdk 1.6版本,一次類推。

緊接著主次版本號(hào)之后的是常量池。

3.常量池

常量池可以理解為Class文件中的資源倉庫,是占用Class文件空間最大的數(shù)據(jù)項(xiàng)目之一。
常量池中常量的數(shù)量是不固定的,所以在常量池入口放置一項(xiàng)u2類型的數(shù)據(jù)代表常量池容易計(jì)數(shù)值,有個(gè)點(diǎn)需要注意這個(gè)容量計(jì)數(shù)是從1而不是0開始。第0項(xiàng)常量空出來是表達(dá)“不引用任何一個(gè)常量池項(xiàng)目”。
看下我們的栗子, 0x0013即十進(jìn)制的19,代表常量池中有18項(xiàng)常量

0013 //constant_pool_count 19(從1開始)
0a00 0400 0f09 0003 0010 0700 1107 0012 0100 016d 0100 0149 0100 063c 696e 6974 
3e01 0003 2829 5601 0004 436f 6465 0100 0f4c 696e 654e 756d 6265 7254 6162 6c65 
0100 0369 6e63 0100 0328 2949 0100 0a53 6f75 7263 6546 696c 6501 000e 5465 7374 
436c 6173 732e 6a61 7661 0c00 0700 080c 0005 0006 0100 1d6f 7267 2f66 656e 6978 
736f 6674 2f63 6c61 7a7a 2f54 6573 7443 6c61 7373 0100 106a 6176 612f 6c61 6e67 
2f4f 626a 6563 74 //常量池 

常量池中主要存放兩大類常量:字面量和符號(hào)引用。
字面量接近Java中的常量概念,比如字符串,聲明為final的常量值等。
符號(hào)引用包括下面三類:

  • 類和接口的全限定名
  • 字段的名稱和描述符
  • 方法的名稱和描述符

常量池中的每一項(xiàng)常量都是一個(gè)表,不同的表是有不同的結(jié)構(gòu),接下來我們來看看14種表的具體含義:

名稱 標(biāo)志 描述
CONSTANT_utf8_info 1 utf-8編碼的字符串
CONSTANT_Integer_info 3 整形字面量
CONSTANT_Float_info 4 浮點(diǎn)型字面量
CONSTANT_Long_info 5 長(zhǎng)整型字面量
CONSTANT_Double_info 6 雙精度浮點(diǎn)型字面量
CONSTANT_Class_info 7 類或接口的符號(hào)引用
CONSTANT_String_info 8 字符串類型字面量
CONSTANT_Fieldref_info 9 字段的符號(hào)引用
CONSTANT_Methodref_info 10 類中方法的符號(hào)引用
CONSTANT_Interface_Methodref_info 11 接口中方法的符號(hào)引用
CONSTANT_NameAndType_info 12 字段或方法的部分符號(hào)引用
CONSTANT_MethodHandle_info 15 表示方法句柄
CONSTANT_MethodType_info 16 表示方法類型
CONSTANT_InvokeDynamic_info 18 表示一個(gè)動(dòng)態(tài)方法調(diào)用點(diǎn)

通過命令

javap -verbose TestClass

就可以把上面的18個(gè)常量都計(jì)算出來,省得自己挨個(gè)根據(jù)ASCII碼進(jìn)行計(jì)算,得到下面的常量表:

常量池//常量池 18個(gè)
1、0a 0004 000f                  Methodref #4, #15
2、09 0003 0010                  Fieldref  #3, #16
3、07 0011                       Class #17
4、07 0012                       Class #18
5、01 0001 6d                    utf-8 m
6、01 0001 49                    utf-8 I 
7、01 0006 3c 69 6e 69 74 3e     utf-8 <init>
8、01 0003 28 29 56              utf-8 ()V
9、01 0004 43 6f 64 65           utf-8 Code
10、01 000f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65     utf-8 LineNumberTable
11、01 0003 69 6e 63             utf-8 inc
12、01 0003 28 29 49             utf-8 ()I
13、01 000a 53 6f 75 72 63 65 46 69 6c 65        utf-8 SourceFile
14、01 000e 54 65 73 74 43 6c 61 73 73 2e 6a 61 76 61    utf-8 TestClass.java
15、0c 0007 0008                 NameAndType #7:#8
16、0c 0005 0006                 NameAndType #5:#6
17、01 001d 6f 72 67 2f 66 65 6e 69 78 73 6f 66 74 2f 63 6c 61 7a 7a 2f 54 65 73 74 43 6c 61 73 73                            utf-8 org/fenixsoft/clazz/TestClass
18、01 0010 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74      utf-8 java/lang/Object

舉個(gè)栗子,比如第三個(gè)開頭是07,那么就是對(duì)應(yīng)CONSTANT_Class_info這個(gè)info,而CONSTANT_Class_info對(duì)應(yīng)的是下面的數(shù)據(jù)結(jié)構(gòu):

類型 名稱 數(shù)量
u1 tag 1
u2 name_index 1
類型 名稱 數(shù)量
u1 tag 1
u2 length 1
u1 bytes length

那么緊跟07 后面的11就是索引第11項(xiàng)常量的意思,第11項(xiàng)是01 0003 69 6e 63, 其中tag是01,也就是CONSTANT_utf8_info這個(gè)info,它的數(shù)據(jù)結(jié)構(gòu):

類型 名稱 數(shù)量
u1 tag 1
u2 length 1
u1 bytes length

所以,長(zhǎng)度是3,往后數(shù)三個(gè)字節(jié)就是69 6e 63,對(duì)應(yīng)的就是inc,這個(gè)也就是方法的名稱,其他的都是這樣的分析方式:
首先找到tag對(duì)應(yīng)的表數(shù)據(jù)結(jié)構(gòu),然后根據(jù)數(shù)據(jù)結(jié)構(gòu)拆分。

篇幅所限,其他的常量項(xiàng)的結(jié)構(gòu)可以參考深入理解Java虛擬機(jī)。

緊接著常量池后的是訪問標(biāo)志。

4.訪問標(biāo)志

在常量池之后緊接這兩個(gè)字節(jié)是訪問標(biāo)志,識(shí)別一些類或者接口層次的訪問信息:

Class是類或者接口
是否public
是否abstract
是否final

具體的標(biāo)志位和含義如下面表格:

名稱 標(biāo)志值 含義
ACC_PUBLIC 0x0001 是否為public
ACC_FINAL 0x0010 是否為final
ACC_SUPER 0x0020 JDK 1.0.2之后編譯出來的類這個(gè)標(biāo)志都為真
ACC_INTERFACE 0x0200 是否為一個(gè)接口
ACC_ABSTRACT 0x0400 是否為abstract類型
ACC_SYNTHETIC 0x1000 標(biāo)識(shí)這個(gè)類并非由用戶代碼產(chǎn)生
ACC_ANNOTATION 0x2000 是否是注解
ACC_ENUM 0x4000 是否是枚舉

在我們這個(gè)栗子中類是public 是JDK1.8編譯出來的,所以access_flags的值為:ACC_PUBLIC | ACC_SUPER = 0x0021

5.類索引/父類索引/接口索引

在訪問標(biāo)志后分別是this_class/super_class/interfaces_count

0003 //this_class           確定這個(gè)類的全限定名
0004 //super_class          java.lang.Object該值就是0000
0000 //interfaces_count     該類沒有實(shí)現(xiàn)任何接口,接口的索引表不占用任何字節(jié)

有的小伙伴就要急了,上面的0003為什么代表this_class?其實(shí)這個(gè)0003就是在常量池中的索引,回顧前面常量池中第3的索引是:07 0011這個(gè)是CONSTANT_Class_info的數(shù)據(jù)結(jié)構(gòu),指向第17的索引:

01 001d 6f 72 67 2f 66 65 6e 69 78 73 6f 66 74 2f 63 6c 61 7a 7a 2f 54 65 73 74 43 6c 61 73 73

這個(gè)是CONSTANT_utf8_info的數(shù)據(jù)結(jié)構(gòu),對(duì)應(yīng)就是

org/fenixsoft/clazz/TestClass

這個(gè)就是類的全限定名。

其它兩個(gè)的分析以此類推,在這個(gè)例子中沒有實(shí)現(xiàn)接口,所以接口數(shù)量是0,也就沒有后面的interfaces。

緊接著的就是fields_count和fields。

6.字段表集合

字段表field_info用于描述類和接口中聲明的變量。變量包括類級(jí)變量和實(shí)例級(jí)變量,但是不包括方法中的變量。描述字段的信息都有哪些?有作用域(public/private/protect等),static,字段名字,字段數(shù)據(jù)類型,其中可以用布爾類型描述的有:

字段的作用域,public/private/protected
實(shí)例變量還是類變量,static
可變性,final
并發(fā)可見性, volatile
可否被序列化, transient

類似與上面的access_flags, 能用布爾類型表示的定義下面的標(biāo)志位:

名稱 標(biāo)志值
ACC_PUBLIC 0x0001
ACC_PRIVATE 0x0002
ACC_PROTECTED 0x0004
ACC_STATIC 0x0008
ACC_FINAL 0x0010
ACC_VOLATILE 0x0040
ACC_TRANSIENT 0x0080
ACC_SYNTHETIC 0x1000
ACC_ENUM 0x4000

不能用布爾類型描述的有:

字段名字
字段數(shù)據(jù)類型,基本類型/對(duì)象/數(shù)組

字段名稱肯定是索引常量池中的數(shù)據(jù)項(xiàng),字段數(shù)據(jù)類型呢?專門定義了描述符來標(biāo)識(shí)數(shù)據(jù)類型, 對(duì)象類型用字符L加對(duì)象的全限定名來表示:

標(biāo)識(shí)字符 含義 標(biāo)識(shí)字符 含義
B 基本類型byte J 基本類型long
C 基本類型char S 基本類型short
D 基本類型double Z 基本類型boolean
F 基本類型float V 特殊類型void
I 基本類型int L 對(duì)象類型,如L/java/lang/Object

對(duì)于數(shù)組類型,每一個(gè)維度使用一個(gè)前置的“[”字符來描述,如“String[][]”表示為“[[Ljava/lang/String;”

字段表也有專門的結(jié)構(gòu), descriptor_index之后可以跟著屬性表集合存儲(chǔ)一些額外的信息,比如private static int m = 123, 那么可能會(huì)有一項(xiàng)ConstantValue的屬性存儲(chǔ)123這個(gè)值。

類型 名稱 數(shù)量
u2 access_flags 1
u2 name_index 1
u2 descriptor_index 1
u2 attributes_count 1
attribute_info attributes attributes_count

對(duì)于我們的例子TestClass, private int m;

//fields_count
0001 
//fields
0002 //private
0005 //m
0006 //I
0000 //attribute_count

緊跟著字段表之后的就是方法表集合。

7.方法表集合

方法表集合和字段表集合很類似,有一個(gè)區(qū)別就是用描述符描述方法時(shí),需要先參數(shù)列表后返回值,比如

void inc()  ------> ()V

java.lang.String toString(int index) ---> (I)Ljava/lang/String

跟屬性表一樣,方法表也有專門的數(shù)據(jù)結(jié)構(gòu):

類型 名稱 數(shù)量
u2 access_flags 1
u2 name_index 1
u2 descriptor_index 1
u2 attributes_count 1
attribute_info attributes attributes_count

在TestClass中有兩個(gè)方法,一個(gè)是默認(rèn)構(gòu)造函數(shù),一個(gè)是方法inc

//methods_count,編譯器添加的實(shí)例構(gòu)造器<init>和源碼inc()
0002 
//methods
0001    //public
0007    //<init>
0008    //()V
0001            //attribute_count
0009    //Code,存放方法里面的Java代碼
......
//methods
0001      //public 
000b     //inc
000c     //()I
0001     //attribute_count
//Atrribute
//Code
0009    //Code,存放方法里面的Java代碼

其中Code是方法的屬性,用于存放方法的Java代碼編譯成的字節(jié)碼指令。

最后一個(gè)格式就是屬性表集合了。

8.屬性表集合

虛擬機(jī)規(guī)范預(yù)定義的屬性有21項(xiàng),這里簡(jiǎn)單看下常用的幾項(xiàng):

屬性 使用位置 含義
Code 方法表 Java代碼編譯成的字節(jié)碼指令
ConstantValue 字段表 final關(guān)鍵字定義的常量值
LineNumberTable Code屬性 Java源碼的行號(hào)與字節(jié)碼指令的對(duì)應(yīng)關(guān)系
SourceFile 類文件 記錄源文件名稱

屬性表結(jié)構(gòu)

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

其中Code屬性表的結(jié)構(gòu), attribute_name_index是指向常量池的索引,這里就是'Code'.

類型 名稱 數(shù)量
u2 attribute_name_index 1
u4 attribute_length 1
u2 max_stack 1
u2 max_locals 1
u4 code_length 1
u1 code code_length
u2 exception_table_length 1
exception_info exception_table 1
u2 attributes_count 1
attribute_info attributes attributes_count

在我們例子中就是:

//Atrribute
0009 //attribute_name_index--->Code 
0000001d //attribute_length--->29
0001    //max_stack 操作數(shù)棧
0001    //max_locals    局部變量表需要的存儲(chǔ)空間 單位slot
00000005 //code_length 字節(jié)碼長(zhǎng)度
2a b7 00 01 b1 //code 存儲(chǔ)字節(jié)碼指令的一序列字節(jié)流
0000 //exception_table_length
0001 //attributes_count--->Code的屬性
//LineNumberTable描述Java源碼行號(hào)與字節(jié)碼行號(hào)之間的對(duì)應(yīng)關(guān)系
000a //attribute_name_index
00000006    //attribute_length
0001        //line_number_table_length
0000        //start_pc 字節(jié)碼行號(hào)
0003        //Java源碼行號(hào)

//method
0001      //public 
000b     //inc
000c     //()I
0001     //attribute_count
//Atrribute
//Code
0009    //Code,存放方法里面的Java代碼
0009 
0000001f 
0002 
0001 
00000007 
2a b4 00 02 04 60 ac    //code 存儲(chǔ)字節(jié)碼指令的一序列字節(jié)流
0000
0001
//LineNumberTable
000a
00000006
0001
0000
0006
0001
//SourceFile
000d        //SourceFile
00000002
000e

9.總結(jié)

能讀懂Class類文件結(jié)構(gòu)是理解虛擬機(jī)的入門功課,本次分享從一個(gè)簡(jiǎn)單例子詳細(xì)闡述了類文件的結(jié)構(gòu)格式,有一些細(xì)節(jié)沒有仔細(xì)說明,比如屬性表的另外的屬性,還有常量池中數(shù)據(jù)項(xiàng),屬性表中異常表。但是有了上面的知識(shí)儲(chǔ)備,自行分析剩下的就不是什么問題了。

另外,本文的思路和例子也是參考深入理解Java虛擬機(jī): JVM高級(jí)特性與最佳實(shí)踐這本書,很經(jīng)典,建議小伙伴們可以看看。

謝謝大家!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評(píng)論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評(píng)論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評(píng)論 2 372

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