往期推荐
2000字带你学习JVM类加载的第一个步骤(Loading字节码)
4分钟带你看懂JVM类加载的第二个过程之linking(链接阶段)
子类加载前先加载父类? 在加载一个类之前,虚拟机总是会试图加载该类的父类,因此父类的
口诀:由父及子,静态先行。
哪些类不会生成
Java编译器并不会为所有的类都产生
哪些类在编译为字节码后,字节码文件中将不会包含
-
一个类中并没有声明任何的类变量,也没有静态代码块时
-
一个类中声明类变量,但是没有明确使用类变量的初始化语句以及静态代码块来执行初始化操作时
-
一个类中包含static final修饰的基本数据类型的字段,这些类字段初始化语句采用编译时常量表达式
对于
虚拟机会保证一个类的
正是因为函数
如果之前的线程成功加载了类,则等在队列中的线程就没有机会再执行
Java程序对类的使用分为两种:主动使用 和 被动使用。
主动使用的情况:主动使用的说明:
Class只有在必须要首次使用的时候才会被装载,Java虚拟机不会无条件地装载Class类型。Java虚拟机规定,一个类或接口在初次使用前,必须要进行初始化。这里指的“使用”,是指主动使用。
主动使用只有下列几种情况:(即:如果出现如下的情况,则会对类进行初始化操作。而初始化操作之前的加载、验证、准备已经完成。)
1. 当创建一个类的实例时,比如使用new关键字,或者通过反射、克隆、反序列化。
2. 当调用类的静态方法时,即当使用了字节码invokestatic指令。
3. 当使用类、接口的静态字段时(final修饰特殊考虑),比如,使用getstatic或者putstatic指令。
4. 当使用java.lang.reflect包中的方法反射类的方法时。比如:Class.forName("com.atguigu.java.Test")
5. 当初始化子类时,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
6. 如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,该接口要在其之前被初始化。
7. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
8. 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。(涉及解析REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄对应的类)
被动使用的情况被动使用的情况
除了以上的情况属于主动使用,其他的情况均属于被动使用。被动使用不会引起类的初始化。
也就是说:并不是在代码中出现的类,就一定会被加载或者初始化。如果不符合主动使用的条件,类就不会初始化。
1. 当访问一个静态字段时,只有真正声明这个字段的类才会被初始化。
当通过子类引用父类的静态变量,不会导致子类初始化
2. 通过数组定义类引用,不会触发此类的初始化
3. 引用常量不会触发此类或接口的初始化。因为常量在链接阶段就已经被显式赋值了。
4. 调用ClassLoader类的loadClass()方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
> 被动的使用,意味着不需要执行初始化环节,意味着没有
如果针对代码,设置参数-XX:+TraceClassLoading,可以追踪类的加载信息并打印出来。本章面试题
-
类加载的时机 (百度)
-
Class的forName("Java.lang.String")和Class的getClassLoader()的loadClass("Java.lang.String")有什么区别? (百度)
-
哪些情况会触发类的加载?(京东)
-
类的加载 = 装载+链接(①②③)+初始化
关注公众号可免费加入大数据学习社群,2021版大数据高薪就业宝典(LeetCode数据库相关题库+大厂大数据面试题108套),还有 大数据笔面试套装(大量面试题+面试技巧+大数据简历模板),还有博主总结的大数据面试宝典脑图合集,涉及14个组件。关注公众号获取哦~
获取方式:关注公众号:大数据面试宝典,回复:666,就可以获得这份超级大礼!



