博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java class文件结构
阅读量:4624 次
发布时间:2019-06-09

本文共 6320 字,大约阅读时间需要 21 分钟。

看了一周深入理解java虚拟机了,今天看到第六章,最近一直处在接受新知识的快感之中,不由得感慨基础知识的重要性,学起来相当过瘾!类文件结构这部分实践性较强,对于分析java代码有很重要的帮组,于是有做点笔记的必要了,在参考书的基础上,将一段代码的字节码完全解析了一遍。
class文件的结构如下
ClassFile {	u4 magic;	u2 minor_version;	u2 major_version;	u2 constant_pool_count;	cp_info constant_pool[constant_pool_count-1];	u2 access_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];}
编译下面这段代码生成class文件
package org.fenixsoft.clazz;public class Test {	private int m;	public int inc(){		return m+1;	}}

对应class文件内容如下

cafe babe 0000 0033 0016 0700 0201 00186f72 672f 6665 6e69 7873 6f66 742f 636c617a 7a2f 5465 7374 0700 0401 0010 6a617661 2f6c 616e 672f 4f62 6a65 6374 0100016d 0100 0149 0100 063c 696e 6974 3e010003 2829 5601 0004 436f 6465 0a00 03000b0c 0007 0008 0100 0f4c 696e 654e 756d6265 7254 6162 6c65 0100 124c 6f63 616c5661 7269 6162 6c65 5461 626c 6501 00047468 6973 0100 1a4c 6f72 672f 6665 6e697873 6f66 742f 636c 617a 7a2f 5465 73743b01 0003 696e 6301 0003 2829 4909 00010013 0c00 0500 0601 000a 536f 7572 63654669 6c65 0100 0954 6573 742e 6a61 76610021 0001 0003 0000 0001 0002 0005 00060000 0002 0001 0007 0008 0001 0009 0000002f 0001 0001 0000 0005 2ab7 000a b1000000 0200 0c00 0000 0600 0100 0000 03000d00 0000 0c00 0100 0000 0500 0e00 0f000000 0100 1000 1100 0100 0900 0000 31000200 0100 0000 072a b400 1204 60ac 00000002 000c 0000 0006 0001 0000 0006 000d0000 000c 0001 0000 0007 000e 000f 00000001 0014 0000 0002 0015

解析:

/*魔数*/cafe babe // 魔数/*次版本*/0000 // 次版本/*主版本*/0033 // 主版本/*常量池个数*/0016 // 常量个数,21(从1开始)/*cp_info类型的数组*///21个常量0700 0201 00186f72 672f 6665 6e69 7873 6f66 742f 636c617a 7a2f 5465 7374 0700 0401 0010 6a617661 2f6c 616e 672f 4f62 6a65 6374 0100016d 0100 0149 0100 063c 696e 6974 3e010003 2829 5601 0004 436f 6465 0a00 03000b0c 0007 0008 0100 0f4c 696e 654e 756d6265 7254 6162 6c65 0100 124c 6f63 616c5661 7269 6162 6c65 5461 626c 6501 00047468 6973 0100 1a4c 6f72 672f 6665 6e697873 6f66 742f 636c 617a 7a2f 5465 73743b01 0003 696e 6301 0003 2829 4909 00010013 0c00 0500 0601 000a 536f 7572 63654669 6c65 0100 0954 6573 742e 6a61 7661/*访问标志*/0021 // 访问标志(使用标志位)/*类索引*/0001 // 类索引/*父类索引*/0003 // 父类索引/*接口个数*/0000 // 接口索引:u2类型的接口计数器 + 各个接口/*u2类型的接口数组*//*字段表数量*/0001 // 字段表数量/*field_info类型数组*/0002 // 字段访问标志0005 // 简单名称0006 //描述符0000 // 字段的属性表数量--- // 字段的属性表集合(0个)/*方法表数量*/0002 // 方法表数量/*method_info数组*///第一个方法0001 // 方法访问标志0007 // 简单名称0008 // 描述符0001 // 属性表数量// 方法的属性表(对应的常量是Code,方法表中使用,代表代码编译成的字节码指令)0009 // Code属性表  u2类型,在常量池中0000 002f // u4类型,指明属性值所占位数0001 //max_stack,操作数栈最大深度,根据它分配栈帧0001 //max_locals,局部变量表所需的存储空间,单位是Slot,不超过32位的数据类型,占一个Slot,64位的占2个Slot0000 0005 // code length,// code,共5个2a // aload_0(将第0个Slot中为refrence类型的本地变量推送至操作数栈顶,其实就是this)b7 // invokespecial(调用栈顶对象的某个方法:实例构造方法、private方法或者它的父类方法)000a // invokespecial的参数,说明具体调用哪个方法,指向常量池中CONSTANT_Methodref_info类型常量b1 // 返回return,返回值为void0000 // 异常表长度//异常信息,长度为0----0002 // code的属性表数量// 方法的属性表,在Code属性表中000c // 表示LineNumberTable,java源码与字节码的偏移量之间的关系0000 0006 // 属性表长度0001 // 行号表的长度// 行号信息0000 // start_pc0003 // line_number// 方法的属性表,在Code属性表中000d // 表示LocalVariableTable,描述栈帧中局部变量表中的变量与java源码中定义的变量之间的关系0000 000c // 该属性表长度0001 // 局部变量表长度// 局部变量信息,长度为1,由5个u2类型构成0000 // start_pc,该局部变量的生命周期开始的字节码偏移量0005 // length,其作用范围覆盖的长度000e // name_index,指向常量池中的索引,局部变量的名称000f // descriptor_index,同上,局部变量的描述符0000 // index,该局部变量在栈帧局部变量表中的Slot位置// 第二个方法0001 // 访问标志0010 // 简单名称,inc0011 // 描述符()I0001 // 属性表数量0009 // // Code属性表0000 0031 // u4类型,指明属性值所占位数0002 // max_stack0001 // max_locals0000 0007 // code_length2a // aload_0(将第0个Slot中为refrence类型的本地变量推送至操作数栈顶,其实就是this)b4 // getfield,获取指定类的实例,并将其压入栈帧0012 // 参数,Test类的m成员04 // iconst_1,将int型1推送至栈顶60 // iadd,将栈顶两个int型数值相加并将结果压入栈顶ac // ireturn,从当前方法返回int0000 // 异常表长度---- //异常信息,长度为00002 // 属性表数量// LineNumberTable000c 0000 0006 0001 0000 0006// LocalVariableTable000d 0000 000c 0001 0000 0007 000e 000f 0000/*类的属性表个数*/0001 // 属性表数量/*类的attribute_info数组*/0014 // SourceFile,记录原文件名称0000 0002 // 属性表长度0015 // 源文件,Test.java

