你管这破玩意叫 class?

沙海 2021年3月23日01:34:40杂谈 Java评论67字数 6031阅读20分6秒阅读模式
摘要

速读摘要

速读摘要文章源自JAVA秀-https://www.javaxiu.com/6257.html

我马上就要把你载了,你先瘦身一下,别占太大地方。每个字符串都有一个索引与之对应,这个是可以计算出来的,不需要额外的字段。不过有了设计变量的经验,方法的数据结构很快就有了雏形。和变量标记部分的思路一样,值也差不多,我们也给他们赋上值就好了。我们效仿常量池的做法,把这些部分都叫"方法的属性",一个方法可能有多个属性,设计结构如下。文章源自JAVA秀-https://www.javaxiu.com/6257.html

原文约 3524 | 图片 26 | 建议阅读 8 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?

程序员小灰 文章源自JAVA秀-https://www.javaxiu.com/6257.html

以下文章来源于低并发编程,作者闪客sun文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

低并发编程文章源自JAVA秀-https://www.javaxiu.com/6257.html

战略上藐视技术,战术上重视技术文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

我是一个 .java 文件,名叫 FlashObject.java,叫我小渣就行。文章源自JAVA秀-https://www.javaxiu.com/6257.html

public class FlashObject {    private String name;    private int age;        public String getName() {        return name;    }    public int add(int a, int b) {        return a + b;    }}
文章源自JAVA秀-https://www.javaxiu.com/6257.html

我马上就要被 JVM 虚拟机老大加载并运行了,此时老虚走了过来。文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:小渣呀,我马上就要把你载了,你先瘦身一下,别占太大地方。文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:好的,没问题,等我十秒钟。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

public class FlashObject{private String name;private int age;public int add(int a,int b){return a+b;}文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:老虚,我瘦身好了,你看看。文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:...,你是不是有病。文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:怎么了,我把没用的空格和回车啥的都去掉了,瘦身了好多呢!文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:行吧,看你这智商,我就给你解释解释。你现在仍然是个文本文件,让你瘦身是让你定一个紧凑的数据结构来表示你这个 Java 文件里的信息,然后告诉我这个数据结构中每个字节都代表什么。文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:哦哦,这样啊。文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:对啊,这样一是方便我去加载,二是我这个虚拟机可不只是为你 Java 语言服务的,还有很多语言最终都可以转换为我虚拟机识别的,你得设计一个通用的格式。文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:嗯嗯,这回我明白啦!文章源自JAVA秀-https://www.javaxiu.com/6257.html

 文章源自JAVA秀-https://www.javaxiu.com/6257.html

1文章源自JAVA秀-https://www.javaxiu.com/6257.html

类信息文章源自JAVA秀-https://www.javaxiu.com/6257.html

