近来在学习Spring AOP时,提到了动态代理,而后学习了常用的JDK、CGLIB动态代理,其中源码多次提到classLoader,所以bz专门去网上寻找了很多博文,但是都参差不齐,以下是我找到的一篇通俗易懂的博文
转载自:http://blog.itpub.net/31561269/viewspace-2222522/
ClassLoader学习笔记
-
概念:Java类加载器(Java Classloader)是Java运行时环境(Java Runtime Environment)的一部分,负责动态加载Java类到Java虚拟机的内存空间中
-
作用:
- class文件都是以字节编码的方式存储在磁盘,在运行程序时,那么就需要对相应的class文件进行解码,ClassLoader就起到了解码的作用。每一个类都有一个类加载器。
class Class<T> { ... private final ClassLoader classLoader; ... }
- class文件都是以字节编码的方式存储在磁盘,在运行程序时,那么就需要对相应的class文件进行解码,ClassLoader就起到了解码的作用。每一个类都有一个类加载器。
-
运用场景:
- 延迟加载:JVM在运行的时候并不是一次加载所有的类,而是按需来进行加载,当需要调用某个类的属性或者方法时,才对相应的类进行解码,然后存放于内存之中,当再次调用这个类的方法时,就不需要再次加载这个类了。
- 注:静态方法或者属性的类加载:当调用静态方法时,首先会解码相应的class文件,但是不会加载类的实例字段(静态方法或属性可以不通过实例对象来调用),实例字段的类别需要等到你实例化对象的时候才可能会加载。
-
实例:
- Class.forName
Class.forName("com.mysql.cj.jdbc.Driver");
- 当我们在使用JDBC驱动时,经常用到forName的方法,它实际的原理就是在加载Driver类的时候,会顺便加载静态代码块,这个静态代码块会将 mysql 驱动实例注册到全局的 jdbc 驱动管理器里
class Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } ... }
- forName 方法同样也是使用调用者 Class 对象的 ClassLoader 来加载目标类。不过 forName 还提供了多参数版本,可以指定使用哪个 ClassLoader 来加载
Class<?> forName(String name, boolean initialize, ClassLoader cl)
- 通过这种形式的 forName 方法可以突破内置加载器的限制,通过使用自定类加载器允许我们自由加载其它任意来源的类库。根据 ClassLoader 的传递性,目标类库传递引用到的其它类库也将会使用自定义加载器加载。
- forName 方法同样也是使用调用者 Class 对象的 ClassLoader 来加载目标类。不过 forName 还提供了多参数版本,可以指定使用哪个 ClassLoader 来加载
- Class.forName