zoukankan      html  css  js  c++  java
  • 《深入了解Java虚拟机》笔记-jvm 类加载机制

    一、类的初始化

    主动引用:比较常见的场景有

    1、使用new关键字去实例化一个对象,读取或者设置一个类的静态字段(被final修饰的静态常量除外,这样的字段会在编译阶段被放入常量池中,不会触发类的加载),调用一个类的静态方法。

    2、使用java.lang.reflect的方法对类进行反射调用的时候,如果类没有被初始化,则会初始化这个类

    3、当初始化一个子类的时候,如果其父类还没有进行初始化,则要先触发其父类的初始化。

    4、虚拟机启动时会初始化程序的入口类(比如包含main方法的那个类)

    以上的四种情形都是对类的主动引用,会触发类的初始化。

    被动引用:

    1、子类引用父类的静态变量,不会触发子类的初始化。对于一个静态变量,只有直接定义这个字段的类才会被初始化。

    class Parent {
        static {
            System.out.println("parent init!");
        }
        protected static String val = "jvm";
    }
    
    class Child extends Parent{
        static {
            System.out.println("child init");
        }
    }
    
    public class InitDemo{
        public static void main(String[] args) {
            System.out.println(Child.val);
        }
    }
    结果为:
    parent init!
    jvm

    子类没有被初始化

    2、常量在编译阶段会被放入到调用类的常量池中,本质上没有直接引用到定义常量的类,不会触发定义常量的类的初始化

    class Normal{
        public final static String str = "jvm";
        static {
            System.out.println("Normal init");
        }
    }
    
    public class ConstantDemo {
        public static void main(String[] args) {
            System.out.println(Normal.str);
        }
    }
    结果为:
    jvm
    
    Normal 类并没有被初始化

    上面的代码在执行过程中并没有输出Normal init,虽然ConstantDemo 在源码中引用了Normal类的常量str,但是在编译阶段此常量的值"jvm"存储到了ConstantDemo的常量池中,对常量Normal.str的引用转化成ConstantDemo对于自身常量池的引用了,因此不会触发Normal 类的初始化。

  • 相关阅读:
    Unity之图片压缩,批量设置,导入自动设置
    Unity之可寻址资源之初始化,下载
    最优二叉树
    独立任务最优调度问题
    石子合并问题
    linux初学笔记
    码农
    用循环打印出多种三角形
    人机猜拳(这是最近的一个总结)
    期末总结
  • 原文地址:https://www.cnblogs.com/wbringarden/p/9710862.html
Copyright © 2011-2022 走看看