 文章源自JAVA秀-https://www.javaxiu.com/6257.html

我的类名叫 FlashObject。文章源自JAVA秀-https://www.javaxiu.com/6257.html

先找个地方把它存起来,放开头吧。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

这里的一个小方格是 1 个字节,也就是 8 位。一个英文字母用 ASCII 码表示为 1 个字节,所以占一个方格,之后不再解释。文章源自JAVA秀-https://www.javaxiu.com/6257.html

严谨的我又想到,这个类应该还有其父类文章源自JAVA秀-https://www.javaxiu.com/6257.html

虽然这个 .java 文件中没写,但也有其默认父类,Object。文章源自JAVA秀-https://www.javaxiu.com/6257.html

当然,我们得记录下全类名文章源自JAVA秀-https://www.javaxiu.com/6257.html

java/lang/Object文章源自JAVA秀-https://www.javaxiu.com/6257.html

记在哪里呢?就紧跟在类名后面吧。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

诶不对,我这个类名呀,父类名呀,都是变长的,这样紧挨着放,谁知道分界点在哪。文章源自JAVA秀-https://www.javaxiu.com/6257.html

不行不行,得分别在前面加个长度,就用两字节表示吧。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

除了父类之外,还有接口名呢!虽然我们这个类没写,但也得定义出来。文章源自JAVA秀-https://www.javaxiu.com/6257.html

这个接口,和类名以及父类名稍有不同,因为可能有多个。文章源自JAVA秀-https://www.javaxiu.com/6257.html

但这不是事儿,先占用两个字节,表示接口的数量即可,之后一个一个的接口名仍然像上面那样紧挨着排布。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

嗯,完美。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

2文章源自JAVA秀-https://www.javaxiu.com/6257.html

常量池文章源自JAVA秀-https://www.javaxiu.com/6257.html

慢慢地,我发现需要字符串名字的地方越来越多。文章源自JAVA秀-https://www.javaxiu.com/6257.html

除了刚刚的类名、父类名、接口名,还有属性名、方法名、属性的类名、方法的入参类型名、返回值类型名,等等等等。文章源自JAVA秀-https://www.javaxiu.com/6257.html

一方面,要是每个都这么展开写下去,那文件格式会很乱,很多结构都是变长的。文章源自JAVA秀-https://www.javaxiu.com/6257.html

另一方面,很多字符串都是重复的,比如属性 name 的类名 String,与方法 getName 的返回值类名 String,重复写两遍,就浪费了空间。文章源自JAVA秀-https://www.javaxiu.com/6257.html

因此,我决定,之前的方案作废,设计一个新的结构来统一存储这些字符串,我给他起名为常量池文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

每个字符串都有一个索引与之对应,这个是可以计算出来的,不需要额外的字段。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

这样,刚刚的类、父类、接口,就都可以指向这个索引了,也因此可以将长度固定下来。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

当然,现在这个常量池,仅仅存放了字符串。文章源自JAVA秀-https://www.javaxiu.com/6257.html

不难想到,还可能有整型、浮点型的值作为常量,甚至还有可能是个引用类型,然后这个引用类型再次指向常量池中的一个索引,有点像指针的指针。文章源自JAVA秀-https://www.javaxiu.com/6257.html

那这么多类型,必然就还需要一个记录类型信息的地方,看来我们得将之前的设计改改。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

这样,我们的常量池,就不单单可以存储简单的字符串常量了,而是可以根据不同类型,存储与其相对应的数据结构的值。文章源自JAVA秀-https://www.javaxiu.com/6257.html

当然,我们常量池的整体结构还是不变的,只不过里面是类型丰富的结构。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

同样,我们的整个设计,也没有因为常量池的小改动,受到影响。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

OK,总结一下我们目前的整体方案。文章源自JAVA秀-https://www.javaxiu.com/6257.html

开头存常量池,之后需要的常量就全往这里放,用一个索引指向它即可。文章源自JAVA秀-https://www.javaxiu.com/6257.html

紧接着存放类本身的相关信息,我们存放了当前类、父类以及接口的信息。文章源自JAVA秀-https://www.javaxiu.com/6257.html

看来老虚要求的瘦身工作,已经初具规模啦。文章源自JAVA秀-https://www.javaxiu.com/6257.html

 文章源自JAVA秀-https://www.javaxiu.com/6257.html

3文章源自JAVA秀-https://www.javaxiu.com/6257.html

变量文章源自JAVA秀-https://www.javaxiu.com/6257.html

