JVM系列之class文件剖析

英属哥伦比亚大学(加拿大)校训:“这是你的思想之地。”


帝都几天的阴雨连绵,心中的热情似乎也被浇灭了,总是感觉有气无力,真的挺渴望阳光的味道。再无力,该做的事还得干,世间的事不可能每件都喜欢,把每件不讨厌的市干习惯了就是会产生依赖感,进而喜欢,这就跟国人夫妻结婚生子过日子一个道理。
本篇是JVM系列开篇,本想搞个深度的剖析,但类文件解析本是繁琐的事情,这几天加班加上心情烦躁,未能全面地梳理,但会尽本人之全力呈现一篇值得阅读的文章。
本篇从以下类文件结构/常量池结构/字段表结构/方法表结构等展示讲解,最后以一个demo进行说明,涉及的东西比较多,会拎出重点的进行讲解。

一 class文件结构

我们知道咱们正常搬砖的地方是.java文件,执行javac命令就会编译成.class字节码文件,这样jvm才能正常解析执行,今天要聊的正是字节码文件。一个class文件由虚拟机指令/符号表/其他辅助信息组成,其数据结构就是无符号数和表。
无符号数:指的是全部二进制位均表示数值,无符号位,第一个"0"或"1"来表示正负;无符号数在class文件中是基本数据类型,均是非负数,用来描述数字、索引引用、数量值、UTF-8编码构成字符串等,包含u1 u2 u4 u8四种,分别代表1个字节、2个字节、4个字节和8个字节。
表:指的是由多个无符号数或其他表作为数据项构成的复合数据类型,以_info结尾,主要用来表示常量池、字段表、方法表等。
附上class文件格式:

译名 数据类型 名称 数量
魔数 u4 magic 1
次版本号 u2 minor_version 1
主版本号 u2 major_version 1
常量池计数器 u2 constant_pool_count 1
常量池 cp_info constant_pool constant_pool_count-1
访问标志 u2 access_flags 1
类索引 u2 this_class 1
父类索引 u2 super_class 1
接口计数器 u2 interfaces_class 1
接口索引集合 u2 interfaces interfaces_count
字段计数器 u2 fields_count 1
字段表集合 field_info fields fields_count
方法计数器 u2 methods_count 1
方法表集合 method_info methods methods_count
属性计数器 u2 attributes_count 1
属性表集合 attribute_info attributes attributes_count

二 常量池

常量池代表class文件中的仓库资源,主要存放两大类常量:字面量和符号引用。
字面量:表示固定值,可以当作常量,通俗理解为等号右边的内容;
符号引用:包含三类常量,分别是类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。
常量池有11种不同的表结构,每一项的第一位都是是一个u1类型的标志位(tag),代表常量类型,结构表单(因简书markdown不支持table标签,无法合并单元格,在此只能用图片替代)如下:

类型 标志 描述
CONSTANT_Utf8_info 1 utf8编码字符串
CONSTANT_Integer_info 3 整型字面量
CONSTANT_Float_info 4 浮点型字面量
CONSTANT_Long_info 5 长整型字面量
CONSTANT_Double_info 6 双精度浮点型字面量
CONSTANT_Class_info 7 类或接口的符号引用
CONSTANT_String_info 8 字符串型字面量
CONSTANT_Fieldref_info 9 字段的符号引用
CONSTANT_Methodref_info 10 类中方法的符号引用
CONSTANT_InterfaceMethodref_info 11 接口中方法的符号引用
CONSTANT_NameAndType_info 12 字段或方法的部分符号引用
CONSTANT_MethodHandle_info 15 标识方法句柄
CONSTANT_MethodType_info 16 标识方法类型
CONSTANT_InvokeDynamic_info 18 表示一个动态方法调用点
常量池结构表1.png
常量池结构表2.png

三 访问标记

紧接着常量池之后的两个字节(u2)代表访问标志(access_flags),用于识别一些类或接口层次的访问信息,表单如下:

