public class Message {
public static void main(String[] args) {
System.out.printf("junshan say:Hello Word!");
}
}
Oolong的语法结构中以“.”符号开头表示这是一个基本的属性项,它对应到Java中就是表示一个Java的基本概念,如一个类、一个方法、一个属性、一个对象或者一个接口等。
类相关的指令
.source Message.java
表示这个代码的源文件是Message.java
.class public Message
表示这是一个类且公有的类名是Message
.super java/lang/Object
表示这个类的父类是Object
方法的定义
.method public <init> ()V
表示这是一个公有方法,没有参数,返回值类型是V
(也就是void),<init>
表示是构造函数
下面的.method public static main([Ljava/lang/String;)V
表示的是main方法,它的参数是一个String类型的数组,其中[
表示的是数组,而L
表示的是一个类形式而不是基本数据类型,凡是L
表示的类后面都会以;
结尾,表示这个类的结束。
常量池
class文件中的常量池如下:
每个常量都是由三个字节来描述的。
第一个字节表示这个常量是什么类型的常量,JVM定义了12种类型的常量,每个种类的常量都会对应一个数值。
这些常量通常都是相互引用的,是一个常量引用了另一个常量。
UTF8常量类型
它可以存储多个字节长度的字符串值,如可以存储类名或者方法名等很长的一个字符串。
UTF8类型的常量由前两个字节来表示后面所存储的字符串的总字节数
01003c
其中的3c
表示后面所跟的字节长度有60个。
UTF8常量由三部分表示,包括这个常量是什么格式的,这个常量有多少个字节,后面就是这个常量实际的内容。
Fieldred、Methodref常量类型
为了描述Class中的属性项和方法。
0900100011
Fieldref类型常量
- 前一个字节表示这个常量是Fieldref类型,所以是09
- 后面两个字节表示的是该Fieldref是哪个类中的Field,存储的值是第几个常量的位置
- 后面两个字节表示的是这个Fieldref常量的Name和Type,同样它也是指向NameAndType类型常量的索引
Class常量类型
Class常量表示的是该类的名称,它会指向另外一个UTF8类型的常量,该常量存储的是该类的具体名称
07表示的是Class类型的常量,后面的两个字节表示的是19个常量,而第19个常量正是一个UTF8类型的常量,该常量存储的是java/lang/Object
,也就是该类的名称。
NameAndType常量类型
为了表示Methodref和Fieldref的名称和类型描述做进一步说明而存在的,名称通常又由UTF8常量类型来表示,而类型描述也由UTF8来表示,所以NameAndType类型是由一个字节的类型表示加上两个字节的UTF8的位置索引组成的。
- 0007指向的是第7个常量,表示的是这个Methodref或者Fieldref的名称
- 0008表示的是Methodref的返回类型或者Fieldref的参数类型
类信息
常量列表的后面就是关于这个类本身的信息描述了,如这个类的访问控制、名称和类型,以及是否有父类或者实现了某些接口等描述信息。
由两个字节表示这个类的访问控制描述
类访问控制的两个字节中实际上只使用了5个bit,其他的bit还没有定义,这5个bit中第一个bit表示的是该类是否是public的,为1的话就是public类,否则就是private类。所以对类的访问修饰只有两种,要么是public要么是private。
第5个bit表示的是该类是否是final类,1表示是,0表示否。
第6个bit描述该类是否含有invokespecial,也就是是否继承其他类,在Java中所有的类默认都继承了Object类。
第10个bit描述了该类是否是接口类,0表示不是接口类,1是接口类。
第12个bit表示该类是否是抽象类,0表示不是抽象类,1表示是抽象类。
后面两个字节0006是该类的类名称,它指向的是第6个常量,0004表示的是该父类的类名称,它指向的是第4个常量定义的名称,再后面的0000表示该类没有实现接口类。