加载过程
- 装载load
- 链接link
- 验证
- 确保被加载类的正确性和合法性,防止高手伪造恶意的非法class文件
- 准备
- 解析
- 初始化initialize
初始化
- 引起类初始化情况
- 称为主动引用,被动引用不会引发初始化
- new一个对象,new字节码指令
- 访问类或接口的静态变量,或对类静态变量赋值,getstatic,putstatic(final修饰,编译期已进入常量池的除外)
- 调用类的静态方法,invokestatic
- 反射调用,如Class.forName("类全限定名")
- 初始化子类前,会先初始化父类
- JVM启动时标明的启动类
- 初始化步骤
- 若未装载和链接,则先装载和链接
- 假设存在直接父类且直接父类还未初始化,则初始化直接父类(接口呢???)
- 依次执行初始化语句(static变量和static语句块)
说明
- 类加载的最终产物是位于堆区(还是方法区???)中的Class对象,Class对象封装了类在方法区内的数据结构,向程序员提供了访问方法区内数据结构的接口
- 加载源
- 本地文件系统
- 通过网络下载class文件
- 从zip和jar等归档文件中加载
- 专有数据库中提取
- 动态编译java源文件
类加载器
- 架构
- Bootstrap ClassLoader
- JRE/lib/rt.jar
- -Xbootclasspath指定的jar包
- C++写的
- Extention ClassLoader
- JRE/lib/ext/*.jar
- -Djava.ext.dirs指定目录下的jar包
- App ClassLoader(System ClassLoader)
- classpath
- -Djava.class.path所指定目录下的类和jar包
- Custom ClassLoader(User Defined Classloaders)
- 继承java.lang.ClassLoader,自定义类加载器
- 双亲委派
Faster Class Loading
- A feature called Class Data Sharing (CDS) was introduce in HotSpot JMV from version 5.0. During the installation process of the JVM the installer loads a set of key JVM classes, such as rt.jar, into a memory-mapped shared archive. CDS reduces the time it takes to load these classes improving JVM start-up speed and allows these classes to be shared between different instances of the JVM reducing the memory footprint.
Classloader Reference
- All classes that are loaded contain a reference to the classloader that loaded them. In turn the classloader also contains a reference to all classes that it has loaded.
相关源码
# Class
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement
@CallerSensitive
public static Class<?> forName(String className) throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
# ClassLoader
public abstract class ClassLoader
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
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) {
// ClassNotFoundException thrown if class not found from the non-null parent class loader
// 这里可以看到,异常其实被忽略了,接着往下尝试
}
if (c == null) {
// If still not found, then invoke findClass in order to find the class.
long t1 = System.nanoTime();
c = findClass(name);//这个方法在ClassLoader里没有实现,而是简单的抛出异常,可以看下javassist.Loader中的实现)
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
网友评论