一步一步实现简单安卓性能监控SDK之熟悉java字节码

什么是字节码

说起字节码就不得不说两个东西:java语言规范和java虚拟机规范。
Java语言规范只是规定了Java语言相关的约束以及规则,而虚拟机规范则才是真正从跨平台的角度去设计的。

java语言的跨平台在一定程度上也是字节码带来的益处

java语言是跨平台的,所谓一次编写,到处运行。之所以是跨平台的,就是java定义了一套与操作系统,硬件无关的字节码格式,这个字节码就是用java class文件来表示的,java class文件内部定义了虚拟机可以识别的字节码格式,这个格式是平台无关性的,在linux系统或者在windows系统上都是一致的。这个就好比html文件,我们定义好规范,这个系统只要去按照规范显示出来里面的内容就好了。好比html就是class文件,浏览器就是虚拟机一样,通过浏览器去执行html的渲染过程,我们无论是用手机,Windows系统,苹果系统上网,显示出来的内容都是一样。 java虚拟机可以从class文件中加载预定义的字节码,也可以从网络,数据库,消息文件中加载字节码。

不仅仅java才有字节码

例如groovy 、Scala等等编译之后都可以转换为字节码,运行在jvm虚拟机上。

class文件是最终归宿.png

java代码被编译之后,最终输出了.class文件。这个文件就是字节码文件,会被jvm虚拟机执行。

class 文件 结构

图片来源自网络

两种数据类型:无符号数和表。

无符号数就是u1、u2、u4、u8来分别代表1个、2个、4个、8个字节。表是由
多个无符号数或其他表构成的复合数据类型,以“_info”结尾。在表开始位置,
通常会使用一个前置的容量计数器,因为表通常要描述数量不定的多个数据。

来看看,

class 数据结构 .png

其中上图中的第1、2、 3 行为header ,共暂用8个字节。

header中包含的版本号信息,和jdk的兼容性有关。只有高版本编译的class文件可以兼容低版本的jdk。也就是向下兼容。

实际分析

class文件结构之header

还记得上一篇文章,我们写的测试程序吗,代码如下
<pre>
public class Main {
public static void main(String args [] ) {
System.out.println(" program main method execute ! ");
}
}
</pre>

用UE打开

UE open

Header部分,前八位:00000000h: CA FE BA BE 00 00 00 31 ; 漱壕...1

前四位(U4)为CAFEBABE是魔数,紧接着的00 00 ,次版本号(U2),再接着的 00 31 代表主版本(U2) 十进制是 49 ,根据如下的jdk版本对照表,得知,最低兼容 1.5

jdk版本对照表.png

class文件结构之常量池

常量池,是保存所有常量的一个区间,包括但不限于字符串,还包含方法名,字面量等等。当前类的类名, 字段名, 方法名, 各个字段和方法的描述符, 对当前类的字段和方法的引用信息, 当前类中对其他类的引用信息等等。可以说,它保存了当前类的所有元数据!!!

常量池中包含的数据类型如下

常量池中的数据类型.png

下一步,00 22 ,代表常量池中常量的个数,22 十进制为34 ,表示常量池里有下标为1~33的表项目。
下标从1开始而不是0,是因为第0个表项表示“不引用常量池中的任意一项”。具体表项看看下图。

这些表项有一个共同的特点是,他们的TAG都是U1类型的!!!


常量池中的数据类型 2.png

幸亏他们的TAG都是U1类型的,否则,jvm该如何计算和分析呢!
分析第一项:0A 为tag,十进制为10对应上方表格中的CONSTANT_Methodref_info , 这个methodref结构是 u1 / u2 / u2 ,u1代表tag刚才说了,再看第二个u2代表的index为00 06 十进制是6 ,指向方法声明类描述符class_info中的索引。第三个元素u2 代表的index是 00 14 十进制是 20,同样指向字段描述。nameAndType_info的索引。综合起来,这个0A 0006 0014 就代表了方法的描述。

其他部分的理解和分析,也都大致如此。

常量池主要为后面的_info字段服务的。

我们看看,刚才我们的那个类都有哪些常量。

逐个分析是比较麻烦的,可以使用JDK自带的用于分析Class文件字节码的工具javap

常量.png

class文件结构之访问标志(access_flags)

访问标志.png

class文件结构之 类索引、父类索引与接口索引集合(this_class 、 super_class 、 interfaces_count 和 interfaces)

  • this_class:**类索引,用于确定这个类的全限定名,占2字节
  • super_class:**父类索引,用于确定这个类父类的全限定名(Java语言不允许多重继承,故父类索引只有一个。除了java.lang.Object类之外所有类都有父类,故除了java.lang.Object类之外,所有类该字段值都不为0),占2字节
  • interfaces_count:**接口索引计数器,占2字节。如果该类没有实现任何接口,则该计数器值为0,并且后面的接口的索引集合将不占用任何字节,
  • interfaces:**接口索引集合,一组u2类型数据的集合。用来描述这个类实现了哪些接口,这些被实现的接口将按implements语句(如果该类本身为接口,则为extends语句)后的接口顺序从左至右排列在接口的索引集合中
    this_class、super_class与interfaces中保存的索引值均指向常量池中一个CONSTANT_Class_info类型的常量,通过这个常量中保存的索引值可以找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串

字段表集合(fields_count 和 fields)

fields_count:字段表计数器,即字段表集合中的字段表数据个数。占2字节

fields:字段表集合,一组字段表类型数据的集合。字段表用于描述接口或类中声明的变量,包括类级别(static)和实例级别变量,不包括在方法内部声明的变量

在Java中一般通过如下几项描述一个字段:字段作用域(public、protected、private修饰符)、是类级别变量还是实例级别变量(static修饰符)、可变性(final修饰符)、并发可见性(volatile修饰符)、可序列化与否(transient修饰符)、字段数据类型(基本类型、对象、数组)以及字段名称。在字段表中,变量修饰符使用标志位表示,字段数据类型和字段名称则引用常量池中常量表示,字段表格式如下表所示:

Paste_Image.png

字段修饰符放在access_flags中,占2字节


字段修饰符.png

方法表集合(methods_count 和 methods)

methods_count:方法表计数器,即方法表集合中的方法表数据个数。

methods:方法表集合,一组方法表类型数据的集合。方法表结构和字段表结构一样:

方法表结构.png

数据项的含义非常相似,仅在访问标志位和属性表集合中的可选项上有略微不同

由于ACC_VOLATILE标志和ACC_TRANSIENT标志不能修饰方法,所以access_flags中不包含这两项,同时增加ACC_SYNCHRONIZED标志、ACC_NATIVE标志、ACC_STRICTFP标志和ACC_ABSTRACT标志

数据项.png

属性表集合(attributes_count 和 attributes)

在Class文件、属性表、方法表中都可以包含自己的属性表集合,用于描述某些场景的专有信息

与Class文件中其它数据项对长度、顺序、格式的严格要求不同,属性表集合不要求其中包含的属性表具有严格的顺序,并且只要属性的名称不与已有的属性名称重复,任何人实现的编译器可以向属性表中写入自己定义的属性信息。虚拟机在运行时会忽略不能识别的属性,为了能正确解析Class文件,虚拟机规范中预定义了虚拟机实现必须能够识别的9项属性:

Paste_Image.png

每种属性均有各自的表结构。这9种表结构有一个共同的特点,即均由一个u2类型的属性名称开始,可以通过这个属性名称来判段属性的类型。

详情参考下面的链接第二条。

参考:
https://github.com/waylau/java-virtual-machine-specification
http://blog.csdn.net/a19881029/article/details/16117251

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容