一:类的生命周期
加载-->(验证 -->准备 -->解析)
连接(以上统称为连接) -->初始化-->使用-->卸载
(1)加载,验证,准备,初始化和卸载这个五个阶段顺序是确定的。但也不是完全依次进行,应该说是互相交叉混合进行。解析阶段则不一定。
(2)类的初始化触发条件:
首次主动使用的情形:
-
创建某个类的新实例时--new、反射、克隆或反序列化;
-
调用某个类的静态方法时;
-
使用某个类或接口的静态字段或对该字段赋值时(final字段除外)
-
调用Java的某些反射方法时
-
初始化某个类的子类时
-
在虚拟机启动时某个含有main()方法的那个启动类。
除了以上几种情形以外,所有其它使用JAVA类型的方式都是被动使用的,他们不会导致类的初始化。
二:类加载器
Java虚拟机中类加载器:
Java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个类负责加载特定位置的类:
BootStrap(启动类加载器),ExtClassLoader(扩展类加载器),AppClassLoader(应用程序类加载器)
类加载器也是Java类,因为Java类的类加载器本身也是要被类加载器加载的,显然必须有第一个类加载器不是Java类,这个正是BootStrap,使用C/C++代码写的,已经封装到JVM内核中了,而ExtClassLoader和AppClassLoader是Java类。
应用程序都是三个类加载器相互配合加载的,也可以加入自己定义的类加载器。

loadClass方法的源代码:
-
public Class<?> loadClass(String name) throws ClassNotFoundException {
-
return loadClass(name, false);
-
}
再来看一下loadClass(name,false)方法的源代码:
-
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{
-
//加上锁,同步处理,因为可能是多线程在加载类
-
synchronized (getClassLoadingLock(name)) {
-
//检查,是否该类已经加载过了,如果加载过了,就不加载了
-
Class c = findLoadedClass(name);
-
if (c == null) {
-
long t0 = System.nanoTime();
-
try {
-
//如果自定义的类加载器的parent不为null,就调用parent的loadClass进行加载类
-
if (parent != null) {
-
c = parent.loadClass(name, false);
-
} else {
-
//如果自定义的类加载器的parent为null,就调用findBootstrapClass方法查找类,就是Bootstrap类加载器
-
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();
-
//如果parent加载类失败,就调用自己的findClass方法进行类加载
-
c = findClass(name);
-
-
// 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;
-
}
-
}
在loadClass代码中也可以看到类加载机制的原理,这里还有这个方法findBootstrapClassOrNull,看一下源代码:
-
private Class findBootstrapClassOrNull(String name)
-
{
-
if (!checkName(name)) return null;
-
-
return findBootstrapClass(name);
-
}
就是检查一下name是否是否正确,然后调用findBootstrapClass方法,但是findBootstrapClass方法是个native本地方法,看不到源代码了,但是可以猜测是用Bootstrap类加载器进行加载类的,这个方法我们也不能重写,因为如果重写了这个方法的话,就会破坏这种委托机制。
参考书:深入理解jvm虚拟机