名称 说明
ACC_PUBLIC 0X0001 public类型
ACC_FINAL 0X0010 声明final,只有类可设置
ACC_SUPER 0X0020 使用invokespecial指令新语义,编译后类的这个标识为真
ACC_INTERFACE 0X0200 接口
ACC_ABSTRACT 0X0400 接口或抽象类此值为真,其他为假
ACC_SYNTHETIC 0X1000 标识此类并非为用户代码生成
ACC_ANNOTATION 0X2000 注解
ACC_ENUM 0X4000 枚举

四 索引顺序

在访问标记之后,有三项来确定该类的继承关系,按顺序依次为:
类索引(this):描述类的全限定名
父类索引(super):描述父类的全限定名
接口索引集合(interfaces):描述类实现的接口集合。

五 字段表集合

在接口索引集合之后是字段计数器,用来标识有多少个字段,紧接着就是字段表集合,字段表用来描述接口或者类中声明的变量。它包括类级变量和实例级变量,但不包括局部变量以及从父类和接口中继承而来的字段。
字段表的格式如下:

名称 类型 数量 描述
access_flags u2 1 字段修饰符
name_index u2 1 字段和方法名称在常量池中的引用
descriptor_index u2 1 字段和方法描述符在常量池中的引用
attribute_count u2 1 字段额外信息属性的个数
attributes attribute_info attribute_count 字段的额外信息属性

字段修饰符如下:

名称 数值 含义
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 0X0100 是否由编译器自动生成
ACC_ENUM 0X0400 是否枚举

全限定名
类全路径中的"."替换为"/",如:org/xwz/demo/jvm/classfile/Test;
简单名称
指的是没有类型和修饰符的字段或者方法名称;
描述符
描述字段的数据类型、方法的参数列表和返回值,其中基本类型字段的描述符用一个大写字母来标识,对象类型用"L"加上类全限定名来标识。
字段描述符如下:

