每当一些其它的类引用在Main类中被解析时,JVM用Main所在类的明确的加载器-应用类加载器-做为初始化加载器。在上面的列子中,为了加载javax.swing.JFrame类JVM将使用应用类加载器做为一个初始化加载器。即,JVM将用应用类应用做为初始化加载器。即。JVM将调用loadClass()方法(loadClassInternal方法)在应用类加载器中。应用类加载器委托给扩展类加载器。
扩展加载器检查这是否是一个启动类(用私有方法 - ClassLoader.findBootstrapClass),启动类加载器是否从rt.jar加载过它。
当SomeAppClass的引用类被解析时,JVM有着相同的过程-用应用类加载器做为初始化加载器。
应用加载器委托给扩展加载器,扩展加载器检查启动加载器,启动加载器找不到"SomeAppClass"类,
于是扩展加载器检查"SomeAppClass"类是否在扩展jars里,结果发现不在。
于是应用类加载器检查在应用的CLASSPATH下的.class字节,如果找到了则进行加载,如果没有找到,将会抛出NoClassDefFoundError异常。
Class是由具体的类加载器与类的完全限定类名唯一定义的。
如果具体的类加载器不同,即使.class字符是从文件系统中的相同位置进行加载的Classes也是不同的。
类加载器委托给父加载器进行加载。
加载Bar类中引用的Foo类,JVM使用Bar类的确切的类加载器做为初始化加载器。JVM会在Bar类的确切加载器上会调用loadClass()方法加载Foo类。
JVM缓存->运行时的类每次初始化加载都将被记录。JVM将会缓存用于以后的解析。即,loadClass()方法不会对于每一次引用都调用。这能确保时间的不变性-即,一个类加载器不允许加载相同类名但字节码不同的类。
他是由缓存来实现的。好的类加载器应该通过调用ClassLoader得call()方法来检查缓存。
Understanding Java class loading https://blogs.oracle.com/sundararajan/entry/understanding_java_class_loading