Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言. Java 技术具有卓越的通用性, 高效性, 平台移植性和安全性, 广泛应用于 PC, 数据中心, 游戏控制台, 科学超级计算机, 移动电话和互联网, 同时拥有全球最大的开发者专业社群.
给你学习路线: html-CSS-js-jq-javase - 数据库 - jsp-servlet-Struts2-hibernate-mybatis-spring4-springmvc-ssh-ssm
每一个 class 字节码文件都唯一对应一个类或接口, class 文件中记录中类或接口的基本信息, 但反之不成立, 不是每一个类或接口都有一个唯一对应的字节码文件, 首先类或接口的字节码可以不以文件的方式存储, 可以直接从内存中生成字节码, 而不产生. class 文件, 动态代理的原理就是直接内存中生成字节码流, 根据加载字节码流进行类加载操作, 类实例化, 生成代理对象.
小编推荐一个学 Java 的学习裙[ 七六零, 二五零, 五四一 ] , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
字节码文件记录的信息: 魔术, class 文件主次版本, 常量池数量及常量池表, 类或接口的访问标志, 类索引, 超类索引, 接口数量及接口表, 字段数量及字段表, 方法数量及方法表, 属性属性及属性表, jvm 中使用类 c 结构体表示每一种属性, 结构体中类型种类有两种, 无符号数及表, 以 _info 结尾表示表, 以 u1,u2,u4,u8 分别表示 1 字节, 2 字节, 4 字节, 8 字节无符号数
- ClassFile{
- u4 magic;
- u2 minor_version;
- u2 major_version;
- u2 constant_pool_count;
- cp_info constant_pool[constant_pool_count];
- u2 acc_flags;
- u2 this_class;
- u2 super_class;
- u2 interfaces_count;
- u2 interfaces[interfaces_count];
- u2 fields_count;
- field_info fields[fields_count];
- u2 methods_count;
- method_info methods[methods_count];
- u2 attributes_count;
- attribute_info attributes[attributes_count];
- }
魔术: 四个字节, 用于定义此字节码文件是否符合虚拟机规范, 保证字节码文件不会威胁虚拟机的安全, 若为 cafebabe 则表示字节码符合虚拟机规范
主次版本号: 四个字节, 前两字节表示次版本号, 后两字节表示主版本号, 用于定义编译的字节码文件格式版本, 低版本虚拟机拒绝运行高版本字节码文件, 但高版本虚拟机会向下兼容低版本字节码文件
常量池数量及常量池表: 这部分主要统计类或接口的字面量和符号引用, 用于每个类或接口拥有的字面量和符号引用属性不一定相同, 所有需要两个字节的长度来表示常量池数目, 常量池数目计数从 1 开始, 比如类或接口中总共有两个字面量符号引用, 则常量池数目为 2, 注意, 不是从 0 开始计数, 0 可能另有用处, 可以用来表示类或接口中未出现的引用, 用来表示超级父类 java.long.Object 全限定名的索引, 常量池表是一个数组, 一共有 18 种类型, 每一种类型有一个 tag 属性与之对应, constant_utf8_info 用于表示文本字符串, 类和接口全限定名, 字段名称及描述符, 方法名称及描述符等常量信息, constant_integer_info 用于存储 int 类型的常量信息, 只存储 int 类型的值, 不存储其他符合引用信息, 比如 final int a=1 符号引用信息为 a, 值为 1,constant_float_info 用于存储 float 类型常量信息, 也是只存储 float 值, 不存储引用信息, constant_long_info 用于存储 long 类型的常量信息, constant_double_info 用于存储 double 类型的常量信息, constant_class_info 用于存储指向常量池列表 constant_unf8_info 类和接口全限定名的有效引用, constant_string_info 用于存储指定常量池列表 constant_utf8_info 某常量项的有效索引, 指向文本字符串, constant_fieldref_info 用于存储指向常量池列表 constant_class_info 常量项和 constant_nameandtype_info 常量项的有效索引, constant_methodref_info 用于存储指向常量池列表 constant_class_info 常量项和 constant_nameandtype_info 常量项的有效索引, constant_interfacemethodref_info 用于存储指向常量池列表 constant_class_info 常量项和 constant_nameandtype_info 常量项的有效索引, constant_nameandtype_info 用于存储指向常量池列表 constant_utf8_info 常量项的有效索引, 可以通过所有找到对应类及描述符, constant_methodtype_info 用于存储指向常量池 constant_utf8_info 常量项, 表示方法类型, 找到对应的方法描述符, constant_methodhandle_info 用于表示方法句柄, 属性 reference_kind 表示方法句柄的类型, 1-4 表示为字段创建的方法句柄, 5-8 表示为类方法 (构造, 实例, 静态) 创建的句柄, 9 表示为接口方法创建的句柄, reference_index 属性指向根据 reference_kind 对应的常量池列表, constant_invokedynamic_info 用于存储当前字节码文件中引导方法 bootstrap_method 数组的有效索引和指向常量池 constant_nameandtype_info 常量项的有效索引
- constant_utf8_info{
- u1 tag;
- u2 length;
- u1 bytes[length];
- }
- constant_integer_info{
- u1 tag;
- u4 bytes;
- }
- constant_float_info{
- u1 tag;
- u4 float;
- }
- constant_long_info{
- u1 falg;
- u8 long;
- }
- constant_double_info{
- u1 tag;
- u4 double;
- }
- constant_class_info{
- u1 tag;
- u2 name_index;
- }
- constant_string_info{
- u1 tag;
- u2 string_index;
- }
- constant_fieldref_info{
- u1 tag;
- u2 class_index;
- u2 name_and_type_index;
- }
- constant_mathodref_info{
- u1 tag;
- u2 class_index;
- u2 name_and_type_index;
- }
- constant_interfacemathodref_info{
- u1 tag;
- u2 class_index;
- u2 name_and_type_index;
- }
小编推荐一个学 Java 的学习裙[ 七六零, 二五零, 五四一 ] , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
- constant_nameandtype_info{
- u1 tag;
- u2 class_index;
- u2 descriptor_index;
- }
- constant_methodhandle_info{
- u1 tag;
- u2 reference_kind;
- u2 reference_index;
- }
- constant_methodtype_info{
- u1 tag;
- u2 descriptor_index;
- }
- constant_invokedynamic_info{
- u1 tag;
- u2 bootstrap_method_attr_index;
- u2 name_and_type_index;
- }
访问标志: 两个字节, 用于定义字节码文件所表示的类或接口的访问权限, 如判断是类还是接口, 类是否被 abstract 修饰, 类是否被 final 修饰, acc_interface 表示是接口, acc_annotation 表示是注解类型, acc_enum 表示是枚举类型, acc_public 表示类或接口是 public 访问权限, acc_final 表示类不允许被继承, acc_abstract 表示类为抽象类, acc_super 表示类调用实例方法时需进行特殊操作
类索引及父类索引: 四个字节, 用于存储指向常量池 constant_class_info 对应的有效索引, 而 constant_class_info 存储常量池列表的 constant_utf8_info 常量项索引, 根据此索引可找到类和父类的全限定名
接口数量及接口表: 接口属性用于存储当前类或接口的直接超类接口数量, 接口表是一个数组, 记住, 只有常量池表从 1 开始计数, 其余都是从数组下表 0 开始计数, 接口表数组的每一个数组元素存储此类或接口的直接超类接口的有效索引, 根据此索引找到 constant_class_info 对应的常量项, 根据 constant_class_info 可找到对应直接超类接口的全限定名
字段数量及字段表: 字段数量用于存储类或接口的字段数目, 包括类字段和实例字段, 字段表为一个数组, 每一个数组元素都相当于一个 field_info 结构的对象, field_info 结构包含字段完整信息: 字段标识符, 字段访问修饰符, 字段是类字段还是实例字段, 字段是否为常量等, 注意: 此处字段表示当前类或接口的字段, 不包括从超类或接口继承的字段, java 语法规范不允许同一个类或接口中出现同一字段名的不同字段, 但是 class 文件中却可以允许出现相同字段名的不同字段, 只有字段的描述符不同即可, field_info 结构属性: access_flags 用于存储字段的访问标志, acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile 等, 注意: acc_final 与 acc_volatile 不能同时出现在同一字段, name_index 指向常量池 constant_utf8_info 常量项的有效索引, 获取当前字段的简单名称, descriptor_index 指向常量池 constant_utf8_info 常量项的有效索引, 获取当前字段的描述符, attribute_count,attributes[attributes_count]这两项表示字段的属性信息, 用于描述字段相关信息, attribute 数组每一个元素都是一个 attribute_info 结构的元素
- field_info{
- u2 access_flags;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- attribute_info attributes[attribuyes_count];
- }
方法数量及方法表: 方法数量用于存储当前类或接口的方法数目, 包括实例方法, 类方法, 抽象方法, 方法表是一个数组, 每一个数组元素都是一个 method_info 结构, method_info 结构包含方法的完整信息: 方法描述符, 访问修饰符, 是否为 final 方法, 是否为 abstract 方法等, 注意: 此处的方法数组只是表示当前类或接口的所有方法, 并不包括从超类及父接口继承来的方法, java 语法规范 java 类或接口中不允许出现方法签名完全一样的方法同时出现, 会编译报错, 而字节码层面却允许方法签名完全相同的方法同时出现, 只需要保证方法的返回值类型不同, method_info 结构属性与 field_info 一致, 但 acc_flags 类型不尽相同, 注意 acc_abstract 不能与 acc_final,acc_static,acc_private,acc_synchronized,acc_native 同时使用, 接口方法中只能使用 acc_public,acc_abstract, 此处我有一个疑问, 接口中 default 方法有没有对应的访问标志, 注意: 方法只能使用 acc_private,acc_protected,acc_public 访问标志
- method_info{
- u2 access_flags;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- attribute_info attributes[attribuyes_count];
- }
属性数量及属性表: 属性数量表示当前字节码文件中 attribute_info 表数目, 属性表是一个数组, 每一个数组元素都是 attribute_info 结构, attribute_info 结构表示属性的完整信息: 第一项指向常量池 constant_utf8_info 某常量项的有效索引, 根据此索引可找到属性对应名称, 属性可以出现在 classFile, 字段表, 方法表中, 用以描述相关信息, attribute_info 结构完整信息: attribute_name_index 指向常量池 constant_utf8_info 常量项的有效索引, 获取属性名称, attribute_length 用于指明 info 数组长度, info[attribute_length]用于存储属性的数据信息, 必须实现的数据信息: Code,ConstantValue,Exceptions, code 属性用于描述 method_info 的具体相关信息, attribute_name_index 指向常量池 constant_utf8_info 常量项的有效索引, 获取属性名称, 即 code,attribute_length 表示 attribute 表示 attribute_info 长度, 不包括 attribute_name_index 和 attribute_length 的初始 6 字节, max_stack 描述当前方法最大栈深度, max_locals 描述当前方法的局部变量表, code_length 表示 code 数组长度, code[]表示当前方法编译后的字节码, ContantVaue 位于 field_info 结构中, 用于通知虚拟机对类变量进行初始化, 即字段需要被 acc_static 修饰, 当前类常量不需要 ContantValue 通知虚拟机执行初始化, 早就执行好了, 实例字段此时不需要初始化
- attribute_info{
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
- code_attribute{
- u2 attribute_name_index;
- u4 attribute_length;
- u2 max_stack;
- u2 max_locals;
- u4 code_length;
- u1 code[code_length];
- u2 exception_table_length;
- exception_info exception_table[exception_table_length];
- u2 attributes_count;
- attribute_info attributes[attributes_count];
- }
- constantvalue_attribute{
- u2 attribute_name_index;
- u4 attribute_length;
- u2 constantvalue_index;
- }
小编推荐一个学 Java 的学习裙[ 七六零, 二五零, 五四一 ] , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
简单名称与描述符:
简单名称是指字段或方法的简单的一种描述, 比如 person class:private String name 字段简单名称为 name,Object class:public String toString()方法简单名称为 toString, 注意: 字段或方法简单名称不允许出现 . : / [ 等 ASSIC 或 Unicode 字符表示形式
描述符一般指字段或方法的类型, 字段描述符表示字段类型描述, 方法描述符表示参数描述与返回值描述, 如: person class:private String name 字段描述符为 Ljava.lang.String,com.test.Person class:setName(String name)方法描述符为(Ljava.lang.String)V, 注意: 其中 V 表示返回值为 void 类型, 如果参数为 void 则表示为()Ljava.lang.Object, 表示无参的返回值为 java.lang.Object 引用类型的方法描述符
字段描述符解释: B byte 字节类型, Z boolean 布尔类型, C char 字符类型, S short 短整型, I 整型, L long 长整型, F float 单进度浮点类型, D double 双精度浮点类型, L reference 对象引用类型,[ reference 数组引用类型
来源: http://www.jianshu.com/p/62fb8234c2e4