class的来龙去脉
Java提供了一种可以在所有平台上都能使用的一种中间代码--字节码类文件(class文件)
- 有了字节码,无论哪种平台只要安装了虚拟机都可以直接运行字节码。
-
字节码,解除了java语言和java虚拟机的耦合,其它语言写的代码转换成字节码也可以在虚拟机上运行。
class的组成
从纵观的角度看,class文件里只有两种数据结构:无符号数和表
- 无符号数:属于基本的数据类型。以u1,u2,u4,u8来表示1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来表示数字、索引值、数量值或者字符串(UTF-8编码)。
- 表:表是由多个无符号数或者其它表作为数据项构成的复合数据类型。class文件中所有的表都以"_info"结尾,整个class文件本质上就是一张表。
无符号数和表组成了class的各个结构,这些结构按照预先规定好的顺序紧密的从前向后排列,相邻的项之间没有任何间隙
实例分析
魔数(magic number)
在class文件开头的四个字节是class文件的魔数,它是一个固定值--0xcafebabe ,魔数是class文件的标志,它是判断一个文件是不是class文件的标准。
版本号
紧跟在魔数后面的四个字节是版本号,前面两个字节代表次版本号,后两个字节代表主版本号。
常量池表(cp_info)
在常量池中保存了类的各种相关信息,比如类的名称、父类的名称、类中的方法名、参数名称、参数类型。
常量池的组织很简单,前端两个字节占有的位置叫做常量池计数器,它记录着常量池的组成元素(常量池项 cp _info)的个数。
每个常量池项都会对应记录着class文件中的某种类型的字面量。JVM根据常量池项中的tag来确定这个常量池项表示的是哪种类型的字面量。
注意 常量池中保存的主要是字面量和符号引用。
字面量是由字命、数字等构成的字符串或数值,字面值只以右值出现。比如 int a=10;string str=”hello“,其中的10 和”hello“都是字面量。
符号引用:符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量: * 类和接口的全限定名 * 字段的名称和描述符 * 方法的名称和描述符
package com.louis.jvm;
public class StringTest {
private String s1 = "JVM原理";
private String s2 = "JVM原理";
private String s3 = "JVM原理";
private String s4 = "JVM原理";
}
结合上图,#15的常量池项的tag=8,对应表示java.lang.string 的对象,查看表结构,结构体存放的是对#16常量项的指向,而#16存放的是真正的字符串内容。
访问标志(access flag)
紧跟在常量池之后的常量是访问标志,占用两个字节。代表着类或者接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。
类索引、父类索引、接口索引计数器
标志后2个字节就是类索引,类索引后两个字节是父类索引,父类索引后两个字节是接口索引计数器。
索引都是指向常量池的第某个常量。
字段表
字段表的主要功能是用来描述类或者接口中声明的变量。这里的字段包含类级别变量以及实例变量,不包括方法内部声明的局部变量。组成结构:字段计数器,字段访问标志,变量名索引,变量类型索引。
方法表
方法表主要描述类中的方法。也是以一个计数器开始的