扩展类加载器-------改变JAVA的父优先类加载顺序

java的类加载机制默认情况下是采用委托模型:当加载某个类时JVM会首先尝试用当前类加载器的父类加载器加载该类,若父类加载器加载不到再由当前类加载器来加载,因此这种模型又叫做“父优先”模型。

但是在实际项目中我们可能会要求先从当前类加载加载再从父类加载器加载,如项目中的某类的版本可能和container中的不一致的时候,若还从container加载就会报jar包冲突的异常,实际上jar包冲突的问题在实际开发过程中是经常会遇到的。如我们在开发Loong时就遇到了类似问题。

解决方案是通过扩展自定义的ClassLoader,重写loadClass方法,先从当前类加载器加载再从父类加载器加载。

Java代码 

  1. public class MCFClassLoader extends URLClassLoader {

  2. public MCFClassLoader(URL[] urls) {

  3. super(urls);

  4. }
  5. public MCFClassLoader(URL[] urls, ClassLoader parent) {

  6. super(urls, parent);

  7. }
  8. public MCFClassLoader(URL[] urls, ClassLoader parent,

  9. URLStreamHandlerFactory factory) {

  10. super(urls, parent, factory);

  11. }
  12. public Class<?> loadClass(String name) throws ClassNotFoundException {

  13. Class c = findLoadedClass(name);

  14. if (c == null) {

  15. try {

  16. c = findClass(name);

  17. catch (ClassNotFoundException e) {

  18. return super.loadClass(name);

  19. }

  20. }

  21. return c;

  22. }
  23. }

[java] view plaincopy

  1. public class MCFClassLoader extends URLClassLoader {

  2. public MCFClassLoader(URL[] urls) {

  3. super(urls);

  4. }
  5. public MCFClassLoader(URL[] urls, ClassLoader parent) {

  6. super(urls, parent);

  7. }
  8. public MCFClassLoader(URL[] urls, ClassLoader parent,

  9. URLStreamHandlerFactory factory) {

  10. super(urls, parent, factory);

  11. }
  12. public Class<?> loadClass(String name) throws ClassNotFoundException {

  13. Class c = findLoadedClass(name);

  14. if (c == null) {

  15. try {

  16. c = findClass(name);

  17. } catch (ClassNotFoundException e) {

  18. return super.loadClass(name);

  19. }

  20. }

  21. return c;

  22. }
  23. }

通过上面的ClassLoader就解决了我们遇到的问题。

思考:通过扩展URLClassLoader可以实现好多有趣的功能,如支持多父、支持加载顺序配置等等。

作为补充给出一个使用上面的ClassLoader的示例代码:

Java代码 

  1. public ClassLoader getDSClassLoader(String moudleName) {

  2. if (DSClassLoader == null) {

  3. try {

  4. DSClassLoader = new MCFClassLoader(

  5. new URL[] {

  6. new URL("......xxx.jar"),

  7. new URL("......yyy.jar")},

  8. ConnectorConfigurationParserServiceImpl.class

  9. .getClassLoader());

  10. catch (MalformedURLException e) {

  11. // TODO Auto-generated catch block

  12. e.printStackTrace();

  13. }

  14. }

  15. return DSClassLoader;

  16. }

[java] view plaincopy

  1. public ClassLoader getDSClassLoader(String moudleName) {

  2. if (DSClassLoader == null) {

  3. try {

  4. DSClassLoader = new MCFClassLoader(

  5. new URL[] {

  6. new URL("......xxx.jar"),

  7. new URL("......yyy.jar")},

  8. ConnectorConfigurationParserServiceImpl.class

  9. .getClassLoader());

  10. } catch (MalformedURLException e) {

  11. // TODO Auto-generated catch block

  12. e.printStackTrace();

  13. }

  14. }

  15. return DSClassLoader;

  16. }

上面的例子说明当xxx.jar或yyy.jar中有需要加载的类时就从这些jar包里加载,即使所在的container里有同样的类,这样可在一定程度上避免jar包版本冲突的问题!

扩展类加载器-------改变JAVA的父优先类加载顺序,码迷,mamicode.com

时间: 2024-11-03 22:48:29

扩展类加载器-------改变JAVA的父优先类加载顺序的相关文章

JVM类加载器及Java类的生命周期

预定义类加载器(三种): 启动(Bootstrap)类加载器: 是用本地代码实现的类装入器,它负责将<Java_Runtime_Home>/lib下面的类库加载到内存中(比如rt.jar).由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作.扩展扩展(Extension)类加载器: 是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的.它负责将< Java_R

java自定义类加载器

前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是eclipse项目中的bin目录里),然后通过java反射机制,获取main方法并执行..class文件名称固定.当 A.class文件更新的时候,问题出现了,main方法的执行结果总和第一次的执行结果相同. 程序流程 代码提交->接收代码->编译成A.class文件->java反射->m

乐字节Java反射之三:方法、数组、类加载器和类的生命周期

本文承接上一篇:乐字节Java发射之二:实例化对象.接口与父类.修饰符和属性 继续讲述Java反射之三:方法.数组.类加载器 一.方法 获取所有方法(包括父类或接口),使用Method即可. public static void test() throws Exception { Class<?> clz = Class.forName("com.shsxt.ref.simple.User "); //获取属性 System.out.println("======

Java虚拟机JVM学习05 类加载器的父委托机制

Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器(System) 2.用户自定义的类加载器: java.lang.ClassLoader的子类,用户可以定制类的加载方式. JVM自带的加载器 Java虚拟机自带了以下几种加载器. 1.根(Bootstrap)类加载器: 该加载器没有父加载器. 它

Java基础知识之类加载器

1.类加载器定义 1.1类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制.JVM中用来完成上述功能的具体实现就是类加载器.类加载器读取.class字节码文件将其转换成java.lang.Class类的一个实例.每个实例用来表示一个java类.通过该实例的newInstance()方法可以创建出一个该类的对象. 1.2类的生命周期: 类从加载到虚拟

[读书笔记]Java类加载器

一.类与类加载器 类加载器除了在类加载阶段的作用外,还确定了对于一个类,都需要由加载它的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性.通俗一点来讲,要判断两个类是否"相等",前提是这两个类必须被同一个类加载器加载,否则这个两个类不"相等". 这里指的"相等",包括类的Class对象的equals()方法.isAssignableFrom()方法.isInstance()方法.instanceof关键字等判断出来的结果. 示例:不同的类

深入理解Java类加载器(1):Java类加载原理解析

1 基本信息 每个开发人员对Java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加载机制是技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助. 2 Java虚拟机类加载器结构简述 2.1 JVM三种预定义类型类加载器 我们首先看一下JVM预定义的三种类型类加载器

java面向对象--类加载器及反射

类加载器 jvm 和 类的关系 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程.同一个jvm的所有线程.所有变量都处于同一个进程里,都使用该jvm进程的内存区. jvm进程终止的情况: 1.程序运行到最后正常结束. 2.遇到System.exit()或Runtime.getRuntime.exit(). 3.遇到未捕获的异常或错误 4.程序所在的平台强制结束了JVM进程 jvm进程终止,jvm内存中的数据将全部丢失. 类加载 当程序主动使用某个类时,如果该类还未被加载到

Java类加载器 ClassLoader的解析

//参考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器基本概念 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的.Java Applet 需要从远程下载 Java 类文件到浏览器中并执行.现在类加载器在 Web 容器和 O