java_编译器和解释器_类加载器
- 编译器
- 解释器
- 类加载器
编译器
- a.java 变成 a.class 就是编译器干的事,也就是你执行 javac a.java产出a.class的过程。 javac 就是 java compiler。
.java文件
package test;public class Test {public static void main(String[] args) {System.out.println("test");}
}
.class文件,也就是字节码文件。 机器码才是 0 1文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package test;public class Test {public Test() {}public static void main(String[] var0) {System.out.println("test");}
}
javap -c Test.class 可以查看 汇编文件 / 字节码指令文件,也就是jvm识别和执行的文件指令。 注意,不是机器码。
机器码 0 1 文件,cpu读取执行的;
汇编码是你jvm能看懂的
PS D:\workspace\learn\leetcode\src\test> javap -c Test.class
Compiled from "Test.java"
public class test.Test {public test.Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]);Code:0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String test5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return
编译器:静态编译器和动态编译器(即时编译器/JIT)。
JIT是后来有的。没有之前,就是静态编译器,也就是,jvm拿到字节码之后,翻译成机器码,再执行。
JIT来了之后:假如你的代码,有一段,是经常调用的(热点代码),JIT就把这段代码,翻译了之后,缓存在一个地方(codeCache),然后下次谁再调用,就不直接去这个地方拿机器码。从而达到动态、省时。
没错,我理解,JIT就是不用等到全部编译成机器码了再执行,边编译边执行
- 简单来说,编译器,就是把java源码编译成.class字节码文件,让jvm能看懂。
解释器
解释器把字节码解释成机器码执行。换句话说,就是jvm接收到了字节码,然后需要去执行,哪一行干什么事,就是解释器解释给系统的。
解释器有不需要编译就能看懂java源码的能力,所以它其实不需要编译这个过程也能执行代码。
类加载器
编译得到了字节码文件,需要将它加载到jvm中才能执行,这就是类加载器干的事情。
现在在来理解:
javac test.java|java test
javac就是编译过程
java就是启动jvm的过程,把.class文件拉到jvm中