属性表可以包含在Class文件、字段表、方法表中。

短短几行代码,我们看起来如此费劲,使用Oracle公司给我们准备的class文件字节码的工具javap。javap -v Test.java命令查看的字节码的内容如下,两者内容是一模一样的

Last modified 2015-12-11; size 378 bytes  MD5 checksum 0e2626e6fdb11bccf73564affa0b63e2  Compiled from "Test.java"public class org.fenixsoft.clazz.Test  SourceFile: "Test.java"  minor version: 0  major version: 51  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Class              #2             //  org/fenixsoft/clazz/Test   #2 = Utf8               org/fenixsoft/clazz/Test   #3 = Class              #4             //  java/lang/Object   #4 = Utf8               java/lang/Object   #5 = Utf8               m   #6 = Utf8               I   #7 = Utf8               
#8 = Utf8 ()V #9 = Utf8 Code #10 = Methodref #3.#11 // java/lang/Object."
":()V #11 = NameAndType #7:#8 // "
":()V #12 = Utf8 LineNumberTable #13 = Utf8 LocalVariableTable #14 = Utf8 this #15 = Utf8 Lorg/fenixsoft/clazz/Test; #16 = Utf8 inc #17 = Utf8 ()I #18 = Fieldref #1.#19 // org/fenixsoft/clazz/Test.m:I #19 = NameAndType #5:#6 // m:I #20 = Utf8 SourceFile #21 = Utf8 Test.java{ public org.fenixsoft.clazz.Test(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #10 // Method java/lang/Object."
":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lorg/fenixsoft/clazz/Test; public int inc(); flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: getfield #18 // Field m:I 4: iconst_1 5: iadd 6: ireturn LineNumberTable: line 6: 0 LocalVariableTable: Start Length Slot Name Signature 0 7 0 this Lorg/fenixsoft/clazz/Test;}

转载于:https://www.cnblogs.com/qhyuan1992/p/5385273.html

你可能感兴趣的文章
iOS设计模式简介
查看>>
c# 扩展方法 奇思妙用 高级篇 九:OrderBy(string propertyName, bool desc)
查看>>
C语言中的地址传递(传指针,传递给形参的指针仍然是实参指针的一份拷贝)
查看>>
redis缓存数据库及Python操作redis
查看>>
opencms忘记Admin用户登录密码解决方案
查看>>
forms组件
查看>>
create-react-app 配置sass
查看>>
02_关系数据库
查看>>
在win7电脑中如何查看运行进程的PID标识符
查看>>
[Vue] vue-cli3.0安装
查看>>
C++学习之字符串
查看>>
图像化列表
查看>>
2014年10月9日——语言基础2
查看>>
How to Create Modifiers Using the API QP_MODIFIERS_PUB.PROCESS_MODIFIERS
查看>>
待飞笔记(第一天 )
查看>>
解惑好文:移动端H5页面高清多屏适配方案
查看>>
traefik添加多证书
查看>>
忽略UserInterfaceState.xcuserstate
查看>>
ReactNative--Flexbox布局
查看>>
java实现读取文件大全
查看>>