 文章源自JAVA秀-https://www.javaxiu.com/6257.html

现在类本身的信息,已经找到合适的位置存放起来了,接下来我们存变量。文章源自JAVA秀-https://www.javaxiu.com/6257.html

变量也可能有多个,所以结构依然仿照我们之前的思路,开头存数量,后面紧跟着各个存放变量的数据结构。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

至于变量用什么数据结构来存,是不是定长的,那就是我们接下来要设计的了。文章源自JAVA秀-https://www.javaxiu.com/6257.html

我们把其中一个变量拿出来,看看它有什么?文章源自JAVA秀-https://www.javaxiu.com/6257.html

private String name;文章源自JAVA秀-https://www.javaxiu.com/6257.html

非常清晰,private 这部分是变量的标记,String 是变量类型,name 是变量名字。文章源自JAVA秀-https://www.javaxiu.com/6257.html

先看标记部分文章源自JAVA秀-https://www.javaxiu.com/6257.html

除了 private,还有 public、protected、static、final、volatile、transient 等,有的可以放在一起,比如文章源自JAVA秀-https://www.javaxiu.com/6257.html

public static final String name;文章源自JAVA秀-https://www.javaxiu.com/6257.html

有的不能放在一起,比如文章源自JAVA秀-https://www.javaxiu.com/6257.html

public private String name; //错误文章源自JAVA秀-https://www.javaxiu.com/6257.html

我们用位图的方式,每一个标记用一个位来表示(比如 public 在第一个位,private 在第二个位,static 在第四个位,final 在第五个位...),这样不论如何排列组合,最终的值都是不一样的。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

我们把这些标记所对应的值,都设计并记录下来。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

标记文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

public文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0001文章源自JAVA秀-https://www.javaxiu.com/6257.html

private文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0002文章源自JAVA秀-https://www.javaxiu.com/6257.html

protected文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0004文章源自JAVA秀-https://www.javaxiu.com/6257.html

static文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0008文章源自JAVA秀-https://www.javaxiu.com/6257.html

final文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0010文章源自JAVA秀-https://www.javaxiu.com/6257.html

volatile文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0040文章源自JAVA秀-https://www.javaxiu.com/6257.html

transient文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0080文章源自JAVA秀-https://www.javaxiu.com/6257.html

复合型的标记,就可以表现为将其相加,比如 public static,就是 0x0001 + 0x0008 = 0x0009。文章源自JAVA秀-https://www.javaxiu.com/6257.html

而这样的赋值方式,不同排列组合后的和没有重复的,且也能根据值很方便地反推出标记。文章源自JAVA秀-https://www.javaxiu.com/6257.html

不错不错,就这样了。文章源自JAVA秀-https://www.javaxiu.com/6257.html

哦对了,类信息本身也有 public 呀 private 这些标记属性,刚刚记录类信息的时候忘了,先加上它,免得一会忘了!文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

再看类型部分文章源自JAVA秀-https://www.javaxiu.com/6257.html

当前类型为 String,属于一个引用数据类型中的类类型文章源自JAVA秀-https://www.javaxiu.com/6257.html

private String name;文章源自JAVA秀-https://www.javaxiu.com/6257.html

除此之外,还有八个基本数据类型,和引用类型中的数组类型文章源自JAVA秀-https://www.javaxiu.com/6257.html

为了占用更少的空间,我们将其用最少的符号来表示。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

符号表示文章源自JAVA秀-https://www.javaxiu.com/6257.html

类型文章源自JAVA秀-https://www.javaxiu.com/6257.html

B文章源自JAVA秀-https://www.javaxiu.com/6257.html

byte文章源自JAVA秀-https://www.javaxiu.com/6257.html

C文章源自JAVA秀-https://www.javaxiu.com/6257.html

char文章源自JAVA秀-https://www.javaxiu.com/6257.html

D文章源自JAVA秀-https://www.javaxiu.com/6257.html

double文章源自JAVA秀-https://www.javaxiu.com/6257.html

F文章源自JAVA秀-https://www.javaxiu.com/6257.html

float文章源自JAVA秀-https://www.javaxiu.com/6257.html

I文章源自JAVA秀-https://www.javaxiu.com/6257.html

int文章源自JAVA秀-https://www.javaxiu.com/6257.html

J文章源自JAVA秀-https://www.javaxiu.com/6257.html

long文章源自JAVA秀-https://www.javaxiu.com/6257.html

S文章源自JAVA秀-https://www.javaxiu.com/6257.html

short文章源自JAVA秀-https://www.javaxiu.com/6257.html

Z文章源自JAVA秀-https://www.javaxiu.com/6257.html

boolean文章源自JAVA秀-https://www.javaxiu.com/6257.html

LClassName ;文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

[文章源自JAVA秀-https://www.javaxiu.com/6257.html

数组文章源自JAVA秀-https://www.javaxiu.com/6257.html

里的基本数据类型,和数组类型,都只占用一个 char 来表示,就只占了 1 个字节。文章源自JAVA秀-https://www.javaxiu.com/6257.html

如果是类,则占用了 L 和 ; 两个字节,再加上全类名所占的字节数。文章源自JAVA秀-https://www.javaxiu.com/6257.html

比如这里的 String 类型,用符号表示,就是文章源自JAVA秀-https://www.javaxiu.com/6257.html

Ljava/lang/String;文章源自JAVA秀-https://www.javaxiu.com/6257.html

但注意,这里的符号,也都可以存放在常量池中,而我们的变量结构中的类型描述符部分,只需要一个常量池索引即可。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

ok,第二部分也搞定了。文章源自JAVA秀-https://www.javaxiu.com/6257.html

再看名字部分文章源自JAVA秀-https://www.javaxiu.com/6257.html

名字部分没什么好说的,相信你直接能猜到了,直接上图。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

OK,两字节的标记、两字节的类型描述符、两字节的变量名称,这个就是我们一个变量的数据结构。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

把它放到我们最终的总视图里。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

搞定!文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

4文章源自JAVA秀-https://www.javaxiu.com/6257.html

方法文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

方法也可能会有很多,我目前只有两个方法,我们拿 add 方法来分析。文章源自JAVA秀-https://www.javaxiu.com/6257.html

public int add(int a, int b) {    return a + b;}
文章源自JAVA秀-https://www.javaxiu.com/6257.html

当然更准确地说,我还有个没写出来的构造方法。文章源自JAVA秀-https://www.javaxiu.com/6257.html

总之,可能会有很多。文章源自JAVA秀-https://www.javaxiu.com/6257.html

不过有了设计变量的经验,方法的数据结构很快就有了雏形。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

标记部分,和变量标记部分的思路一样,值也差不多,我们也给他们赋上值就好了。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

标记文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

public文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0001文章源自JAVA秀-https://www.javaxiu.com/6257.html

private文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0002文章源自JAVA秀-https://www.javaxiu.com/6257.html

protected文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0004文章源自JAVA秀-https://www.javaxiu.com/6257.html

static文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0008文章源自JAVA秀-https://www.javaxiu.com/6257.html

final文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0010文章源自JAVA秀-https://www.javaxiu.com/6257.html

volatile文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0040文章源自JAVA秀-https://www.javaxiu.com/6257.html

transient文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0080文章源自JAVA秀-https://www.javaxiu.com/6257.html

synchronized文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0020文章源自JAVA秀-https://www.javaxiu.com/6257.html

native文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0100文章源自JAVA秀-https://www.javaxiu.com/6257.html

abstract文章源自JAVA秀-https://www.javaxiu.com/6257.html

0x0400文章源自JAVA秀-https://www.javaxiu.com/6257.html

方法描述符,说的是方法的入参与返回值,比如我们的:文章源自JAVA秀-https://www.javaxiu.com/6257.html

int add(int a, int b);文章源自JAVA秀-https://www.javaxiu.com/6257.html

入参与返回值的类型符号表示,与上面变量类型的符号表示完全一样,只不过多了一个 void 类型。文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

符号表示文章源自JAVA秀-https://www.javaxiu.com/6257.html

类型文章源自JAVA秀-https://www.javaxiu.com/6257.html

B文章源自JAVA秀-https://www.javaxiu.com/6257.html

byte文章源自JAVA秀-https://www.javaxiu.com/6257.html

C文章源自JAVA秀-https://www.javaxiu.com/6257.html

char文章源自JAVA秀-https://www.javaxiu.com/6257.html

D文章源自JAVA秀-https://www.javaxiu.com/6257.html

double文章源自JAVA秀-https://www.javaxiu.com/6257.html

F文章源自JAVA秀-https://www.javaxiu.com/6257.html

float文章源自JAVA秀-https://www.javaxiu.com/6257.html

I文章源自JAVA秀-https://www.javaxiu.com/6257.html

int文章源自JAVA秀-https://www.javaxiu.com/6257.html

J文章源自JAVA秀-https://www.javaxiu.com/6257.html

long文章源自JAVA秀-https://www.javaxiu.com/6257.html

S文章源自JAVA秀-https://www.javaxiu.com/6257.html

short文章源自JAVA秀-https://www.javaxiu.com/6257.html

Z文章源自JAVA秀-https://www.javaxiu.com/6257.html

boolean文章源自JAVA秀-https://www.javaxiu.com/6257.html

LClassName ;文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

[文章源自JAVA秀-https://www.javaxiu.com/6257.html

数组文章源自JAVA秀-https://www.javaxiu.com/6257.html

V文章源自JAVA秀-https://www.javaxiu.com/6257.html

void文章源自JAVA秀-https://www.javaxiu.com/6257.html

由于有多个参数类型,所以要定一个整体的格式,而整个描述符的格式为:文章源自JAVA秀-https://www.javaxiu.com/6257.html

( 参数1类型 参数2类型 ... ) 返回值类型文章源自JAVA秀-https://www.javaxiu.com/6257.html

比如我们的文章源自JAVA秀-https://www.javaxiu.com/6257.html

int add(int a, int b);文章源自JAVA秀-https://www.javaxiu.com/6257.html

就表示为文章源自JAVA秀-https://www.javaxiu.com/6257.html

(II)I文章源自JAVA秀-https://www.javaxiu.com/6257.html

是不是非常精简了?同样,这也是个字符串,也可以存储在常量池里,就不再赘述。文章源自JAVA秀-https://www.javaxiu.com/6257.html

(至于参数 a 和 b 这个名字,不需要保存起来,实际上在转换的字节码以及实际虚拟机中运行时,只需要知道局部变量表中的位置即可,叫什么名字都无所谓)文章源自JAVA秀-https://www.javaxiu.com/6257.html

方法名称,我们再熟悉不过了,放常量池!文章源自JAVA秀-https://www.javaxiu.com/6257.html

ok,前三个说完了。最后一个,就有意思了。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

代码、异常、注解等。以看到,有相当多的信息需要记录。文章源自JAVA秀-https://www.javaxiu.com/6257.html

比如我写这样的方法。文章源自JAVA秀-https://www.javaxiu.com/6257.html

@RequestMapping()public String function(String a) throws Exception {    return a;}
文章源自JAVA秀-https://www.javaxiu.com/6257.html

那就会有代码部分、异常、注解等需要录入的信息。文章源自JAVA秀-https://www.javaxiu.com/6257.html

但似乎除了代码部分之外,其他部分都不是每个方法都有的,如果都定义出来,岂不是浪费空间,那怎么办呢?文章源自JAVA秀-https://www.javaxiu.com/6257.html

我们效仿常量池的做法,把这些部分都叫“方法的属性”,一个方法可能有多个属性,设计结构如下。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

这样,方法具有哪些属性,按需添加进来就好,如果不需要这个属性,也不用浪费空间,完美!文章源自JAVA秀-https://www.javaxiu.com/6257.html

回过头看我们的这个方法。文章源自JAVA秀-https://www.javaxiu.com/6257.html

public int add(int a, int b) {    return a + b;}
文章源自JAVA秀-https://www.javaxiu.com/6257.html

刚刚方法签名部分已经都解决了,只剩下代码文章源自JAVA秀-https://www.javaxiu.com/6257.html

return a + b;文章源自JAVA秀-https://www.javaxiu.com/6257.html

这个要怎样存放呢?文章源自JAVA秀-https://www.javaxiu.com/6257.html

之前听老虚说过,JVM 识别的是一种叫字节码的东西,所以我要把 Java 语言写出的代码,转换为字节码。文章源自JAVA秀-https://www.javaxiu.com/6257.html

这部分很复杂,就不展开说我的过程了,经过一番努力后,我把这一行简简单单的代码转换为了字节码。文章源自JAVA秀-https://www.javaxiu.com/6257.html

1B 1C 60 AC文章源自JAVA秀-https://www.javaxiu.com/6257.html

一共占四个字节。文章源自JAVA秀-https://www.javaxiu.com/6257.html

我把这四个字节,就放在刚刚代码类型的属性中。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

ok,大功告成。文章源自JAVA秀-https://www.javaxiu.com/6257.html

回过头,我们将之前的方法部分补充完整。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

再将这个结构,添加到我们全局结构中。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

完美!文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

5文章源自JAVA秀-https://www.javaxiu.com/6257.html

class文章源自JAVA秀-https://www.javaxiu.com/6257.html

我把我转换为了这样的结构,并带着这个最终的设计稿,去找了老虚。文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:嗯!还真不赖!文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:那当然,我可是研究了好久呢。文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:不过,我再给你改改,在开头加些东西把。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:老虚,你这加的是啥呀?文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:一看你就没经验。文章源自JAVA秀-https://www.javaxiu.com/6257.html

魔数一般用来识别这个文件的格式,通过文件名后缀的方式不靠谱,一般有格式的文件都会有个魔数的。文章源自JAVA秀-https://www.javaxiu.com/6257.html

后面两个用来标识一下版本号,不同版本可能数据结构和支持的功能不一样,这个今后会有用的!文章源自JAVA秀-https://www.javaxiu.com/6257.html

小渣:原来如此,还是你老虚见多识广。可是你说用来识别这个文件的格式,我这个文件是啥呀?文章源自JAVA秀-https://www.javaxiu.com/6257.html

老虚:你这个破玩意,就叫它 class 文件吧!文章源自JAVA秀-https://www.javaxiu.com/6257.html

FlashObject.class文章源自JAVA秀-https://www.javaxiu.com/6257.html

后记文章源自JAVA秀-https://www.javaxiu.com/6257.html

根据 Java 虚拟机规范,Java Virtual Machine Specification Java SE 8 Edition,一个 class 文件的标准结构,是这样的。文章源自JAVA秀-https://www.javaxiu.com/6257.html

ClassFile {    u4             magic;    u2             minor_version;    u2             major_version;    u2             constant_pool_count;    cp_info        constant_pool[constant_pool_count-1];    u2             access_flags;    u2             this_class;    u2             super_class;    u2             interfaces_count;    u2             interfaces[interfaces_count];    u2             fields_count;    field_info     fields[fields_count];    u2             methods_count;    method_info    methods[methods_count];    u2             attributes_count;    attribute_info attributes[attributes_count];}
文章源自JAVA秀-https://www.javaxiu.com/6257.html

我们的设计与它几乎相同。文章源自JAVA秀-https://www.javaxiu.com/6257.html

只有后两项,我们没有涉及到,本身也不是重点。文章源自JAVA秀-https://www.javaxiu.com/6257.html

常量池中的类型,有以下几种。文章源自JAVA秀-https://www.javaxiu.com/6257.html

Constant Type
Value
CONSTANT_Class
7
CONSTANT_Fieldref
9
CONSTANT_Methodref
10
CONSTANT_InterfaceMethodref
11
CONSTANT_String
8
CONSTANT_Integer
3
CONSTANT_Float
4
CONSTANT_Long
5
CONSTANT_Double
6
CONSTANT_NameAndType
12
CONSTANT_Utf8
1
CONSTANT_MethodHandle
15
CONSTANT_MethodType
16
CONSTANT_InvokeDynamic
18

如果想了解 class 文件的全部细节,最好的办法就是阅读官方文档,也就是 Java 虚拟机规范的第四部分。文章源自JAVA秀-https://www.javaxiu.com/6257.html

Chapter 4. The class File Format文章源自JAVA秀-https://www.javaxiu.com/6257.html

这里的链接可以直接定位:文章源自JAVA秀-https://www.javaxiu.com/6257.html

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2文章源自JAVA秀-https://www.javaxiu.com/6257.html

不要觉得官方文档晦涩难懂,这个部分还是非常清晰明了的,大多数博客基本上对格式的讲解都缺斤少两,而且说得也不形象,还不如直接阅读官方文档呢。文章源自JAVA秀-https://www.javaxiu.com/6257.html

还有一个好的方式,就是直接观察 class 文件的二进制结构解析,这里推荐一个工具文章源自JAVA秀-https://www.javaxiu.com/6257.html

classpy文章源自JAVA秀-https://www.javaxiu.com/6257.html

用这个工具打开一个 class 文件,是这个样子。文章源自JAVA秀-https://www.javaxiu.com/6257.html

你管这破玩意叫 class?文章源自JAVA秀-https://www.javaxiu.com/6257.html

左边解析好的树型结构,可以直接和右边的 class 文件的二进制内容相对应,非常好用。文章源自JAVA秀-https://www.javaxiu.com/6257.html

最后,希望大家找时间用这个工具分析一个复杂的 class 文件,会很有帮助的。祝大家学会 class 文件。文章源自JAVA秀-https://www.javaxiu.com/6257.html

完~文章源自JAVA秀-https://www.javaxiu.com/6257.html

文章源自JAVA秀-https://www.javaxiu.com/6257.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
  • 版权声明:本站是JAVA秀团队的技术分享社区,我们会经常分享资源和教程。
  • 转载请注明:你管这破玩意叫 class? - JAVA秀 ☜(ˆ▽ˆ)
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定