Java字节相关资料
2015-05-10 13:36
363 查看
深入理解JVM—字节码文件子系统
2012-03-20 15:48:42| 分类: JVM | 标签:jvm 字节码 子系统 深入理解 class |举报|字号 订阅下载LOFTER客户端
我们在前面的几篇文章已经提到过很多次,Java是一种平台无关性的语言,而平台无关性主要是因为有了中间代码—字节码。其运行流程如下所示:
同样的,我们的
JVM有着更强大的功能,平台无关性和语言无关性,如下图所示,无论什么语言,只要编译后是符合Java虚拟机规范的字节码文件,JVM便可以正常运行。
那
Class文件究竟是什么样子的一个格式,什么一个结构的呢?下面让我们一起来解开它的面纱。
字节码具有以下结构特征
1、 Class文件是以8bit为基础单位的二进制数据流,也就是我们的一个Byte。
2、 字节码数据严密紧凑,无分隔符,这一点是效仿当初的C语言。
3、 字节码只存在无符号数字和表两周数据类型
4、 所有的字节码数据采用UTF-8字符编码
学过数据结构的都知道,任何物质都是有数据构成的,字节码主要有无符号数字和表构成,无符号数字使用u1、u2、u3、u4表示一个、两个、三个和四个字节,用于描述数字、索引、数值和字符串等,而表主要以无符号数和其他表组合而成的复合数据,通常 以_info结尾。
那字节码为减是如何生成的呢?这一点我在上一篇博文中已经写的很详细了,大家可以参考上篇博文。
类在加载前必须先解析字节码,字节码主要由以下文件格式构成
名称 | 类型 | 数量 |
magic | u4 | 1 |
minor_version | u2 | 1 |
major_version | u2 | 1 |
constant_pool_count | u2 | 1 |
constant_pool | cp_info | constant_pool_count-1 |
access_flags | u2 | 1 |
this_class | u2 | 1 |
super_class | u2 | 1 |
interfaces_count | u2 | 1 |
interfaces | u2 | interfaces_count |
fields_count | u2 | 1 |
fields | field_info | fields_count |
methods_count | u2 | 1 |
methods | method_info | methods_count |
attributes_count | u2 | 1 |
attributes | attribute_info | attributes_count |
接下分别是编译这段字节码的编译器的小版本和大版本,如下图所示:
对应的版本关系如下(注意,这个是
16进制的哈)
JDK 编译器版本 | target 参数 | 十六进制minor.major | 十进制minor.major |
jdk1.1.8 | 不能带 target 参数 | 00 03 00 2D | 45.3 |
jdk1.2.2 | 不带(默认为 -target 1.1) | 00 03 00 2D | 45.3 |
jdk1.2.2 | -target 1.2 | 00 00 00 2E | 46.0 |
jdk1.3.1_19 | 不带(默认为 -target 1.1) | 00 03 00 2D | 45.3 |
jdk1.3.1_19 | -target 1.3 | 00 00 00 2F | 47.0 |
j2sdk1.4.2_10 | 不带(默认为 -target 1.2) | 00 00 00 2E | 46.0 |
j2sdk1.4.2_10 | -target 1.4 | 00 00 00 30 | 48.0 |
jdk1.5.0_11 | 不带(默认为 -target 1.5) | 00 00 00 31 | 49.0 |
jdk1.5.0_11 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
jdk1.6.0_01 | 不带(默认为 -target 1.6) | 00 00 00 32 | 50.0 |
jdk1.6.0_01 | -target 1.5 | 00 00 00 31 | 49.0 |
jdk1.6.0_01 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
jdk1.7.0 | 不带(默认为 -target 1.6) | 00 00 00 32 | 50.0 |
jdk1.7.0 | -target 1.7 | 00 00 00 33 | 51.0 |
jdk1.7.0 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
跟着大小编译器版本后面的就是我们的常量池。常量池主要有字面常量和符号引用两种组成。字面常量主要包括文本常量,被声明为final的常量值等。符号引用主要包含类和接口的全限定名、字段的名称和描述符以及方法的名称和描述符等。其中常量池中每一种常量都是使用表来进行描述的。常量中的表如下图所示
其详细的结构如下图所示
常量值最基本的就是
UTF-8类型的字符串,如下图所示
01
表示UTF-8后面跟的是他的内容。我们可以通过javap –verbose ${ClassName}来查看。
紧接着的两个字节是访问标识符,如下表所示
我们来看一个实例,刚才那段代码对应的访问标识符如下:
对照表格我们可以清楚的看到对应的访问标识符是
public的。
下面紧接着的是对应的类索引、父类索引和接口索引集。如图所示:
这里
0x07属于类结构,对应的索引为0x11,为第17个常量,对应的数据如下图所示
这里我们就可以看待对应的类名了,是一个
UTF-8类型的字符串。同样的,我们可以查找对应的父类和接口索引。我们也可以同javap –verbose ${ClassName}来查看,命令运行的结构如下图所示:
我们可以清晰的看到对应的常量和关系。
紧接着下面的数据是字段表,他的结构如下所示
他有一个访问标识符,字段名称索引,描述索引和属性表。属性表我们稍后在讨论,现在我们来了解以下敌营的描述符。
描述符是通过一个简单的符号来代替一段符号的描述,如Int就是用一个I表示,数组就使用[表示,下面是一些基本的例子。
我们前面已经提到了一个简单名称、全限定名和描述符,那这几个有啥区别的呢?下面用一个例子来展示以下
不用多说,大家一看就明白了吧!具体到我们之前的那段代码示例,如下图所示
接下来的是方法表,方法表和字段表很像,结构如下图所示
对应的访问标识符如下:
结合上面的示例如下:
适应
javap可以很清楚的看到方法表的内容
在
Java里面,我们没定义一个方法,JVM在运行时知道我们要调用哪些方法,那这些是通过什么来区分的呢?有人会说,肯定通过方法名了,那方法名相同的怎么办?也许你继续会说,方法名相同,还有参数不同哇?那返回值 不同行不行?我们很早已经知道答案,方法名相同参数不同的函数写法被称为是重载,在Java语言中,重载一个方法除了需要和原方法相同的方法名之外,还需要和原方法有不同的特征签名。而这个特征签名包括顺序的签名类型的集合,并不包含返回值类型,因此不同的返回值类型不能重载,但是我们可以定义返回类型不同、名称相同、签名不同的方法,如下图代码所示。
紧接着方法表,接下来的就是属性表,属性表主要包含以下信息
我们使用
javap命令可以很详细的看到对应的结果。
JDK
从1.5以后加入了 不少新的属性表,下表展示了JDK1.5
1.6新加入的属性表。
但是这些字节码被解析之后还需要哪些步骤去执行的呢?请参加下篇博文。字节码执行引擎。
相关文章推荐
- Java相关学习资料和平台汇总
- Java JDBC下执行SQL的不同方式、参数化预编译防御 相关学习资料 http://zh.wikipedia.org/wiki/Java数据库连接 http://lavasoft.blog.51
- java预赛试题的相关的资料介绍
- java缓存相关资料
- Java9相关资料(JShell简易教程等)
- http://www.coreservlets.com/ ——Java相关的培训网站,英文(有的有中文),很多免费的PDF讲课资料。
- 我在网上收集的java相关资料
- java相关资料整理
- java Https 相关资料
- java项目中.properties中文资源文件相关资料
- java相关资料(jdk1.6)
- Tomcat启动:A fatal error has been detected by the Java Runtime Environment(JVM Crash分析及相关资料)
- java 相关资料网址
- java开发相关资料
- Java 7之传统I/O - 其它相关字节输入输出流类
- Android和JAVA面试题相关资料
- JAVA编程相关资料(初学整理合集)
- [JAVA多线程相关资料]
- java flex blazeds 开发相关资料
- [置顶] 转载一个即将成为大牛朋友的学习方法(内涵相关文档资料,java相关),