怎么在百度建网站,太原做网站找谁,网站权重分为几个等级,公司网站建设youyi51无关性的基石
实现语言无关性的基础是虚拟机和字节码存储格式。Java虚拟机不与任何语言绑定#xff08;包括Java#xff09;#xff0c;它只与‘Class文件’这种特定的二进制文件格式所关联。Class文件中包含了Java虚拟机指令集、符号表以及其它辅助信息。出于安全考虑包括Java它只与‘Class文件’这种特定的二进制文件格式所关联。Class文件中包含了Java虚拟机指令集、符号表以及其它辅助信息。出于安全考虑《Java虚拟机规范》要求在Class文件中必须应用许多强制性的语法和结构化约束但图灵完备的字节码格。
Class类文件的结构
Class文件是一组以8个字节为基础的二进制流各项数据项目严格按照顺序紧凑的排列在文件中中间没有任务分隔符。当遇到需要占用8个字节以上空间的数据项时则会按照高位在前的方式分割成若干个8个字节进行存储。
高位在前 高位的字节存储在内存中的低位。
例如‘123456’ 那么1位高位的字节6为低位的字节加入有内存地址 012345那么0中存1,1中存2.。。。5中存6这种模式叫做高位在前也叫大端。
Class文件结构中包括两种数据结构‘无符号数’和‘表’。
无符号数是基本数据类型。用u1,u2,u3,u4来分别表示1个字节、2个字节、3个字节、4个字节。表是由一系列无符号数或者其他表组成的复合数据结构。所有的表都习惯性的以”_info“结尾。
Class文件格式表 P215 魔数
魔数用来确定该文件是否为能被JVM所接受的Class文件。
现写两个Java类
package j1;public class Test {private String item itemStr;public String nothing(){return item;}
}
package j1;public class Test1 {private int count 1;public int inc() {return count 1;}
}
将其编译后用notepad或者sublime打开
可以看到在十六进制下两个Class文件的头四个字节是cafebabe这四个字节就是魔数。为什么说cafebabe是四个字节呢因为这里是16进制1个字节占8位需要用两位十六进制符号表示例如 11001101用十六进制表示应该为0XCD简写为CD.
次版本号
紧跟着魔数后面的两个字节为次版本号
主版本号 紧跟着次版本号后面的为主版本号0034由16进制转换为十进制后为52查询Class文件版本号可以找到JDK版本为JDK8.所以该文件能被JDK8及以上版本的虚拟机所执行。
常量池
主版本号后为常量池的的入口。常量池的入口放着一个u2类型的数据用来表示常量池中常量的数目。
0013表示常量池中有18项常量索引值范围为1-19。为什么0X0013转换为十进制后为19但是这里说常量池中有18项常量呢因为第一个常量存在索引为1的位置这么做是考虑到后面某些指向常量池的索引值的数据在特定的情况下需要表达“不引用任何一个常量池项目”的含义这个时候将索引值设为0即可来表示。
Class文件结构中只有常量池的容量计数是从1开始的其余都是从0开始。
常量池中主要存放两大类常量 字面量和符号引用
字面量
文本字符串被final修饰的常量等
符号引用
符号引用输入编译原理方面的概念
被模块导出或开放的包Packge类和接口的全限定名字段的名称和描述符方法的名称和描述符方法句柄和方法类型动态调用点和动态常量
描述符是什么方法句柄是什么动态调用是什么动态常量是什么
截止JDK13一共有17中不同类型的常量。现总结为如下
我们以Test1.class文件来分析 红框内的内容为常量池其内容按照常量池项目图来按图索骥即可。
利用命令javap -v Test1.class或者javap -verbose Test1.class来反编译字节码文件可以得到下图 其中Constant pool下项目与16进制文件中红框内容对应。
访问标志
常量池结束后紧接着的2个字节代表访问标志access_flags,这个标志用来表示一些类或者接口层次的访问信息。
比如说这个Class是类还是接口是否定义为Public类是否为Abstract类如果是类的话是否被声明为final等等。
access_flags一共有16个标志位可用当前定义了其中的9个。没有使用到的标志位为0.因此标志位的值也可以理解为是使用到的标志的位运算或。
图见 p224
类索引、父类索引、接口索引集合
类索引及父类索引都是一个u2类型的数据接口索引集合是一组u2类型的数据的集合。这三项数据确定了改类型的继承及实现关系。
类索引确定了这个类的全限定名父类索引确定了该类的父类的全限定名。除了java.lang.Object外其余类的父类索引都不为0.接口索引集合用来描述该类实现了哪些接口这些被实现的接口安装implements关键字若该类表示的是一个接口那么应该为extends后的接口顺序从左到右排列在索引集合中。对于接口索引集合入口的第一项u2类型的数据为接口的计数器表示索引表的容量也就是实现了几个接口若没有实现接口则值为0。可以看到这里有点类似常量池的结构。
字段表集合
图见 p226-227
字段表用来描述接口或者类中声明的变量。包括类级变量以及实例级变量但是不包括方法内部的局部变量。
全限定名 将类的全限定名中.“用”/代替后的字符串。
简单名称: 没有类型和参数修饰的方法或者字段。例如有个一方法public void test(int a,int b){}则该方法的简单名称为test。一个字段int a 1;其简单名称为”a“。
描述符 按照一定的规则来描述字段的类型、方法的参数列表数量类型及顺序和返回值。
描述符标识字符含义见P227
描述符的一些规则
对于数组每增加一个维度就使用一个前置的“[”来表述例如int[ ] [ ]对应的描述符为“[[I”。用描述符来描述方法时按照先参数列表后返回指的顺序来描述。例如java.lang.String.toString()的描述符为()Ljava/lang/String。
字段表中可能会有一个属性集合表用来存储一些额外的数据。
字段表集合中不会出现父类或者父接口中继承而来的字段但可能出现一些代码中不存在的字段。对于Class文件格式来讲只要两个字段的描述符不是完全相同的那字段重名就是合法的。
方法表集合
结构与字段表集合类似。图见P229
方法中的Java代码存在方法属性表集合中一个名为“Code”的属性里面。
tip
若父类方法没有在子类中重写方法表集合中就不会出现来自父类的方法信息。在编译时编译器可能向方发表自动添加方法比如类构造器“()”、实例构造器()Java中重载一个方法需要与原方法具有相同的简单名称及与原方法不同的特征签名。特征签名是指一个方法中各个参数在常量池中的字段符号引用集合。返回值不包括在特征签名中。
属性表集合
这段内容有点烦躁回头再看