Java 触发类加载的六大时机! | CSDN 博文精选

2019 年 10 月 16 日 程序人生
作者 | weiwenhou

责编 | 刘静

出品 | CSDN博客


前言


什么情况下会触发类加载的进行呢?本文将结合代码demo谈谈几种情况,希望对大家有帮助。


类加载时机


什么情况需要开始类加载过程的第一阶段:加载?Java虚拟机规范中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,虚拟机规范则严格规定了以下几种情况必须立即对类进行初始化,如果类没有进行过初始化,则需要先触发其初始化。


创建类的实例


为了验证类加载,我们先配置一个JVM参数
-XX:+TraceClassLoading 监控类的加载

在IDE配置如下:

demo代码:

public class ClassLoadInstance {    
    static {    
        System.out.println("ClassLoadInstance类初始化时就会被执行!");    
    }    
    public ClassLoadInstance({    
      System.out.println("ClassLoadInstance构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        ClassLoadInstance instance = new ClassLoadInstance();    
    }    
}

运行结果:

结论:

new ClassLoadInstance实例时,发现ClassLoadInstance被加载了,因此 new创建实例对象,会触发类加载进行。
访问类的静态变量
demo代码:
public class ClassLoadStaticVariable {    
    static {    
        System.out.println("ClassLoadStaticVariable类初始化时就会被执行!");    
    }    
    public static int i = 100;    
    public ClassLoadStaticVariable({    
      System.out.println("ClassLoadStaticVariable构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        System.out.println(ClassLoadStaticVariable.i);    
    }    
}

运行结果:

结论:

访问类ClassLoadStaticVariable的静态变量i时,发现ClassLoadStaticVariable类被加载啦,因此访问类的静态变量会触发类加载。
注意:
访问final修饰的静态变量时,不会触发类加载,因为在编译期已经将此常量放在常量池了。


访问类的静态方法


demo代码:
public class ClassLoadStaticMethod {    
    static {    
        System.out.println("ClassLoadStaticMethod类初始化时就会被执行!");    
    }    
    public static void method(){    
        System.out.println("静态方法被调用");    
    }    
    public ClassLoadStaticMethod({    
      System.out.println("ClassLoadStaticMethod构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args{    
        ClassLoadStaticMethod.method();    
    }    
}

运行结果:

结论:

访问类ClassLoadStaticMethod的静态方法method时,发现ClassLoadStaticMethod类被加载啦,因此访问类的静态方法会触发类加载。


反射


demo代码:
package classload;    
public class ClassLoadStaticReflect {    
    static {    
        System.out.println("ClassLoadStaticReflect类初始化时就会被执行!");    
    }    
    public static void method(){    
        System.out.println("静态方法被调用");    
    }    
    public ClassLoadStaticReflect({    
      System.out.println("ClassLoadStaticReflect构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args) throws ClassNotFoundException {    
        Class.forName("classload.ClassLoadStaticReflect");    
    }    
}

运行结果:

结论:

反射得到类ClassLoadStaticReflect时,发现ClassLoadStaticReflect类被加载啦,因此反射会触发类加载。


当初始化一个类时,发现其父类还未初始化,则先触发父类的初始化


demo代码:
//父类    
public class ClassLoadSuper {    
    static {    
        System.out.println("ClassLoadSuper类初始化时就会被执行!这是父类");    
    }    
    public static int superNum = 100;    
    public ClassLoadSuper({    
        System.out.println("父类ClassLoadSuper构造函数!");    
    }    
}    
//子类    
public class ClassLoadSub extends ClassLoadSuper {    
    static {    
        System.out.println("ClassLoadSub类初始化时就会被执行!这是子类");    
    }    
    public static int subNum = 100;    
    public ClassLoadSub({    
        System.out.println("子类ClassLoadSub构造函数!");    
    }    
}    
public class ClassLoadTest {    
    public static void main(String[] args) throws ClassNotFoundException {    
        ClassLoadSub classLoadSub = new ClassLoadSub();    
    }    
}

运行结果:

看了运行结果,是不是发现,网上那道经典面试题(讲讲类的实例化顺序?)也很清晰啦。先父类静态变量/静态代码块-> 再子类静态变量/静态代码块->父类构造器->子类构造器

结论:
实例化子类ClassLoadSub的时候,发现父类ClassLoadSuper先被加载,因此当初始化一个类时,发现其父类还未初始化,则先触发父类的初始化


虚拟机启动时,定义了main()方法的那个类先初始化


demo代码:
package classload;    
public class ClassLoadTest {    
    public static void main(String[] args)  {    
       System.out.println(ClassLoadSub.subNum);    
    }    
}

运行结果:

结论:

虚拟机启动时,即使有ClassLoadSub,ClassLoadSuper,ClassLoadTest等类被加载, 但ClassLoadTest最先被加载,即定义了main()方法的那个类会先触发类加载。


练习与小结


触发类加载的六大时机,我们都分析完啦,是不是不做个题都觉得意犹未尽呢?接下来,我们来分析类加载一道经典面试题吧。
class SingleTon {      
    private static SingleTon singleTon = new SingleTon();      
    public static int count1;      
    public static int count2 = 0;      
    private SingleTon({      
        count1++;      
        count2++;      
    }      
    public static SingleTon getInstance({      
        return singleTon;      
    }      
}      
public class ClassLoadTest {      
    public static void main(String[] args{      
        SingleTon singleTon = SingleTon.getInstance();      
        System.out.println("count1=" + singleTon.count1);      
        System.out.println("count2=" + singleTon.count2);      
    }      
}  
运行结果:

分析:

SingleTon.getInstance(),调用静态方法,触发SingleTon类加载。
SingleTon类加载初始化,按顺序初始化静态变量。
先执行private static SingleTon singleTon = new SingleTon(); ,调用构造器后,count1,count2均为1;
按顺序执 行 public static int count1; 没有赋值,所以count1依旧为1;
按顺序执行 public static int count2 = 0;所以 count2变为0.
版权声明:本文为CSDN博主「 weiwenhou 的原创文章。
扫描下方二维码,查看博主精彩分享!
想学习物联网不知道从哪开始学?敲门砖的物联网接入技术或是其一。本次公开课邀请到拥有13年从业经验的翰云科技研发总监段奇,深入剖析物联网接入技术,物联网平台架构设计以及实践, 立即扫码报名!
 热 文 推 荐 
不服!身边程序员同事竟说自己敲代码速度快!Ctrl+C、Ctrl+V ?
网红“AI大佬”被爆论文剽窃,Jeff Dean都看不下去了
德国 IT 薪酬大揭秘!

【只有光头才能变强,文末有xx】分享一波Lambda表达式

如何解决多机房、多网络下的物联网部署方案?

从4个维度深度剖析闪电网络现状,在CKB上实现闪电网络的理由 | 博文精选

太鸡冻了!我用Python偷偷查到暗恋女生的名字

一文了解超级账本DLT、库、开发工具有哪些, Hyperledger家族成员你认识几个?

为什么北京西二旗的程序员从不点外卖?
点击阅读原文,精彩继续。
  
  
    
你点的每个“在看”,我都认真当成了喜欢
登录查看更多
0

相关内容

【干货书】流畅Python,766页pdf,中英文版
专知会员服务
226+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
70+阅读 · 2020年1月17日
【模型泛化教程】标签平滑与Keras, TensorFlow,和深度学习
专知会员服务
21+阅读 · 2019年12月31日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
88+阅读 · 2019年11月25日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
23+阅读 · 2019年11月7日
用 Python 开发 Excel 宏脚本的神器
私募工场
26+阅读 · 2019年9月8日
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
已删除
创业邦杂志
5+阅读 · 2019年3月27日
C# 10分钟完成百度人脸识别
DotNet
3+阅读 · 2019年2月17日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
DiscuzX 3.4 Phar反序列化漏洞
黑客工具箱
8+阅读 · 2019年1月4日
逆向 | C++ 加壳程序的编写思路
计算机与网络安全
9+阅读 · 2019年1月1日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
Github 项目推荐 | 用 PyTorch 0.4 实现的 YoloV3
AI研习社
9+阅读 · 2018年8月11日
消息队列技术点梳理(思维导图版)
架构文摘
3+阅读 · 2018年4月3日
Arxiv
92+阅读 · 2020年2月28日
Joint Monocular 3D Vehicle Detection and Tracking
Arxiv
8+阅读 · 2018年12月2日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
6+阅读 · 2018年2月7日
VIP会员
相关VIP内容
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
226+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
70+阅读 · 2020年1月17日
【模型泛化教程】标签平滑与Keras, TensorFlow,和深度学习
专知会员服务
21+阅读 · 2019年12月31日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
88+阅读 · 2019年11月25日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
23+阅读 · 2019年11月7日
相关资讯
用 Python 开发 Excel 宏脚本的神器
私募工场
26+阅读 · 2019年9月8日
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
已删除
创业邦杂志
5+阅读 · 2019年3月27日
C# 10分钟完成百度人脸识别
DotNet
3+阅读 · 2019年2月17日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
DiscuzX 3.4 Phar反序列化漏洞
黑客工具箱
8+阅读 · 2019年1月4日
逆向 | C++ 加壳程序的编写思路
计算机与网络安全
9+阅读 · 2019年1月1日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
Github 项目推荐 | 用 PyTorch 0.4 实现的 YoloV3
AI研习社
9+阅读 · 2018年8月11日
消息队列技术点梳理(思维导图版)
架构文摘
3+阅读 · 2018年4月3日
Top
微信扫码咨询专知VIP会员