Java虚拟机系列二:class字节码详细分析

索引:

Java虚拟机系列一: Java文件如何被加载执行

全文的分析都基于class字节码,它与android dex字节码有很大的区别。class字节码是以类为单位组织的,而dex是多个类的集合

一.class字节码是什么?

字节码是由jvm规范所定义的一套描述class内容的结构,由于它的描述与指令集的平台无关性,只要能够将自己的语言翻译成为字节码,就都能被虚拟机执行,这样的语言如java,groovy,kotlin等。hotpot虚拟机是jvm规范的标准实现。

二.class字节码的简单例子看全貌

眼见为实,我们定义一个Test.java类

public class Test {
    static String a = "hucaihua";
}
复制代码

通过编译得到Test.class,通过010Editor查看它的内容,可以看出它是用字节为单位组织的二进制内容,也就是说它的本质是用01串存储的二进制流。

在这里软件为了方便展示,以16进制来表示,一个16进制需要用4位二进制来表示,因此这里的每一个隔开的数据,代表的就是一个字节8位。

CA FE BA BE 00 00 00 37 00 14 0A 00 05 00 0F 08
00 10 09 00 04 00 11 07 00 12 07 00 13 01 00 01
61 01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53
74 72 69 6E 67 3B 01 00 06 3C 69 6E 69 74 3E 01
00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C
69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00
08 3C 63 6C 69 6E 69 74 3E 01 00 0A 53 6F 75 72
63 65 46 69 6C 65 01 00 09 54 65 73 74 2E 6A 61
76 61 0C 00 08 00 09 01 00 08 68 75 63 61 69 68
75 61 0C 00 06 00 07 01 00 04 54 65 73 74 01 00
10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63
74 00 21 00 04 00 05 00 00 00 01 00 08 00 06 00
07 00 00 00 02 00 01 00 08 00 09 00 01 00 0A 00
00 00 1D 00 01 00 01 00 00 00 05 2A B7 00 01 B1
00 00 00 01 00 0B 00 00 00 06 00 01 00 00 00 01
00 08 00 0C 00 09 00 01 00 0A 00 00 00 1E 00 01
00 00 00 00 00 06 12 02 B3 00 03 B1 00 00 00 01
00 0B 00 00 00 06 00 01 00 00 00 02 00 01 00 0D
00 00 00 02 00 0E
复制代码

三.class字节码的结构体

class结构的官方说明

我们知道,class是格式化的二进制流,也就是它的二进制流是按照jvm虚拟机规范规定的格式来表示内容的,在jvm中class定义如下:

ClassFile {
    u4             magic;               //魔数,固定值0xCAFEBABE
    u2             minor_version;       //次版本号
    u2             major_version;       //主版本号
    u2             constant_pool_count; //常量池的个数
    cp_info        constant_pool[constant_pool_count-1];  //常量池内容
    u2             access_flags;        //class 访问标识
    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];          //属性内容
}
复制代码

其中 u4,u2都是固定长度的描述字段,u4长度为4个字节,u2长度为2个字节。

cp_info , field_info , method_info , attribute_info 为结构体,每个结构体有单独的定义,并且它们的长度都是变化的。

四.class结构体重点结构说明

4.1 cp_info(18种常量类型的描述)

cp_info是class中占用字节数最多的块,它用不同的结构体定义了18种常量类型,这18种常量类型都用tag来表示它的具体类型。
class_cp_info

下图分析了CONSTANT_Class_info中的实际内容,其它内容的查找方式一样,不再继续分析。

class_def_analysis

4.2 field_info(字段描述)

field_info的定义如下:

field_info {
    u2             access_flags; //访问标志 
    u2             name_index; //名字在常量中的索引
    u2             descriptor_index; //描述在常量中的索引
    u2             attributes_count; //属性的个数
    attribute_info attributes[attributes_count]; //属性列表
}
复制代码
  • access_flags 访问标志一共包含如下9类,常用的如public,static,private,protected等:
Flag Name	Value	Interpretation
ACC_PUBLIC	0x0001	Declared public; may be accessed from outside its package.
ACC_PRIVATE	0x0002	Declared private; usable only within the defining class.
ACC_PROTECTED	0x0004	Declared protected; may be accessed within subclasses.
ACC_STATIC	0x0008	Declared static.
ACC_FINAL	0x0010	Declared final; never directly assigned to after object construction (JLS §17.5).
ACC_VOLATILE	0x0040	Declared volatile; cannot be cached.
ACC_TRANSIENT	0x0080	Declared transient; not written or read by a persistent object manager.
ACC_SYNTHETIC	0x1000	Declared synthetic; not present in the source code.
ACC_ENUM	0x4000	Declared as an element of an enum.
复制代码

4.3 attribute_info (属性描述)

属性描述信息可以作用于ClassFile , field_info,method_info,cod_attribute的描述。

我们常见的例如泛型,注解等都属于attribute_info的范畴。

它的定义如下:

attribute_info {
    u2 attribute_name_index; //属性名字如<Signature>表示泛型,<RuntimeVisibleAnnotations>表示注解等
    u4 attribute_length; //属性长度
    u1 info[attribute_length]; //属性信息
}
复制代码

下图用一个例子来说明属性
class_attribute

4.4 method_info (方法描述)

方法描述的定义与field_info一致,不再重复说明:

method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
复制代码

方法描述(method_info)与字段描述(field_info)最大的区别在于attribute_info不一样,

所有method_info都包含一个attribute_info,它的名字叫code,用于包含方法的指令信息。

下图体现了我们定义的get方法中的指令信息
class_method_instruction

免责声明:务必仔细阅读

  • 本站为个人博客,博客所转载的一切破解、path、补丁、注册机和注册信息及软件等资源文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。

  • 本站为非盈利性站点,打赏作为用户喜欢本站捐赠打赏功能,本站不贩卖软件等资源,所有内容不作为商业行为。

  • 本博客的文章中涉及的任何解锁和解密分析脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断.

  • 本博客的任何内容,未经许可禁止任何公众号、自媒体进行任何形式的转载、发布。

  • 博客对任何脚本资源教程问题概不负责,包括但不限于由任何脚本资源教程错误导致的任何损失或损害.

  • 间接使用相关资源或者参照文章的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, 博客对于由此引起的任何隐私泄漏或其他后果概不负责.

  • 请勿将博客的任何内容用于商业或非法目的,否则后果自负.

  • 如果任何单位或个人认为该博客的任何内容可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明至admin@proyy.com.我们将在收到认证文件后删除相关内容.

  • 任何以任何方式查看此博客的任何内容的人或直接或间接使用该博客的任何内容的使用者都应仔细阅读此声明。博客保留随时更改或补充此免责声明的权利。一旦使用并复制了博客的任何内容,则视为您已接受此免责声明.

您必须在下载后的24小时内从计算机或手机中完全删除以上内容.

您使用或者复制了本博客的任何内容,则视为已接受此声明,请仔细阅读


更多福利请关注一一网络微信公众号或者小程序

一一网络微信公众号
打个小广告,宝塔服务器面板,我用的也是,很方便,重点是免费的也能用,没钱太难了,穷鬼一个,一键全能部署及管理,送你3188元礼包,点我领取https://www.bt.cn/?invite_code=MV9kY3ZwbXo=


一一网络 » Java虚拟机系列二:class字节码详细分析

发表评论

发表评论

一一网络-提供最优质的文章集合

立即查看 了解详情