类加载
类加载针对对象
总所周知,java中数据类型分为 基本数据类型和**引用数据类型,**基本数据类型一开始就被jvm定义好了,故类
加载的类型是针对于 引用数据类型
一个类只能被加载一次吗
准确地说应该是一个类只能被同一类加载加载一次
加载过程

loading:简而言之,就是把磁盘里的字节码文件加载到内存,并在堆上生成一个Class对象(类模版对象)
Linking(验证)阶段
验证:验证加载的字节码是否合法,合理符合规范
准备:为类的静态变量分配内存,并将其赋为默认值。不包含static final修饰的基本数据类型,final类型
的在编译就分配好内存了,准备阶段就是显性赋值了
解析:把符号引用变成直接引用
ps:java虚拟机并没有规定以上三步一定要按顺序。比如在hotspot vm中,解析操作是在初始化化后
的,因为涉及到内存的分配
初始化阶段:重要工作就是执行类的初始化方法:
1.clinit<>()是由jvm来控制的,我们不能在代码中重写or调用它,本身就是字节码指令
2.它是由类的静态成员变量语句以及static代码块组成的
3.在虚拟机加载一个类之前,会先尝试加载该类的父类,因为父类的clinit<>()方法总是在子类之前被执行
也就是说父静态代码块优先于子类
4.clinit<>()是加锁的,多线程尝试去初始化同一个类的,只能有一个线程去执行初始化,其他线程都得阻
塞
5.clinit<>()采用的是懒加载思想,类or接口只有在被第一次主动使用时才会初始化
类的主动使用和被动使用?
主动使用:
1. 创建一个实例对象,如new,clone,反序列化
2. 调用类的静态方法,即执行字节码指令invokestatic
3. 当使用类,接口的静态变量(final变量另外说),即执行字节码指令getstatic,putstatic
4. 通过反射API去创建
5. 当初始化一个类时,其父类还没初始化,会先初始化其父类
6. 虚拟机启动时,main方法所在那个类也会先被初始化
7. jdk7中methodHandle第一次使用调用它的invoke时也会初始化其目标类
只有主动使用xx类,类才会被初始化,而被动使用是不会的
被动使用的情况:
1. 只有真正声明静态变量的类才会被初始化,比如子类去调用父类的静态变量,子类并不会被初始化。至于子类有没有验证,准备,则需要通过使用-XX:+TraceClassLoading来追踪类的加载信息
2. 调用类的引用常量该类并不会被初始化
3. 通过数组定义类引用,不会触发此类的初始化 即 MyClass[] arr=new MyClass[6];

什么时候加载类?
JVM规范并没有强制约束,交给虚拟机具体实现来自由把握