虚拟机类加载技术 ---类加载时机

JAVA 类从被加载到虚拟机内存开始到卸载出内存为止, 它的生命周期包括了以下几个步骤:加载,验证,准备,解析,初始化,使用,卸载。其中验证,准备和解析统称为链接过程。发生的顺序如下下图所示:


       上图中,加载,验证,准备,初始化和卸载这几个步骤是确定的,类加载过程必须按照这个过程进行,然而解析阶段则不一定,它在目中情况下可以在初始化阶段之后再开始,这是为类支持java语言的动态绑定。

       1:什么时候会触发类加载?

       java虚拟机规范中并没有进行强制的约束,但是对于初始化阶段,虚拟机规范严格的规定有且只有5中情况,必须立即对类进行初始化(加载,验证,准备在此之前完成)  .

       1):遇到new,getstatic,putstatic,invokestatic这四条字节码指令时。如果类没有进行过初始化,则必须触发其初始化。这是条指令最长见的场景是。使用new操作,设置和获取类的静态字段(被final修饰的字段除外,已在编译期将其放入常量池中的字段除外).以及调用类的静态方法时。

      2): 使用reflect包中的方法对类进行反射调用的的时候,如果类中没有经过初始化,则需要先触发其初始化。

      3): 初始化一个类的时候,如果其父类还没有进行初始化是,则需要先触发其父类的初始化。

      4): 当虚拟机启动时,用户需要制定一个要执行的主类(包含main方法的类)虚拟机会先初始化这个主类。

      5): 使用JDK1.7动态语言支持时,如果一个MethodHandle实例最后解析的结果REF_getStatic, REF_putStatic,REF_invokeStatic 的方法和句柄,并且这个方法的所对应的类没有初始化,会先触发这个类的初始化。

1:本次主要讨论第一种情况,new,getstatic,putstatic,invokestatic字节码

package cn.zjdyms.classloader;

//显示类加载的过程需要添加虚拟机参数-XX:+TraceClassLoader/-verbose:class

public class Loading {

public static void main(String[] args) throws InterruptedException {

//Thread.sleep(5000);

System.out.println("------------------");

/*new NewLoader();

System.out.println(LoadingInner.i);

                System.out.println(LoadingInner2.j);

System.out.println(GetLoader.STR);

SetLoader.STR = "ss";

StaticMethod.say();*/

}

static class LoadingInner{

public static final int i = 0;

public static int j = 0;

}

       static class LoadingInner2{

public static int j = 0;

}

static class NewLoader{

static class GetLoader{

static String STR = "abcd";

}

static class SetLoader{

static String STR = "defg";

}

static class StaticMethod{

public static void say() {

System.out.println("helloWorld");

}

}

}

注释有加上时:打印输出


字节指令: 暂时不存在调用上述内部类的指令。


去除main方法中的注释,中间加载几个内部类但是没有加载LoadingInner类。


字节码指令:从字节码中可以看出为什么没有加载LoadingInner类。取值直接使用的iconst_0取得LoadingInner中的i值。是final修饰的字段并且是静态字段。


    剩余的指令就不做一一介绍了。


package cn.zjdym.learn;

public class StaticTest

{

    public static void main(String[] args)

    {

        staticFunction();

    }

 

    static StaticTest st = new StaticTest();

 

    static

    {

        System.out.println("1");

    }

 

    {

        System.out.println("2");

    }

 

    StaticTest()

    {

        System.out.println("3");

        System.out.println("a="+a+",b="+b);

    }

 

    public static void staticFunction(){

        System.out.println("4");

    }

 

    int a=110;

    static int b =112;

}

上面的方法的具体的输出有兴趣的可以自行测试。下次的详解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值