字节码是构成Java平台无关性的基石。实现语言无关性的基础是虚拟机和字节码存储格式。
Java语言中的各种变量、关键字和运算符的语义最终是由多条字节码命令组成,因此字节码命令所能提供的语义描述能力肯定会比Java语言本身更强大。
 
Class类文件的结构
        Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符,所以整个Class文件中存储的内容基本上程序运行中必要的数据。
        当遇到需要占用8位字节以上空间的数据项时,则会按照位字节进行存储。
 
Class文件的格式:类似于C语言结构体的伪结构来存储,这种伪结构只有两种数据类型:无符号数和表,后面的解析以这两种数据类型为基础。
1)无符号数:属于基本的数据类型,无符号数可以描述数字、索引引用、数量值或者是按照UTF-8编码构成字符串值。
2)表:由多个无符号数或者其他表作为数据项构成的复合数据类型。表用于描述有层次关系的复合结构的数据。整个Class文件本质上就是一张表。
        
        无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时候称这一系列连续的某一类型的数据为某一类型的集合。
        Class文件中的数据项无论是顺序还是数量,都是被严格限定的,哪个字节代表什么意思,长度是什么样的,先后顺序如何,都是不允许改变的。
 
结构详解:
1)magic:魔数,头四个字节,它的作用是用于确定这个文件是否为一个能被虚拟机接受的Class文件。很多文件存储标准中都使用魔数来进行身份识别,如图片格式等。
        使用魔数而不是扩展名来进行识别主要是基于安全考虑,因为文件扩展名是可以随意修改的。
        Class文件的魔数值为:0xCAFEBABE。
 
2)Minor Version、Major Version(Class文件的版本号):在魔数之后的4个字节。第5、6个字节是次版本号(Minor Version),第7、8个字节是主版本号(Major Version)。
        Java版本号是从45开始的,JDK1.1之后的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1 使用45.0~45.3的版本号),高版本的JDK能向下兼容以前版本的Class文件,但不能向后兼容。
 
3)constant-pool常量池:常量池是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是Class文件中第一个出现的表类型数据项目。
        由于常量池中的常数的数量是不固定的,所以在常量池的入口处放置一项u2(代表两个字节)类型的数据,代表常量池容量计数值(constant-pool-count)。值得注意的是:这个容量计数是从1而不是从0开始的。原因是为了满足后面某些指向常量值得索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的意思。
        常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值。而符号引用则属于编译原理方面的概念,包括:a、类和接口的全限定名(Fully Qualified Name);b、字段的名称和描述符(Descriptor);c、方法的名称和描述符。
        Java代码在进行Javac编译时,不像C或者C++那样的“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态加载。所以,在Class文件中不会保存各种方法和字段的最终内存布局信息,因此这些字段和方法的符号引用不经过转换的话就无法让虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或者运行时解析并翻译到具体的内存地址中。
        
        常量池中的每一项常量都是一个表,共有11种结构各不相同的表结构数据。这11种表都有一个共同的特点,就是表开始的第一位是一个u1类型的标志位(tag,取值为1~12,缺少标志为2的数据类型),代表这个常量属于哪种常量类型。
如:CONSTANT_Class_info型常量的结构:(u1)tag + (u2)name_index,标志位+索引值,索引值指向常量池中的一个CONSTANT_Utf-8_info类型的常量,此常量代表这个类(或者接口)的全限定名。
CONSTANT_Utf8_info型常量的结构:(u1)tag+(u2)length+(u1)bytes,标志位+字符串长度的字节+数量为length的bytes值。
        Class文件中方法、字段等都需要引用CONSTANT_Utf8_info型常量来描述名称,所以CONSTANT_Utf8_info型常量的最大长度也就是Java中方法和字段名的最大长度,最大值是65535.所以Java程序中如果定义了超过64KB英文字符的变量或方法名,将会无法编译。
        javap可以用来分析Class文件字节码,用javap -verbose参数输出Class文件的字节码内容。
 
4)access_flags(访问标志):在常量池结束后,紧接着的2个字节代表访问标志(access_flags),这个标志用来识别一些类或接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类。是否被声明为final等等。
 
access_flags中一共有32个标志位可以使用,当前只定义了其中的8个,其他的标志位要求一律为0.
 
5)this_class、super_class、interfaces(类索引、父类索引和接口索引集合):this_class和super_class都是一个u2类型的数据,而接口索引集合是一组u2类型的数据的集合。Class文件中由这三项数据来确定这个类的继承关系。
        类索引用于确定这个类的全限定名,父索引用于确定这个类的父类的全限定名。由于java语言不允许多重继承,所以父索引只有一个,且不为空。接口索引集合描述了这些类实现了哪些接口,它们按照继承的顺序依次从左到右排列在接口集合中。
        类索引、父类索引和接口索引集合都按照顺序排列在访问标志之后。类索引和父类索引引用两个u2类型的索引值表示,他们各自指向一个类型为CONSTANT_Class_info的类描述符常量,通过其内的索引值找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串。而对于接口索引集合,入口的第一项是u2类型的接口计数器(interfaces_count)表示索引表的容量。
 
