手机网站设计尺寸,c4d一般要学多久,医院网站页面设计,网站弹出代码Java 提供了一种可以在所有平台上都能使用的一种中间代码---字节码文件(.class文件)。有了字节码#xff0c;无论是那个平台只要安装了虚拟机都可以直接运行字节码文件。有了虚拟机#xff0c;解除了 java 虚拟机与 java 代码之间的耦合。
Java 虚拟机当初被设计出来时就不单…
Java 提供了一种可以在所有平台上都能使用的一种中间代码---字节码文件(.class文件)。有了字节码无论是那个平台只要安装了虚拟机都可以直接运行字节码文件。有了虚拟机解除了 java 虚拟机与 java 代码之间的耦合。
Java 虚拟机当初被设计出来时就不单单只运行 java 这一种语言目前 java 虚拟机已经可以支持很多除 java 语言以外的其它语言了比如 Groovy, JRuby, json, skilla等。之所以可以支持其它语言是因为这些语言经过编译之后也可以生成能够被 JVM 解析并执行的字节码文件。而虚拟机并不关心字节码是由哪一种语言编译而来如下图所示 class 文件
从纵观的角度看class 文件里只有两种数据结构无符号数和表。 无符号数属于基本的数据类型。以 u1u2u4u8来分别代表 1 个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用数量值或者字符串UTF-8编码。 表表由多个无符号数或者其它表作为数据项构成的复合数据类型。class 文件中所有的表都以“_info”结尾。整个 class 文件本质上就是一张表。
表和无符号数之间的关心 class 文件结构 无符号数和表组成了 class 中的各个结构这些结构按照预先规定好的顺序紧密的从前向后排列相邻的项之间没有任何间隙。当 JVM 加载某个 class 文件时JVM 就是根据上图中的结构去解析 class 文件。加载 class 文件到内存中并在内存中分配相应的内存空间具体某种结构需要占用多大的空间可以参考如下图 实例解析
把 test.java 编译成 test.class 文件。用十六进制编辑器打开 .class 文件可以用在线的编辑器 HexD.it。 package software_test;import java.io.Serializable;public class test implements Serializable, Cloneable {private int num 1;public int add(int i) {int j 10;num num i j;return num;}} 打开 test.class 文件的内容 1. 魔数(magic number) 在 class 文件开头的四个字节是 class 文件的魔数它是一个固定的值--0XCAFEBABE。魔数是 class 文件的标志它是判断一个文件是不是 class 格式文件的标准。
2. 版本号 前两个字节 0000代表次版本号minor_version)后两个字节 0034 是主版本号major_version)对应的十进制值为52当前 class 文件的主版本号为52次版本号为0所以综合版本号是52.0也就是 jdk1.8.0。
3. 常量池
紧跟在版本号之后的是一个叫做常量池的表cp_info)。在常量池中保存了类的各种相关信息比如类的名称、父类的名称、类中的方法名、参数名称、参数类型等。
常量池中的每一项都是一个表其项目类型共有14种。常量池中的每一项都会有一个 u1 大小的 tag 值是表的标识。 JVM 解析 class 文件时通过 tag 值来判断当前数据结构是哪一个表。例如CONSTANT_Class_info 表 tag占用一个字节大小值为为7说明是 CONSTANT_Class_info 类型表。
name_index是一个索引值可以将它理解为一个指针指向常量池中索引为 name_index 的常量表。比如 name_index 7则它指向常量池中第7个常量表表与表之间是有关联的。 再例如 CONSTANT_Utf8_info 表 tag值为1表示是 CONSTANT_Utf8_info类型表。
length表示 u1[]的长度比如length 5则表示接下来的数据是 5 个连续的u1类型数据。
bytes u1 类型数组长度为上面第2个参数 length 的值。
面试题Java 源文件中 String 字符串的长度 有限制吗
有字符串存储在Class文件的常量池中。在 Java 代码中声明的 String 字符串最终在 class 文件中的存储格式是 CONSTANT_utf8_info因此一个字符串最大长度也就是 u2 所能代表的最大值 655362^16 个但是需要使用2个来保存null值因此一个字符串的最大长度为 65536 - 2 65534。
class 文件在常量池的前面使用2个字节的容量计数器用来代表当前类中常量池的大小。 001D 转化为十进制为29即常量计数器的值为29。其中下标为0的常量被 JVM 留作其他特殊用途因此 Test.class 中时间的常量池大小为这个计数器的值减1也就是28个。
第一个常量 0A 转化为十进制为10通过查看常量池14种表格图可以查到 tag10的表类型为 CONSTANT_Methodref_info因此常量池中的第一个常量类型为类的方法引用表。其结构如下 也就是说0A之后的两个直接是指向该方法所属类再紧跟的两个字节指向此方法的名称和类型。 0006十进制为6表示指向常量池中的第6个常量
000F十进制为15表示指向常量池中的第 15 个常量。
至此第一个常量解读完毕
第二个常量 09转化为十进制为9即tag 9表示是字段引用表 CONSTANT_Fieldref_info其结构如下 同理 0010指向常量池中第 16 个常量0011指向常量池中第17个常量。
至此我们已经解析了常量池中的2个常量剩下的26个常量也是如此。
4. 访问标志 紧跟在常量池之后的常量是访问标志占用两个字节。访问标志代表类或者接口的访问信息。比如该 class 文件是类还是接口是否被定义成 public是否是 abstract如果是类是否被声明成 final 等。各种访问标志如下图所示 我们定义的 test.java 是一个普通 Java 类不是接口、枚举或注解并且被 public 修饰但没有被声明为 final 和 abstract因此它所对应的 access_flags 为 00210X0001 和 0X0020相结合。
5. 类索引、父类索引和接口索引计时器
访问标志后的2个字节就是类索引类索引后的2个字节就是父类索引父类索引后的2个字节则是接口索引计数器。如下图所示 综上所述我们可以得出当前类为 Test继承自 Object 类并实现了 “Serializable”和“Cloneable”这两个接口。
6. 字段表
紧跟在接口索引集合后面的就是字段表字段表的主要功能是用来描述类或者接口中声明的变量。这里的字段包含了类级别变量以及实例变量但不包含方法中的局部变量。其具体结构如下 字段访问标志 其中第7和8个常量就 num 和 i。因此可以得出类中有一个为num类型为 int 的变量。
7. 方法表
字段之后跟着的就是方法表常量方法表常量应该也是以一个计数器开始的因为一个类中的方法数量是不固定的。 上图表示 test.class中有两个方法但是我们只在 test.java 中声明了一个 add 方法因为默认构造器方法也被包含在方法表常量中。方法表结构如下 访问标志 8. 属性表
在之前解析字段和方法的时候在它们的具体结构中都能看到有一个叫做 attributes_info 的表这就是属性表。属性表没有一个固定结构各种不同的属性只要满足以下结构即可