jvm ClassLoader学习总结1.0
什么是Java ClassLoader:
- 它是java runtime environment 的一部分,用于动态加载类到JVM。
- 通常是在使用某个类时才加载该类。
- Java 提供了ClassLoader的抽象类;HotSpot VM 中,采用双亲代理模式加载类,有Boostrap ClassLoader,ExtClassLoader和AppClassLoader三个层次(实际实现时,类加载器之间并不是Inheritance,而是Composition)。
- 当系统对类加载有特殊要求时,可以创建UserDefined类加载器(应当能够完成ClassLoader的基本功能)。常见的场景有:对Java类的字节码进行特殊的查找和处理;利用类加载器产生的隔离特性来满足特殊的需求(比如动态更新时,需要多版本共存)。
- 每一个被加载的class都保存了加载它的ClassLoader的指针。
-
ClassLoader 方法说明:
- defineClass 方法将一个字节数组转换为 Class 类的实例。这种新定义的类的实例可以使用 Class.newInstance 来创建。由于定义Java类涉及虚拟机的核心功能,从安全的角度出发,defineClass 方法被声明为final, 不能由classLoader子类来覆写。一般来说,它是由原生代码实现的。
-
protected Class<?> loadClass(String name,boolean resolve)throws ClassNotFoundException
使用指定的二进制名称来加载类。此方法的默认实现是使用双亲委派代理的模式,将按以下顺序搜索类:先调用 findLoadedClass(String) 来检查是否已经加载类,如果已经加载直接返回已加载Class对象。
在父类加载器上调用 loadClass 方法,这一步是双亲代理模式生效的地方。如果父类加载器为 null,则使用虚拟机的内置类加载器。
调用 findClass(String) 方法查找类。
如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class) 方法(请看下一篇类的解析)。鼓励用 ClassLoader 的子类重写 findClass(String),而不是使用此方法。
public Class<?> loadClass(String name) throws ClassNotFoundException 等价于 resolve = false后调用对应的protected方法
-
protected final Class<?> findLoadedClass(String name)
如果 Java 虚拟机已将此加载器记录为该类的启动加载器,则返回该类。否则,返回 null。
Returns the class with the given binary name if this loader has been recorded by the Java virtual machine as an initiating loader of a class with that binary name. Otherwise null is returned.
注意,其他类加载器加载的同名类和该类无关。 -
protected Class<?> findClass(String name) throws ClassNotFoundException
当无法使用双亲代理模式加载类时,该方法被调用,它主要封装了当前类加载器的加载逻辑。如果需要破坏双亲代理模式,则需要覆写loadClass 方法。
-
public static ClassLoadergetSystemClassLoader()
public URL getResource(String name)
public Enumeration<URL> getResources(String name) throws IOException
public InputStream getResourceAsStream(String name) 通常,资源放在class文件相同的目录下,避免使用绝对路径。getResourceAsStream 方法内部实现时,是先调用getResource方法等到URL对象,在调用该对象的openStream方法实现。
注意事项:
- 数组对应的类不是由classloader 加载或创建的,而是由Java runtime 自动创建的,对应的指令是newarray,anewarray或者multianewarray。
- 类加载器所创建对象的方法和构造方法可以引用其他类。为了确定引用的类,Java 虚拟机将调用最初创建该类的类加载器的
loadClass方法,从而保证由同一个类加载器加载。 - 判断两个类是否相等:类的对象的全名是否相等;两个类对象的定义类加载对象是否相等。
- 在传递路径的参数时,用"/"代替package名中的"."。
参考资料:
《The JavaTM Virtual Machine Specification 》Third Edition
《深入理解Java 7: 核心技术与最佳实践》 第九章:Java 类加载器
《深入理解Java虚拟机:JVM高级特性与最佳实践》第七章:虚拟机加载机制

浙公网安备 33010602011771号