浅入了解JVM

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
      将类、方法、属性等符号引用解析为直接引用
      常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
      (就是将内存中的方法区中的名称跟值绑定关联起来)
  • initializing
    • 调用类初始化代码 ,给静态成员变量赋初始值
      在这里插入图片描述

类加载器

  • Bootstrap (加载lib/rt.jar charset.jar 等核心类)
  • Extension (加载 jre/lib/ext 包下的内容)
  • App (通常自己写的类)
  • CustomClassLoader(自定义加载)

## 未完待续

  1. load - 默认值 - 初始值
  2. 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");
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值