CLINIT vs JVM Assemble "JASMIN"
A class or interface has at most one class or interface initialization method and is initialized (§5.5) by invoking that method. The initialization method of a class or interface has the special name <clinit>, takes no arguments, and is void (§4.3.3).
Other methods named <clinit> in a class file are of no consequence. They are not class or interface initialization methods. They cannot be invoked by any Java Virtual Machine instruction and are never invoked by the Java Virtual Machine itself.
具体翻译见文章
https://www.jianshu.com/p/7985df51017a
上边两段话大概意思是,JAVA 的类或接口最多只有一个clinit 方法(interface initialization method),而且这个方法必须无参,返回值为void,其他任务名字为clinit的方法都将被忽略。
In a class file whose version number is 51.0 or above, the method must additionally have its ACC_STATIC flag (§4.6) set in order to be the class or interface initialization method.
这段话说明在不同版本下是否需要ACC_STATIC(static)标记
e文基本搞懂了,如何验证翻译的对不对?
文章里说了,clinit方法非java源代码的关键字,通过源代码是无法验证的。
所以只能通过jvm汇编来实现。
-
第一种验证方式通过asm hardcode来验证,代码已经附在
https://www.jianshu.com/p/7985df51017a -
第二种通过jvm汇编代码来验证.
而我们所知的jvm 汇编器,sun官方是没有提供的,通过javap 可以反汇编,但不能修改汇编代码
缘于《基于JVM的汇编语言》一书,找到jasmin 项目。down下来源码,源码已经是2000年左右的代码,基于ant编译,笔者将源代码改成maven项目,提交到github上
https://github.com/sparrowzoo/sparrow-jasmin
项目的文档及demo都到项目中
有兴趣的同学可以fork。
另附 clinit 方法执行顺序
package com.sparrow.jdk.clinit;
public class Main {
static {
System.out.println("static init");
}
private static int i=initInt(1);
private static int j=initInt(2);
//java 源码中static 可以出现多次
static {
System.out.println("static init 2");
}
private static Integer initInt(int i){
System.out.println("static field init"+i);
return 100;
}
public static void main(String[] args) {
System.out.println("main method ");
}
}
网友评论