三 类文件结构
1 Java虚拟机的两种中立特性
    · 平台无关性
    · 语言无关性
    实现平台无关性和语言无关性的基础是虚拟机和字节码存储格式(Class文件)。
 
2 Class类文件的结构
    ---Class文件是一组以8位字节为基础单位的二进制流,当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。
    ---“高位在前”:即最高位字节在地址最低位、最低位字节在地址最高位。
    ---Class文件格式的两种数据类型:
        · 无符号数:是基本的数据类型,包括u1、u2、u4、u8,可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成的字符串值。
        · 表:是由多个无符号数或者其他表作为数据项构成的复合数据类型,用于描述有层次关系的复合结构的数据。
    (1)魔数和Class文件的版本
            · 魔数:
                ---每个Class文件的头4个字节。
                ---用于确定这个文件是否为一个能被虚拟机接受的Class文件。
                ---Class文件的魔数值为:0xCAFEBABE。
            · 版本号:
                ---紧接着魔数的4个字节。
                ---第5和第6个字节是次版本号,第7和第8个字节是主版本号。Java的版本号是从45开始的。
    (2)常量池
            ---常量池入口:u2类型,代表常量池容量计数值,计数从1开始而不是0开始(目的在于满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”时可以把索引值置为0)。
            ---常量池主要存放:字面量和符号引用。
            ---字面量:比较接近于java语言层面的常量概念,如文本字符串、声明为final的常量值。
            ---符号引用:属于编译原理方面的概念。包括:
                · 类和接口的全限定名;
                · 字段的名称和描述符;
                · 方法的名称和描述符。
            ---常量池中每一项常量都是一个表,JDK1.7中,共有14种常量类型,见下表。
         
            ---具体细节略。
    (3)访问标志
            ---常量池结束之后的两个字节代表访问标志,用于识别一些类或者接口层次的访问信息。
            ---一共有16个标志位可以使用,当前只定义了8个,未使用到的标志位要求一律为0。
        
    (4)类索引、父类索引与接口索引集合
            ---类索引:一个u2类型数据,用于确定这个类的全限定名,指向一个类型为CONSTANT_Class_info的类描述符常量。
            ---父类索引:一个u2类型数据,用于确定这个类的父类的全限定名,指向一个类型为CONSTANT_Class_info的类描述符常量。
            ---接口索引:一组u2类型数据的集合,用于确定这个类实现了哪些接口,入口的第一项是接口计数器。
    (5)字段表集合
            ---字段表用于描述接口或者类中声明的变量。字段包括类变量和实例变量,但不包括方法内部声明的局部变量。字段表结构如下表:
                        
            ---其中,access_flags为字段修饰符,可以设置的标志位和含义见下表:
                        
            ---name_index代表字段的简单名称,descriptor_index代表字段的描述符。
                · 全限定名:把类的完全限定名中的”.“替换成了”/“。
                · 简单名称:没有类型和参数修饰的方法或者字段名称。
                · 描述符:描述字段的数据类型、方法的参数列表(包括数量、类型及顺序)和返回值。描述符标识字符含义如下表:
                        
                ---对于数组类型,每一维度将使用一个前置的”[“字符来描述;
                ---用描述符描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号之内。
            ---字段表集合中不会列出从超类或者父接口中继承而来的字段,但有可能列出原本Java代码之中不存在的字段,例如在内部类中为了保持对外部类的访问性,会自动添加指向外部类实例的字段。
    (6)方法表集合
            ---类似字段表的内容。
            ---方法里的Java代码,经过编译器编译成字节码指令后,存放在方法属性表集合中一个名为”Code“的属性里面。
    (7)属性表集合
            略
 
3 字节码指令简介
    ---Java虚拟机的指令:由一个字节长度的、代表着某种特定操作含义的数字(即操作码)以及跟随其后的零至多个代表此操作所需参数而构成。
    ---由于Java虚拟机操作码的长度为一个字节,意味着字节码指令集的操作码总数不超过256条。
    (1)加载和存储指令
            ---用于将数据在栈帧中的局部变量表和操作数栈之间来回传输。包括
                · 将一个局部变量加载到操作栈,如iload;
                · 将一个数值从操作数栈存储到局部变量表,如istore;
                · 将一个常量加载到操作数栈,如bipush;
                · 扩充局部变量表的访问索引的指令:wide。
    (2)运算指令
            ---用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶。包括:
                · 加法指令,如iadd;
                · 减法指令,如isub;
                · 乘法指令,如imul;
                · 除法指令,如idiv;
                · 求余指令,如irem;
                · 取反指令,如ineg;
                · 位移指令,如ishl;
                · 按位或指令,如ior;
                · 按位与指令,如iand;
                · 按位异或指令,如ixor;
                · 局部变量自增指令,如iinc;
                · 比较指令,如dcmpg;
    (3)类型转换指令
            ---可以将两种不同的数值类型进行相互转换,可以用于
                · 实现用户代码中的显示类型转换操作;
                · 处理字节码指令集中数据类型相关指令无法与数据类型一一对应的问题。
            ---Java虚拟机直接支持以下数据类型的宽化类型转换:
                · int类型到long、float、或者double类型;
                · long类型到float、double类型;
                · float类型到double类型。
            ---int或long类型窄化转换为整数类型T的时候,丢弃除最低位N个字节以外的内容,N是类型T的数据类型长度。
            ---将一个浮点值窄化转换为整数类型T(int或long)的时候,遵循以下规则:
                · 若浮点值为NaN,转换结果为T类型的0;
                · 若浮点值不是无穷大的话,使用向零舍入模式取整,获得整数v,如果v在目标类型T的表示范围之内,那转换结果就是v;
                · 否则,根据v的符号,转换为T所能表示的最大或者最小整数。
            ---将double类型窄化转换为float类型:采用最接近数舍入模式得到一个可以使用float类型表示的数字,
                · 如果转换结果的绝对值太小而无法使用float来表示,将返回float类型的正负零;
                · 如果转换结果的绝对值太大而无法使用float来表示,将返回float类型的正负无穷大;
                · 对于double类型的NaN将按规定转换为float类型的NaN值。
            ---数据类型窄化转换可能发生上限溢出、下限溢出和精度丢失等,但永远不可能导致虚拟机抛出运行时异常。
    (4)对象创建和访问指令
            ---包括:
                · 创建类实例的指令:new;
                · 创建数组的指令:newarray、anewarray、multianewarray;
                · 访问类字段和实例字段的指令:getstatic、putstatic、getfield、putfield;
                · 把一个数组元素加载到操作数栈的指令,如baload;
                · 把一个操作数栈的值存储到数组元素中的指令,如bastore;
                · 取数组长度的指令:arraylength;
                · 检查类实例类型的指令:instanceof、checkcast。
    (5)操作数栈管理指令
            ---包括:
                · 将操作数栈的栈顶一个或者两个元素出栈:pop、pop2;
                · 复制栈顶一个或两个数值并将复制值或双份的复制值重新压入栈顶,如dup;
                · 将栈最顶端的两个数值互换:swap。
    (6)控制转移指令
    (7)方法调用和返回指令
    (8)异常处理指令
    (9)同步指令

深入理解Java虚拟机读书笔记3----类文件结构的更多相关文章

  1. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

  2. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

  3. 深入理解Java虚拟机读书笔记5----虚拟机字节码执行引擎

    五 虚拟机字节码执行引擎   1 运行时栈帧结构     ---栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素.     ---栈帧中存储了方法的局部变 ...

  4. 深入理解Java虚拟机读书笔记9----线程完全与锁优化

    九 线程完全与锁优化   1 Java语言中的线程完全         ---线程安全:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用 ...

  5. 深入理解Java虚拟机读书笔记8----Java内存模型与线程

    八 Java内存模型与线程   1 Java内存模型     ---主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.     ---此处的变量和J ...

  6. 深入理解Java虚拟机读书笔记7----晚期(运行期)优化

    七 晚期(运行期)优化 1 即时编译器(JIT编译器)     ---当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”,包括被多次调用的方法和被多次执行的循环体.     ...

  7. 深入理解Java虚拟机读书笔记4----虚拟机类加载机制

    四 虚拟机类加载机制 1 类加载机制     ---概念:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.     -- ...

  8. 深入理解Java虚拟机读书笔记1----Java内存区域与HotSpot虚拟机对象

    一 Java内存区域与HotSpot虚拟机对象 1 Java技术体系.JDK.JRE?     Java技术体系包括:         · Java程序设计语言:         · 各种硬件平台上的 ...

  9. 深入理解java虚拟机读书笔记1--java内存区域

    Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随 ...

随机推荐

  1. shiro注解

    shiro注解权限控制-5个权限注解 RequiresAuthentication: 使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证. Requi ...

  2. vue项目打包后的资源路径问题

    最近做的vue项目,本地测试完成后,build上线,却发现了文件路径问题,提示各种诸如js,css等资源找不到的错: 正确解决方式有两种,一种是绝对路径配置,详细可以网上查,个人推荐第二种相对路径,这 ...

  3. Scala基础

    1.seq[String] 用[]表示参数类型,java使用<>表示参数,因为Scala 允许以<命名方法和变量名,java不允许 2.支持range的类型:Char .Int . ...

  4. 使用LNMP架构部署动态网站环境(源代码安装)

  5. vim-go 安装

    vim-go 安装 https://studygolang.com/articles/3229

  6. Oracle 相关知识

    1.Navicat 连接Oracle 报错: 解决办法: 1).先下载oracle客户端,win64_11gR2_client.zip,下载地址:http://www.oracle.com/techn ...

  7. delphi 多线程之 TEvent 和 TLightweightEvent

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  8. Git 日常操作

    本地新建Git库步骤: 初始化git库:git init 建立本地和远程的关联: git remote add origin ip:端口/ 项目.git 从远程下载所有分支到本地:git  fetch ...

  9. Fibonacci_array

    重新开始学习C&C++ Courage is resistance to fear, mastery of fear, not abscence of fear //斐波那契数列 Fibona ...

  10. C#用反射实现两个类的对象之间相同属性的值的复制

    在进行实体转换操作的时候如果需要在对两个实体之间两个属性字段差不多相同的类要进行一个互相的转换,我们要把a对象的所有字段的值都复制给b对象,我们只能用b.属性=a.属性来写,如果属性字段太多的话,就要 ...