Java虚拟机对class文件采用的是按需加载的方式,
也就是说当需要使用该类时才会将它的class文件加载到内存生成的class对象。
而且加载某个类的class文件时,java虚拟机采用的是双亲委派模式。
即把请求交由父类处理,它是一种任务委派模式
通过查看最顶层父类ClassLoader的loaderClass方法,我们可以验证双亲委派机制。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先检查此类是否被加载过了
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 调用父类的加载器方法
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 此时是最顶级的启动类加载器
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// 抛出异常说明父类无法加载
}
if (c == null) {
//父类无法加载的时候,由子类进行加载。
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
//记录加载时间已经加载耗时
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
-
避免类的重复加载
当自己程序中定义了一个和Java.lang包同名的类,此时,由于使用的是双亲委派机制,会由启动类加载器去加载
JAVA_HOME/lib
中的类,而不是加载用户自定义的类。此时,程序可以正常编译,但是自己定义的类无法被加载运行。 -
保护程序安全,防止核心API被随意篡改