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 类的初始化。

  • 相关阅读:
    .NET:CLR via C# The CLR’s Execution Model
    VisualStudio:WEB 性能测试和负载测试 入门
    Maven:Maven 入门
    技术人生:东莞之行
    技术人生:新的生活计划
    Java:使用 Java 开发的一个异常处理框架
    .NET:命令行解析器介绍
    技术人生:希望有生之年开发一个“自己的解释语言”
    .NET:异常处理的两条“黄金定律”,求批!
    FAQ:Domain Event 和 C# 中的 Event 有啥区别?
  • 原文地址:https://www.cnblogs.com/wbringarden/p/9710862.html
Copyright © 2011-2022 走看看