6)filed_info(字段表集合):用于描述接口或类中声明的变量。字段(filed)包括了类级变量或实例化变量,但不包括在方法内部声明的变量。
        字段中包括的信息:字段的作用域(public、private、protected修饰符)、是类级变量还是实例级变量(static修饰符)、可变性(final)、并发可见性(volatile修饰符)、可否序列化(reansient修饰符)、字段数据类型(基本类型、对象、数组)、字段名称等。在这些信息中,各个修饰符都是布尔值,要么有,要么没有。而字段叫什么名字、字段被定义成什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。
字段表结构:
字段访问标志:
跟随access_flags标志的是两项索引值,name_index和descriptor_index。它们都是对常量池的引用,分别代表着字段的简单名称及字段和方法的描述符。
描述符标识字符含义:
        对于数组类型,每一个维度将使用一个前置的“【”来描述。如“【I”:一个整型数组。
        用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照严格顺序放在一组小括号之内。如方法void inc()的描述符为“()V”。
        字段表集合中不会列出从超类或者父接口中继承而来的字段,但有可能列出原本java代码之中不存在的字段,如在内部类中为了保持对外部类de访问性,会自动添加指向外部类实例的字段。
 
7)methods(方法表集合):
方法访问标志:
 
8)attribute_info(属性表集合):在Class文件、字段表、方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。
虚拟机规范预定义的属性:
 
 
 
 
 
 
 
 
 
 

JVM小结--类文件结构的更多相关文章

  1. 深入理解JVM(六)类文件结构

    6.1 关于类文件 1.class文件的一次编译,到处运行的跨平台性: 2.JVM不止有跨平台性,还有跨语言性,不管是JRuby还是Groovy写出来的程序,只要编译出符合JVM规范的class文件就 ...

  2. JVM(4) 类文件结构

    一.实现“平台无关性” 字节码(ByteCode)存储格式和虚拟机是实现语言无关性的基础.Java虚拟机不和包括Java在内的任何语言绑定,它只与“Clas”文件这种特定的二进制文件格式所关联,Cla ...

  3. JVM学习笔记(三):类文件结构

    代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与&quo ...

  4. jvm 类文件结构学习

    本文以代码示例来学习 java 类文件的结构,其中对类文件结构的学习均来自周志明先生所著的 <深入理解 Java 虚拟机>一书,在此表示诚挚的感谢. 代码如下: package com.r ...

  5. 【搞定Jvm面试】 面试官:谈谈 JVM 类文件结构的认识

    类文件结构 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机.Java 语言通过字节码的方式,在一定程度上解决 ...

  6. 四、JVM — 类文件结构

    类文件结构 一 概述 二 Class 文件结构总结 2.1 魔数 2.2 Class 文件版本 2.3 常量池 2.4 访问标志 2.5 当前类索引,父类索引与接口索引集合 2.6 字段表集合 2.7 ...

  7. jvm(4):类文件结构

    typora-root-url: ./ 类文件结构 魔数Magic Number 每个Class文件的头4个字节是魔数.值为0xCAFEBABE 唯一作用:确定这个文件是一个能被虚拟机接受的Class ...

  8. JVM类文件结构

    作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...

  9. JVM学习第三天(JVM的执行子系统)之开篇Class类文件结构

    虽然这几天 很忙,但是学习是不能落下的,也不能推迟,因为如果推迟了一次,那么就会有无数次;加油,come on! Java跨平台的基础: 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节 ...

随机推荐

  1. JAVA实验报告三:敏捷开发与XP实践

    实验内容 1. XP基础 2. XP核心实践 3. 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软件工程包括下列领域:软件需 ...

  2. 《找出1到正整数N中出现1的次数》

    <找出1到正整数N中出现1的次数> 编程思想:依次求出正整数每个位数上出现1的次数,累加即可得到最后想要的结果:而每一位上出现1的个数与和它相邻的其它位数上的数字有关系(以此位置上的数为对 ...

  3. jsp九大内置对象之一request

    request对象,目的是用来获取客户端的请求. 主要方法有: request.getMethod();                      // 获取提交请求的方式 request.getPr ...

  4. android 的helloworld没跑起来 原因

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com. ...

  5. Unity发布Windows程序遇到的问题

    Unity版本:5.6.2 因为程序中使用了Networking模块,所以在打包发布的时候需要登录Unity的账号,并做设置. 错误信息如下: 解决办法如下: 先登录Unity账号,并在Service ...

  6. Head First Java & 重载 覆盖

  7. UIPickerView的使用

    简介:UIPickerView是一个选择器控件,它比UIDatePicker更加通用,它可以生成单列的选择器,也可生成多列的选择器,而且开发者完全可以自定义选择项的外观,因此用法非常灵活.UIPick ...

  8. 课堂alpha发布

    项目组名:奋斗吧兄弟 今天七组对于各自项目现有的成果进行了alpha发布,下面是我的一些感想. 天天向上团队的连连看游戏: 令我印象最深的是天天向上团队的连连看项目,他们目前能展示给我们的是核心的连连 ...

  9. php $_SERVER['HTTP_USER_AGENT'] 2

    //mobile  false pc   true no pc    function is_mobile(){        $agent = strtolower($_SERVER['HTTP_U ...

  10. properties文件读取与写入

    将peoperties文件的读取和写入封装成了一个工具类: import java.io.BufferedInputStream; import java.io.FileInputStream; im ...