类的加载时机有哪些?
* 创建该类或子类的对象会触发类加载。 * 访问类的静态成员变量时会触发类加载。 * 调用类的静态方法时会触发类加载。 * 使用java命名执行有main方法的类,也会触发类的加载 * 使用Class类的forName方法也可以强制触发类的加载。
Class类的对象:在类加载的时候创建出来的,如果是使用反射技术,必须要先获得该Class对象。
什么是类加载器
一个负责加载类的对象。
类加载器的作用
将类的字节码文件从硬盘中加载到内存,并在内存中创建一个Class对象。 Class对象就是根据类的字节码文件创建出来的,该对象中包含了类中的所有信息:成员变量和成员方,构造方法等
类加载器的分类
引导类加载器:BootstrapClassLoader 由C/C++语言编写的一个类 负责加载Java中基础jar里面的类,比如:rt.jar
扩展类加载器:ExtClassLoader 由Java语言编写,是Java中的一个类 负责加载扩展包中的类
应用类加载器:AppClassLoader 由Java语言编写,是Java中的一个类 负责加载程序猿自己编写的类以及第三方jar中的类。 ExtClassLoader和AppClassLoader都是ClassLoader的子类
如何获得类加载器对象
通过Class对象的getClassLoader方法获得。
类加载器间的关系
应用类加载器的父加载器是:扩展类加载器(ExtClassLoader) 扩展类加载器的父加载器是:引导类加载器(BootstrapClassLoader) * 并不是子父关系,是上下级关系。
类加载器常用方法
ClassLoader getParent() 获得父加载器对象 URL getResource(String name) * 根据资源文件名获得URL对象 * 资源文件名是以 / 开头,表示从src目录下查找(本质是bin下查找) - URL:统一资源定位符 http://www.baidu.com/image/a.png - URL类常用方法 - String getPath(); 获得资源的绝对路径。 InputStream getResourceAsStream(String name) - 根据资源文件名获得与该文件关联的字节输入流 - 资源文件名是以 / 开头,表示从src目录下查找(本质是bin下查找)
示例代码
public class ClassLoaderDemo02 { public static void main(String[] args) throws Exception { // 获得学生类的Class对象 Class c = Student.class; // 根据资源文件名获得与该文件关联的字节输入流 InputStream in = c.getResourceAsStream("/a.txt"); System.out.println(in.read()); } /** * URL getResource(String name) * @throws Exception */ public static void test02() throws Exception { // 获得学生类的Class对象 Class c = Student.class; // 根据资源文件名获得URL对象 URL url = c.getResource("/a.txt"); System.out.println(url.getPath()); // 创建字节输出流 FileInputStream fis = new FileInputStream(url.getPath()); System.out.println(fis.read()); fis.close(); } /** * ClassLoader getParent() 获得父加载器对象 * @throws ClassNotFoundException */ public static void test01() throws ClassNotFoundException { // 获得学生类的Class对象 Class c = Student.class; // 获得类加载器对象 ClassLoader cl = c.getClassLoader(); // sun.misc.Launcher$AppClassLoader@4e25154f System.out.println(cl); // 获得cl的父加载器对象 ClassLoader clp = cl.getParent(); // sun.misc.Launcher$ExtClassLoader@33909752 System.out.println(clp); // 获得clp的父加载器对象 ClassLoader clpp = clp.getParent(); // null System.out.println(clpp); // 获得类加载器为null时:表示此类是引导类加载器负责加载的 System.out.println(String.class.getClassLoader()); } }
类加载器加载机制:双亲委托机制
双亲委派模型的工作流程
- 如果一个类加载器收到了类加载的请求, - 它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上, - 因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中, - 只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载, - 子加载器才会尝试自己去加载该类。