虚拟机规范中并没有强制约束何时进行加载,但是规范严格规定了只有下列六种情况必须对类进行加载:
除过主动引用外,所有引用类的方式都不会触发加载,称为被动引用。
/*
被动引用的常见例子:
*/
//通过子类引用父类的静态字段,不会导致子类的加载
System.out.println(SubClass.value);//value字段在SubClass类的父类中定义
//通过数组定义来引用类,不会触发此类的加载。该过程会对数组类进行加载,数
//组类是一个由虚拟机自动生成的、直接继承自Object的子类,其中包含了数
//组的属性和方法。
SuperClass[] sca = new SuperClass[10];
//常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量
//的类,因此不会触发定义常量的类的加载。
System.out.println(ConstClass.HELLOWORLD);
在类加载过程的加载阶段,通过类的完全限定名,获取描述类的二进制流的实现类,被称为“类的加载”。
从JVM虚拟机的角度来讲,只存在以下两种不同的类的加载器:
从Java来发人员的角度来看,类加载器可以划分的更细致一些:
Java.util.*
,java.io.*
,java.lang.*
类等常用基础都是由启动类加载器加载。启动类加载器无法被Java程序直接引用。public class classLoaderTest i
public static void main(string[] args){
//(启动类)系统类加载器:
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemclassLoader); //sun.misc.Launcher$AppclassLoader@73d16e93
//扩展类加载器:
ClassLoader extendclassLoader = systemclassLoader.getParent();
System.out.println(extendclassLoader); //sun.misc.Launcher$ExtclassLoader@15db9742
//引导类加载器:
ClassLoader bootstrapclassLoader = extendclassLoader.getParent();
System.out.println(bootstrapclassLoader); // null
//用户自定义的类默认用系统类加载器
ClassLoader classLoader = ClassLoaderTest.class.getclassLoader();system.out.println(classLoader);// sun.misc.Launcher$AppClassLoader@73d16e93
}
}