分析Java的类加载器与ClassLoader(一):概述
来源:互联网 发布:2017云计算大会 ppt 编辑:程序博客网 时间:2024/06/05 19:56
有关类加载器的基本知识,请先看文章:http://blog.csdn.net/tangyangguang/article/details/8878302
1,类加载器概述
Java程序是由许多独立的类字节码文件(*.class)组成。一个应用程序可能直接或间接的涉及到成千上万个Class,如果一次性全部装入内存,无疑是时间和空间的浪费。所以JVM启动时只会加载核心的类字节码和必要的其他类字节码,用户自定义的类将会在第一次使用时加载,这叫做动态加载类字节码。而类加载器就是用来加载类字节码文件到JVM中,以供程序使用的。
2,JVM中的自带的类加载器
- Bootstrap ClassLoader
- 启动类加载器,用c/c++实现的,它负责加载核心Class(即所有java.*开头的类)。
- 这个类加载器没有对应的Java类。
- Extension ClassLoader
- 扩展类加载器,它负责加载扩展的Class(存放在JRE的lib/ext/目录下的类)。
- 这个类加载器对应sun.misc.Launcher$AppClassLoader类。
- Application ClassLoader
- 应用程序类加载器,负责加载应用程序自身的类(CLASSPATH目录中的Class)。
- 这个类加载器对应sun.misc.Launcher$ExtClassLoader类。
Bootstrap ClassLoader是最顶级的类加载器,也是Extension ClassLoader的父“类加载器”,Extension ClassLoader是Application ClassLoader的父“类加载器”。如下图所示:
测试代码:
package cn.itcast;public class ClassLoaderTest {public static void main(String[] args) {ClassLoader cl = Thread.currentThread().getContextClassLoader();System.out.println("当前的类加载器:" + cl);while(cl != null){cl = cl.getParent();System.out.println("parent类加载器:" + cl);}}}
执行结果:
当前的类加载器:sun.misc.Launcher$AppClassLoader@19821fparent类加载器:sun.misc.Launcher$ExtClassLoader@addbf1parent类加载器:nul
3,“ClassLoader”与“类加载器”的区别
我们平常说的ClassLoader实际上表示两个概念:一是“类加载器”概念;二是ClassLoader类,全名是java.lang.ClassLoader。java.lang.ClassLoader是JDK中的一个普通类(ClassLoader是一个抽象类),是用Java语言编写的,我们可以自己写一个ClassLoader的子类,以扩展Java虚拟机加载类的方式。
4,类加载器使用委托模式进行类加载
类加载器使用委托模型来搜索类和资源。每个“类加载器”实例都有一个相关的父“类加载器”(parent)。需要查找类或资源时,类加载器实例会先委托给其父类加载器进行加载,如果parent是null的话,则表示为Bootstrap类加载器,只有在上级类加载器没有找到的情况下,自己才会加载,这就避免我们重写一些系统类,来破坏系统的安全。
分析java.lang.ClassLoader的源码:
protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {// 先从缓存中拿Class:// 1, 如果这个Class之前被加载过,就会记录到缓存中,这里就会返回缓存的Class对象。// 2, 如果这个Class之前没有被加载过,则这里返回nullClass c = findLoadedClass(name);if (c == null) {// 如果缓存中没有想要的Class对象,则进行加载try {// 如果parent不为null,则调用parent的loadClass进行加载if (parent != null) {c = parent.loadClass(name, false);}// 如果parent为null,则调用BootstrapClassLoader进行加载else {c = findBootstrapClass0(name);}} catch (ClassNotFoundException e) {// 如果仍然无法加载成功,则调用自身的findClass进行加载c = findClass(name);}}if (resolve) {resolveClass(c);}return c;}
从以上源码中可以得知:
1,类加载器使用委托模式进行类加载。
2,我们如果想自己写一个类加载器,则只需要重载findClass()这个方法。
5,规则细节
- 类加载器使用委托模式进行类加载。
- Class.getClassLoader()方法可以返回加载这个Class的ClassLoader,如果返回null,表示是Bootstrap ClassLoader。
- 如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B。
- 我们如果想自己写一个类加载器,则只需要重载findClass()这个方法。
- 在自定义的ClassLoader对象中,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。
- 我们可以在自定义的ClassLoader中重写loadClass()方法,在实现代码中不采用委托模式进行类加载,但不推荐这样做。
- Class.forName()是加载类字节码并进行初始化(例如执行static代码块),如果之前加载过,则会使用缓存的Class。
- ClassLoader.loadClass()是加载类字节码,但不会进行初始化(例如不会执行static代码块),而是在第一次使用这个类时执行初始化。
- 如果使用同一个ClassLoader实例多次加载同一个Class(自己重写loadClass()方法可以实现这个效果),会抛java.lang.LinkageError错误。
(实验代码将写到后面的文章中)
- 分析Java的类加载器与ClassLoader(一):概述
- 类加载器ClassLoader概述
- 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码
- java 类加载器ClassLoader详解(一)——原理与模式
- java反射Reflection(一)之的类加载器ClassLoader和Class类
- ClassLoader的加载过程及分析一
- Java的类的加载器ClassLoader
- 类的加载器 java.lang.ClassLoader
- Java类加载器ClassLoader的说明
- java的类加载器ClassLoader
- Java类加载器 ClassLoader的解析
- java类的加载器ClassLoader
- java的classloader类加载器
- java 的类加载机制(classloader)
- java 类的加载(ClassLoader)机制
- ClassLoader与类的加载
- 类加载器(ClassLoader)对java安全性的支持
- Java类加载器(ClassLoader)浅析
- 不使用第三方变量 给两个变量相互交换值PHP实现
- PHP (单例模式与工厂模式)
- K-means聚类算法
- 饮食问题--01背包--动态规划
- 求topK问题
- 分析Java的类加载器与ClassLoader(一):概述
- 半夜睡不着,MFC搞起来!
- spring 事务配置例子详解
- UML类图关系大全
- git服务器搭建过程
- 高级项目管理师个人总结--项目启动
- spring 事务基础
- Ubuntu and Windows 7
- 用存储过程产生序列号,解决了匿名用户没有存储过程授权的问题