Java类加载器学习总结

上传人:豆浆 文档编号:11121686 上传时间:2017-10-12 格式:DOC 页数:12 大小:161KB
返回 下载 相关 举报
Java类加载器学习总结_第1页
第1页 / 共12页
Java类加载器学习总结_第2页
第2页 / 共12页
Java类加载器学习总结_第3页
第3页 / 共12页
Java类加载器学习总结_第4页
第4页 / 共12页
Java类加载器学习总结_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《Java类加载器学习总结》由会员分享,可在线阅读,更多相关《Java类加载器学习总结(12页珍藏版)》请在金锄头文库上搜索。

1、加载器概念类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下: Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件) 。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。类加载器分类JDK 默认提供了如下几种 ClassLoader:1、Bootstrp Class LoaderBoot

2、strp 加载器是用 C+语言写的,它是在 Java 虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib 或者 -Xbootclasspath 参数指定的路径以及%JAVA_HOME%/jre/classes 中的类,虚拟机出于安全等因素考虑,不会加载%JAVA_HOME%/jre/lib 路径下 存在的陌生类,开发者通过将要加载的非 JDK 自身的类放置到此目录下期待启动类加载器加载是不可能的。2、ExtClassLoader Bootstrp class loader 加载 ExtClassLoader,并且将ExtClassLoader 的父加载器设置为 Boot

3、strp loader。ExtClassLoader 是用 Java 写的,具体来说就是sun.misc.Launcher$ExtClassLoader,ExtClassLoader 主要加载%JAVA_HOME%/jre/lib/ext,此路径下的所有 classes 目录以及java.ext.dirs 系统变量指定的路径中类库。3、AppClassLoader Bootstrp class loader 加载完 ExtClassLoader 后,就会加载AppClassLoader,并且将 AppClassLoader 的父加载器指定为ExtClassLoader。AppClassLoad

4、er 也是用 Java 写成的,它的实现类是sun.misc.Launcher$AppClassLoader,另外我们知道 ClassLoader 中有个 getSystemClassLoader 方法,此方法返回的正是AppclassLoader。AppClassLoader 主要负责加载 classpath 所指定的位置的类或者是 jar 文档,它也是 Java 程序默认的类加载器。综上所述,它们之间的关系可以通过下图形象的描述:双亲委托模型Java 中 ClassLoader 的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤: 当前 ClassLoader 首先从

5、自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载时可以直接返回。 当前 classLoader 的缓存中没有找到被加载的类时,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到 bootstrp ClassLoader。 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。线程上下文类加载器ContextClassLoader 是 java.lang.Thread 类的一

6、个属性,Thread类中的方法 getContextClassLoader()和setContextClassLoader(ClassLoader cl)用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl)方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器(AppClassLoader),在线程中运行的代码可以通过此类加载器来加载类和资源。双亲委托模型并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口(Service

7、Provider Interface,SPI ) ,允许第三方为这些接口提供实现。常见的 SPI 有 JDBC、JCE、 JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供,如 JAXP 的 SPI 接口定义包含在 javax.xml.parsers 包中(rt.jar) 。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI 的 Apache Xerces 所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xm

8、l.parsers.DocumentBuilderFactory 类中的 newInstance()方法用来生成一个新的 DocumentBuilderFactory 的实例。这里的实例的真正的类是继承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的实现所提供的。如在 Apache Xerces 中,实现的类是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。而问题在于,SPI 的接口是 Java 核心库的一部分,是由引导类加载器(BootstrpClassLoader)来加载的;SPI 实

9、现的 Java 类一般是由系统类加载器(APPClassLoader)来加载的。引导类加载器是无法找到 SPI 的实现类的,因为它只加载 Java 的核心库。它也不能代理给系统类加载器,因为它是系统类加载器的祖先类加载器。也就是说,类加载器的双亲委托模型无法解决这个问题。线程 ContextClassLoader 正好解决了这个问题。如果不做任何的设置,Java 应用的线程的 ContextClassLoader 默认就是系统上下文类(AppClassLoader)加载器。在 SPI 接口的代码中使用线程ContextClassLoader,就可以成功的加载到 SPI 实现的类。线程Conte

10、xtClassLoader 在很多 SPI 的实现中都会用到。以下是一个简单的 Java 应用,用于测试 ContextClassLoader。import javax.xml.parsers.DocumentBuilderFactory;public class TestClassLoader public static void main(String args) throws Exception TestClassLoader test = new TestClassLoader();test.testLoad();private void testLoad() throws Excep

11、tion / 1System.out.println(Thread.currentThread();/ Threadmain,5,main/ 2System.out.println(Thread.currentThread().getContextClassLoader();/ sun.misc.Launcher$AppClassLoader19821f/ 3DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(org.apache.xerces.jaxp.DocumentBuilderFactoryImpl,

12、null);注释/2 显示当前主线程使用的上下文类加载器是 AppClassLoader,注释/3 由 DocumentBuilderFactory 负责加载并实例化它的一个实现类,该实现类由 Apache Xerces 提供,同时在 newInstance 中传入了一个空的加载器 。public class DocumentBuilderFactorypublic static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader)try return (DocumentBuil

13、derFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false); catch (FactoryFinder.ConfigurationError e) throw new FactoryConfigurationError(e.getException(), e.getMessage(); /.DocumentBuilderFactory 中的 newInstance 方法将加载的任务交给FactoryFinder 来完成。class FactoryFinder static Object newInsta

14、nce(String className, ClassLoader cl, boolean doFallback)throws ConfigurationErrortry /使用 给定的加载器cl ,获取DocumentBuilderFactoryImpl类的Class对象,此处的cl为nullClass providerClass = getProviderClass(className, cl, doFallback);/创建 DocumentBuilderFactoryImpl的实例 Object instance = providerClass.newInstance();return

15、 instance; catch (ClassNotFoundException x) throw new ConfigurationError(Provider + className + not found, x); catch (Exception x) throw new ConfigurationError(Provider + className + could not be instantiated: + x,x); /.获取 DocumentBuilderFactoryImpl 实现类的 Class 对象在getProviderClass 方法中完成。class Factory

16、Finder static private Class getProviderClass(String className, ClassLoader cl,boolean doFallback) throws ClassNotFoundException try if (cl = null) /1cl = ss.getContextClassLoader();if (cl = null) throw new ClassNotFoundException();else /2由上下文类加载器完成实现类的加载return cl.loadClass(className);else return cl.loadClass(className); catch (ClassNo

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号