java从编译到执行的过程
- 我们写的代码是.java文件
- 通难过javac编译成.class文件
- 当调用java命令时,会加载到classLoader内存中
java类库 String Object 等等
- 加载在内存中会调用字节码解释器或JIT即时编译器 解释或编译
即使编译 就是常用的一些方法会编译好放在内存中,下次来直接调用执行引擎
- 解释编译完成后,调用执行引擎执行
- 执行引擎操作的就是系统的硬件了
常见的JVM实现
JDK JRE JVM 三者关系
类加载的全过程
- 先是吧class文件读取到内存中 (loading 双亲委派机制)
- linking加载:
- Verification
验证文件是否符合JVM规定 - Preparation
静态成员变量赋默认值
Integer 默认值 0 Long 0L Double 0.0 复杂对象 null - Resolution
将类、方法、属性等符号引用解析为直接引用
常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
(就是将内存中的方法区中的名称跟值绑定关联起来)
- Verification
- initializing
- 调用类初始化代码 ,给静态成员变量赋初始值
- 调用类初始化代码 ,给静态成员变量赋初始值
类加载器
- Bootstrap (加载lib/rt.jar charset.jar 等核心类)
- Extension (加载 jre/lib/ext 包下的内容)
- App (通常自己写的类)
- CustomClassLoader(自定义加载)
- load - 默认值 - 初始值
- new - 申请内存 - 默认值 -分配内存空间 - 初始值
证明load加载过程
- 执行T.count的时候,先初始化T (load linking)
- count =0, t =null
- 当赋值的时候,先赋值t=2 在new T 执行构造方法进行count++
- 所以结果为 2+1
public class T001_ClassLoadingProcedure {
public static void main(String[] args) {
System.out.println(T.count);
}
}
class T {
public static int count = 2; //0
public static T t = new T(); // null
private T() {
count ++;
}
}
3
调换执行顺序
- 执行T.count的时候,先初始化T (load linking)
- count =0, t =null
- 当赋值的时候,先执行new T,执行构造方法,这时count 还是0 count++
- 再赋值count 把count 赋值为初始值 2
- 所以结果输出为2
public class T001_ClassLoadingProcedure {
public static void main(String[] args) {
System.out.println(T.count);
}
}
class T {
public static T t = new T(); // null
public static int count = 2; //0
private T() {
count ++;
}
}
2
懒加载
LazyLoading 五种情况
- new getstatic putstatic invokestatic指令,访问final变量除外
- java.lang.reflect对类进行反射调用时
- 初始化子类的时候,父类首先初始化
- 虚拟机启动时,被执行的主类必须初始化
- 动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化
public class T008_LazyLoading { //严格讲应该叫lazy initialzing,因为java虚拟机规范并没有严格规定什么时候必须loading,但严格规定了什么时候initialzing
public static void main(String[] args) throws Exception {
P p; //不加载
X x = new X(); //子类继承父类,初始化时,先加载父类,载加载子类
System.out.println(P.i); //被final修饰的对象,直接获取,不加载类
System.out.println(P.j); //会加载类,然后获取值
Class.forName("com.mashibing.jvm.c2_classloader.T008_LazyLoading$P"); //会加载类
}
public static class P {
final static int i = 8;
static int j = 9;
static {
System.out.println("P");
}
}
public static class X extends P {
static {
System.out.println("X");
}
}
}