描述符 含义
B 基本类型byte
C 基本类型char
D 基本类型double
F 基本类型float
I 基本类型int
J 基本类型long
S 基本类型short
Z 基本类型boolean
V 特殊类型void
L 对象类型,如Ljava/lang/Object
[ 数组类型,如[java/lang/String

六 方法表集合

类文件对方法描述与对字段描述几乎采用完全一致的方式,其结构也完全一致,不同之处在于访问标志有所区别,如方法具有字段不具备的特有修饰,像native/synchronized等,同理字段也具备特别的修饰像volatile等。
方法表访问标志如下:

名称 数值 含义
ACC_PUBLIC 0X0001 是否public
ACC_PRIVATE 0X0002 是否private
ACC_PROTECTED 0X0004 是否protected
ACC_STATIC 0X0008 是否static
ACC_FINAL 0X0010 是否final
ACC_SYNCHRONIZED 0X0020 是否synchronized
ACC_BRIDGE 0X0040 是否由编译器产生的桥接方法
ACC_VARARGS 0X080 是否接受不定参数
ACC_NATIVE 0X0100 是否native
ACC_ABSTRACT 0X0400 是否abstract
ACC_STRICTFP 0X0800 是否strictfp
ACC_SYNTHETIC 0X1000 是否由编译器自动产生

七 属性表集合

Class文件、字段表、方法表、属性表都可以携带自己的属性表集合,用 于描述某些场景专有的信息。
属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
info u1 attribute_length

属性列表如下:

名称 位置 含义
Code 方法表 编译后的字节码指令
ConstantValue 字段表 final定义的常量值
Deprecated 类、字段表、方法表 声明deprecated的方法和字段
Exceptions 方法表 方法抛出的异常
EnclosingMethod 类文件 标识这个类所在的外围方法,仅当一个类为局部类或者匿名类时才拥有此属性
InnerClasses 类文件 内部类列表
LineNumberTable Code属性 Java源码的行号与字节码指令的对应关系
LocalVariableTable Code属性 方法的局部变量描述
StackMapTable Code属性 JDK1.6中新增的属性,供新的类型检查验证器(Type Checker)检查和处理目标方法的局部变量和操作数栈所需要的类型是否匹配
SourceFile 类文件 记录源文件名称
Signature 类、方法表、字段表 JDK1.5中新增的属性,用于支持泛型下的方法签名,在Java语言中,任何类、 接口、初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数化类型(Parameterized Types),则Signature属性会为它记录泛型签名信息。由于Java的泛型采用擦除法实现,在为了避免类型信息被擦除后导致签名混乱,需要这个属性记录泛型中的相关信息。
SourceDebugExtension 类文件 JDK1.6中新增的属性,用于存储额外的调试信息
Synthetic 类、方法表、字段表 标识方法或字段为编译器自动生成的
LocalVariableTypeTable JDK1.5中新增的属性,使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加
RuntimeVisibleAnnotations 类、方法表、字段表 JDK1.5新增的属性,为动态注解提供支持,用于注明哪些注解是运行时(实际上运行时就是进行反射调用)可见的
RuntimeInvisibleAnnotations 类、方法表、字段表 JDK1.5新增的属性,用于指明哪些注解是运行时不可见的
RuntimeVisibleParameterAnnotations 方法表 JDK1.5新增的属性,作用与RuntimeVisibleAnnotations属性类似,只不过作用对象为方法参数
RuntimeInvisibleParameterAnnotations 方法表 JDK1.5新增的属性,作用与RuntimeInvisibleAnnotations属性类似,只不过作用对象为方法参数
AnnotationDefault 方法表 JDK1.5新增的属性,用于记录注解类元素的默认值
BootstrapMethods 类文件 JDK1.7中新增的属性,用于保存invokedynamic指令引用的引导方法限定符

下面说下属性表中的重点属性:
Code属性
方法体中的代码经过Javac编译处理后,最终变为字节码指令,存储在方法表的属性集合Code属性中,但并非所有方法表都有Code属性,如抽象类或接口。
Code属性表结构如下:

名称 类型 数量 含义
attribute_name_index u2 1 指向CONSTANT_Utf8_info类型常量的值固定为"Code"
attribute_length u4 1 标识属性值的总长度
max_stack u2 1 代表了操作数栈(Operand Stacks)深度的最大值
max_locals u2 1 代表了局部变量所表示的存储空间
code_length u4 1 字节码指令长度
code u1 code_length 存储编译后产生的字节码指令
exception_table_length u2 1
exception_table exception_info exception_table_length
attribute_count u2
attributes attribute_info attribute_count

Exceptions属性
在方法表中与Code属性平级的一项属性,作用是列举出方法中可能抛出的受检查异常(Checked Exceptions)。
Exceptions属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
number_of_exceptions u2 1
exception_index_table u2 number_of_exceptions

LineNumberTable属性
描述Java源码行号与字节码行号(字节码的偏移量)之间的对应关系,可以在编译的时候分别使用-g:none和-g:lines选项来取消或者要求生成这项信息。
LineNumberTable属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
line_number_table_length u2 1
line_number_table line_number_info line_number_table_length

** LocalVariableTable属性**
描述栈帧中局部变量表中的变量与Java源码中定义的变量之间的关系。
LocalVariableTable属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
local_varible_table_length u2 1
local_variable_table local_variable_info local_varible_table_length

局部变量表结构如下:

名称 类型 数量 含义
start_pc u2 1 代表局部变量的生命周期开始的字节码偏移量
length u2 1 代表局部变量的生命周期作用范围覆盖的长度
name_index u2 1 指向常量池中CONSTANT_Utf8_info型常量的索引,代表局部变量的名称
descriptor_index u2 1 指向常量池中CONSTANT_Utf8_info型常 量的索引,代表局部变量的描述符
index u2 1 局部变量在栈帧局部变量表中Slot的位置,当这个变量数据类型是64位类型时(double和long),它占用的Slot为index和index+1两个

SourceFile属性
记录生成这个Class文件的源码文件名称,sourcefile_index数据项是指向常量池中CONSTANT_Utf8_info型常量的索引,常量值是源码文件的文件名。
SourceFile属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
sourcefile_index u2 1

ConstantValue属性
作用是通知虚拟机自动为静态变量赋值,只有被static关键字修饰的常量(类变量)才可以使用这项属性。目前Sun Javac编译器的选择是:如果同时使用final和static 来修饰一个变量,并且这个变量的数据类型是基本类型或者String的话,就生成ConstantValue属性来进行初 始化,如果这个变量没有被final修饰,或者并非基本类型及字符串,则将会选择在<clinit>方法中进行初始化。
ConstantValue属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
constantvalue_index u2 1

InnerClasses属性
用于记录内部类与宿主类之间的关联关系,"number_of_classes"代表需要记录多少个内部类信息。
InnerClasses属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
number_of_classes u2 1
inner_classes inner_classes_info number_of_classes

inner_classes_info表结构如下:

名称 类型 数量 含义
inner_class_info_index u2 1 指向常量池中CONSTANT_Class_info型常量的索引,代表内部类的符号引用
outer_class_info_index u2 1 指向常量池中CONSTANT_Class_info型常量的索引,代表宿主类的符号引用
inner_name_index u2 1 代表内部类的名称
inner_class_access_flags u2 1 内部类的访问标志

内部类访问标志如下:

名称 数值 含义
ACC_PUBLIC 0X0001 是否public
ACC_PRIVATE 0X0002 是否private
ACC_PROTECTED 0X0004 是否protected
ACC_STATIC 0X0008 是否static
ACC_FINAL 0X0010 是否final
ACC_INTERFACE 0X0040 是否interface
ACC_ABSTRACT 0X080 是否abstract
ACC_SYNTHETIC 0X0100 是否非用户代码产生
ACC_ANNOTATION 0X0400 是否是一个注解
ACC_ENUM 0X0800 是否是一个枚举

Deprecated和Synthetic属性
两者都属于标志类型的布尔属性,只存在有和没有的区别,没有属性值的概念。Deprecated代表已经不再推荐使用;Synthetic代表字段或者方法并不是由Java源码直接产生的,而是由编译器自行添加的。
其属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u2 1

StackMapTable属性
在JDK1.6发布后增加到Class文件规范中,它是一个复杂的变长属性,位于Code属性的属性表中,会在虚拟机类加载的字节码验证阶段被新类型检查验证器(Type Checker)使用,目的在于代替以前比较消耗性能的基于数据流分析的类型推导验证器;一个方法的Code属性最多只能有一个StackMapTable属性。
StackMapTable属性表结构如下:

名称 类型 数量
attribute_name_index u2 1
attribute_length u4 1
number_of_entries u2 1
stack_map_frame stack_map_frame entries 1

费了九牛二虎之力,终于把理论部分整理完毕,是时候该整个demo让咱们一起玩玩真实的。说句实话,能把上面的部分看完,看到这里的是真英雄,会有一种“众里寻他千百度,蓦然回首那人却在灯火阑珊处”的感觉。
demo会分三个部分展示,其一是Java源文件;jdk提供的用于分析class文件的工具javap命令,用"javap -v xxx.class"打开查看字节码情况;其三使用文档工具打开字节码文件的16进制查看,Windows推荐notepad++(需要安装插件),Mac推荐sublime,这里使用sublime,具体演示情况请下阅。
demo展示Java源文件如下:

package org.xwz.xwzdemo.jvm.classfile;

import java.io.Serializable;

/**
 * 解析class文件的演示类
 * 1/继承一个类,实现两个接口
 * */
public class ReadClass extends Exception implements Runnable,Serializable {

    //常量信息
    private final static String XWZ_NAME = "阿伦故事";

    //public修饰int
    public int xwz_age = 29;

    //transient修饰boolean
    transient boolean isMale = true;

    //private变量
    private String address;

    //静态代码块
    static {
        long girlFriends = 8;
    }

    //有参构造
    ReadClass(String address){
        this.address = address;
    }

    //类方法
    static void initXwz(){
        System.out.println("---initXwz method---");
    }

    //普通方法
    public void whoAmI(){
        System.out.println("---who am i---");
    }

    //实现方法
    @Override
    public void run() {
        System.out.println("---this is run method");
    }
}

javap展示字节码文件如下:

Classfile /Users/bjqxdn0921/xwz-test/xwz-demo/src/main/java/org/xwz/xwzdemo/jvm/classfile/ReadClass.class
  Last modified 2019-8-13; size 846 bytes
  MD5 checksum f534aebea36571f07dcc45a7b348cc1b
  Compiled from "ReadClass.java"
public class org.xwz.xwzdemo.jvm.classfile.ReadClass extends java.lang.Exception implements java.lang.Runnable,java.io.Serializable
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #12.#34        // java/lang/Exception."<init>":()V
   #2 = Fieldref           #11.#35        // org/xwz/xwzdemo/jvm/classfile/ReadClass.xwz_age:I
   #3 = Fieldref           #11.#36        // org/xwz/xwzdemo/jvm/classfile/ReadClass.isMale:Z
   #4 = Fieldref           #11.#37        // org/xwz/xwzdemo/jvm/classfile/ReadClass.address:Ljava/lang/String;
   #5 = Fieldref           #38.#39        // java/lang/System.out:Ljava/io/PrintStream;
   #6 = String             #40            // ---who am i---
   #7 = Methodref          #41.#42        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #8 = String             #43            // ---this is run method
   #9 = Long               8l
  #11 = Class              #44            // org/xwz/xwzdemo/jvm/classfile/ReadClass
  #12 = Class              #45            // java/lang/Exception
  #13 = Class              #46            // java/lang/Runnable
  #14 = Class              #47            // java/io/Serializable
  #15 = Utf8               XWZ_NAME
  #16 = Utf8               Ljava/lang/String;
  #17 = Utf8               ConstantValue
  #18 = String             #48            // 阿伦故事
  #19 = Utf8               xwz_age
  #20 = Utf8               I
  #21 = Utf8               isMale
  #22 = Utf8               Z
  #23 = Utf8               address
  #24 = Utf8               <init>
  #25 = Utf8               (Ljava/lang/String;)V
  #26 = Utf8               Code
  #27 = Utf8               LineNumberTable
  #28 = Utf8               whoAmI
  #29 = Utf8               ()V
  #30 = Utf8               run
  #31 = Utf8               <clinit>
  #32 = Utf8               SourceFile
  #33 = Utf8               ReadClass.java
  #34 = NameAndType        #24:#29        // "<init>":()V
  #35 = NameAndType        #19:#20        // xwz_age:I
  #36 = NameAndType        #21:#22        // isMale:Z
  #37 = NameAndType        #23:#16        // address:Ljava/lang/String;
  #38 = Class              #49            // java/lang/System
  #39 = NameAndType        #50:#51        // out:Ljava/io/PrintStream;
  #40 = Utf8               ---who am i---
  #41 = Class              #52            // java/io/PrintStream
  #42 = NameAndType        #53:#25        // println:(Ljava/lang/String;)V
  #43 = Utf8               ---this is run method
  #44 = Utf8               org/xwz/xwzdemo/jvm/classfile/ReadClass
  #45 = Utf8               java/lang/Exception
  #46 = Utf8               java/lang/Runnable
  #47 = Utf8               java/io/Serializable
  #48 = Utf8               阿伦故事
  #49 = Utf8               java/lang/System
  #50 = Utf8               out
  #51 = Utf8               Ljava/io/PrintStream;
  #52 = Utf8               java/io/PrintStream
  #53 = Utf8               println
{
  public int xwz_age;
    descriptor: I
    flags: ACC_PUBLIC

  transient boolean isMale;
    descriptor: Z
    flags: ACC_TRANSIENT

  org.xwz.xwzdemo.jvm.classfile.ReadClass(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Exception."<init>":()V
         4: aload_0
         5: bipush        29
         7: putfield      #2                  // Field xwz_age:I
        10: aload_0
        11: iconst_1
        12: putfield      #3                  // Field isMale:Z
        15: aload_0
        16: aload_1
        17: putfield      #4                  // Field address:Ljava/lang/String;
        20: return
      LineNumberTable:
        line 23: 0
        line 13: 4
        line 15: 10
        line 24: 15
        line 25: 20

  public void whoAmI();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #6                  // String ---who am i---
         5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 28: 0
        line 29: 8

  public void run();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #8                  // String ---this is run method
         5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 33: 0
        line 34: 8

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=2, locals=2, args_size=0
         0: ldc2_w        #9                  // long 8l
         3: lstore_0
         4: return
      LineNumberTable:
        line 20: 0
        line 21: 4
}
SourceFile: "ReadClass.java"

sublime展示字节码文件如下:

cafe babe 0000 0034 0036 0a00 0c00 2209
000b 0023 0900 0b00 2409 000b 0025 0900
2600 2708 0028 0a00 2900 2a08 002b 0500
0000 0000 0000 0807 002c 0700 2d07 002e
0700 2f01 0008 5857 5a5f 4e41 4d45 0100
124c 6a61 7661 2f6c 616e 672f 5374 7269
6e67 3b01 000d 436f 6e73 7461 6e74 5661
6c75 6508 0030 0100 0778 777a 5f61 6765
0100 0149 0100 0669 734d 616c 6501 0001
5a01 0007 6164 6472 6573 7301 0006 3c69
6e69 743e 0100 1528 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 2956 0100 0443
6f64 6501 000f 4c69 6e65 4e75 6d62 6572
5461 626c 6501 0006 7768 6f41 6d49 0100
0328 2956 0100 0372 756e 0100 083c 636c
696e 6974 3e01 000a 536f 7572 6365 4669
6c65 0100 0e52 6561 6443 6c61 7373 2e6a
6176 610c 0018 001d 0c00 1300 140c 0015
0016 0c00 1700 1007 0031 0c00 3200 3301
000e 2d2d 2d77 686f 2061 6d20 692d 2d2d
0700 340c 0035 0019 0100 152d 2d2d 7468
6973 2069 7320 7275 6e20 6d65 7468 6f64
0100 276f 7267 2f78 777a 2f78 777a 6465
6d6f 2f6a 766d 2f63 6c61 7373 6669 6c65
2f52 6561 6443 6c61 7373 0100 136a 6176
612f 6c61 6e67 2f45 7863 6570 7469 6f6e
0100 126a 6176 612f 6c61 6e67 2f52 756e
6e61 626c 6501 0014 6a61 7661 2f69 6f2f
5365 7269 616c 697a 6162 6c65 0100 0ce9
98bf e4bc a6e6 9585 e4ba 8b01 0010 6a61
7661 2f6c 616e 672f 5379 7374 656d 0100
036f 7574 0100 154c 6a61 7661 2f69 6f2f
5072 696e 7453 7472 6561 6d3b 0100 136a
6176 612f 696f 2f50 7269 6e74 5374 7265
616d 0100 0770 7269 6e74 6c6e 0021 000b
000c 0002 000d 000e 0004 001a 000f 0010
0001 0011 0000 0002 0012 0001 0013 0014
0000 0080 0015 0016 0000 0002 0017 0010
0000 0004 0000 0018 0019 0001 001a 0000
003d 0002 0002 0000 0015 2ab7 0001 2a10
1db5 0002 2a04 b500 032a 2bb5 0004 b100
0000 0100 1b00 0000 1600 0500 0000 1700
0400 0d00 0a00 0f00 0f00 1800 1400 1900
0100 1c00 1d00 0100 1a00 0000 2500 0200
0100 0000 09b2 0005 1206 b600 07b1 0000
0001 001b 0000 000a 0002 0000 001c 0008
001d 0001 001e 001d 0001 001a 0000 0025
0002 0001 0000 0009 b200 0512 08b6 0007
b100 0000 0100 1b00 0000 0a00 0200 0000
2100 0800 2200 0800 1f00 1d00 0100 1a00
0000 2100 0200 0200 0000 0514 0009 3fb1
0000 0001 001b 0000 000a 0002 0000 0014
0004 0015 0001 0020 0000 0002 0021 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容