对于不同级别classloader define的类的问题处理

问题

问题描述:程序代码中,执行下列语句:Object mapperObj = Class.forName(mapperClassName).newInstance();MapperInterface mapper = (MapperInterface)mapperObj; 报ClassCastException。

bug fix:  1.分别取得运行环境下mapperObj和MapperInerface.class的 classloader:   mapperObj.getClass().getClassLoader() : sun.misc.Launcher$AppClassLoader    MapperInterface.class.getClass().getClassLoader() : WebContainerClassLoader2.由jvm classload 机制可知,jvm load class 分四个层次:  第一层为bootstrapclassloader : 主要负责load rt.jar等jvm必须的jar包中的类。  第二层为extclassloader : 主要负责load 被置于java.ext.dirs属性值所指路径(默认%JAVA_HOME%/lib/ext) 中所有的class.其实现类为sun.misc.Launcher$ExtClassLoader   第三层为systemclassloader : 负责load 被置于CLASSPATH路径中的类。 其实现类一般为sun.misc.Launcher$AppClassLoader   第四层为appclassloader : 由应用程序设计者继承ClassLoader并实现完成相应user-defined ClassLoader。用于根据应用程序需要加载并不是设计时就知道的类。

详细的load策略偶就不多写了,很多文章上都有,总之两句话: 当define一个类的时候,低层classloader会向上层询问是否已经define,有则直接拿来用;当load一个类的时候,同样低层向高层询问是否能find到,能就直接拿来用。

由此可知,由于原有系统原因, mapperObj被 systemclassloader define;而这里使用的接口是被appclassloader WebContainerClassLoader define的。所以会造成 ClassCastException错误。用instanceof也可发现mapperObj 确实不是 MapperInterface的实例。

由于原系统原因,无法通过改动其他代码完成更换mapperObj classload的动作,而运行到当前代码时,mapperObj 已经被define,所以无法通过forName方法的参数更改其class loader,后面的代码就无法调用其方法。

解决方法:采用类反射,换有Object定义的属性接 mapperObj;在下面的代码中,利用mapperObj.getClass().getInterface()方法判断是否其继承了 MapperInterface。 然后用反射调用其方法。例:

mapper = Class.forName(mapperClassName).newInstance();

Class[] tmpInterface = mapper.getClass().getInterfaces();   for(int i=0 ;i<tmpInterface.length ;i++){ if(tmpInterface[i].getName().equals("MapperInterface.class.getName()"))    flag = true;}

if(flag){  Class[] tc = new Class[2] ;  tc[0] = String.class;  tc[1] = HttpServletRequest.class;  Method mapperFunc = mapper.getClass().getMethod( "mapFunction", tc );  Object res = mapperFunc.invoke( mapper, new Object[] { event.getServletClassName(),req } );}

时间: 2024-10-31 07:28:05

对于不同级别classloader define的类的问题处理的相关文章

ExtJS 4.2 教程-03:使用Ext.define自定义类

转载自起飞网,原文地址:http://www.qeefee.com/extjs-course-3-define-classes ExtJS 4.2 教程-01:Hello ExtJS ExtJS 4.2 教程-02:bootstrap.js 工作方式 ExtJS 4.2 教程-03:使用Ext.define自定义类 ExtJS 4.2 教程-04:数据模型 ExtJS 4.2 教程-05:客户端代理(proxy) ExtJS 4.2 教程-06:服务器代理(proxy) ExtJS 4.2 教程

C++中用#define访问类的私有成员

我们知道,类的私有成员在类的外部是不能被访问的. 例如有下面的这个简单的类: class ClxECS{private:int iPrivate;}; 那么下面的这个函数是不能通过编译的: void ECS_test(){ClxECS lx;lx.iPrivate = 13; cout << lx.iPrivate << endl;} 但是,我们并不是没有办法来访问类的私有成员. 其实,方法很简单,只要在类的声明前面加上如下一行代码就行了: #define private publ

如何在Java中使用ClassLoader载入类、文件和web资源等各种资源

ClassLoader主要对类的请求提供服务,当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象. ClassLoader负责载入系统的所有资源(Class,文件,图片,来自网络的字节流等),通过ClassLoader从而将资源载入JVM 中.每个class都有一个引用,指向自己的ClassLoader. 1. 获得ClassLoader的几种方法 可以通过如下3种方法得到ClassLoader : this.getClass

Java ClassLoader基础及加载不同依赖 Jar 中的公共类

本文主要介绍 ClassLoader 的基础知识,ClassLoader 如何动态加载 Jar,ClassLoader 隔离问题及如何加载不同 Jar 中的公共类. 本文工程开源地址见:Java Dynamic Load Jar@Github,Clone 以后直接以 Java Application去运行 java-dynamic-loader-host 工程即可. 其实本文只是 Android 插件化的一个引子,做过 Android 插件化的同学,可以试试对于 Android Support

struct与class关键字在定义类中的区别

struct关键字是从C语言中继承过来的,class和struct均可定义类,用它们定义类的唯一差别在于默认的成员保护级别和默认的继承保护级别(P57--第57页,2.8--章节2.8:P485,15.2.5): 默认情况下,struct的保护级别为public,而class的保护级别为private. 下面分别就这两种情况进行举例: 例1:默认的成员保护级别 [cpp] view plaincopyprint? struct S_Base {       int foo(int) { retu

Commons Logging存在的ClassLoader问题详解

在看Java Logging相关的框架.代码.资料的时候,一直有听说Commons Logging存在ClassLoader相关的问题,但是看它的实现代码(1.1.1版本),对ClassLoader做了非常详细的查找:用了Thread Context ClassLoader.System ClassLoader.以及LogFactoryImpl本身的ClassLoader,感觉上已经很全面了.上周末有幸找到一篇Ceki Gülcü写文章,详细介绍了Commons Logging中存在的Class

深入分析Java ClassLoader原理

一.什么是ClassLoader?          大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常.而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需

(一三六)基类——第十三章

OOP编程的主要目的之一是提供可以重用的代码(比如类,可以反复使用).   C++有类库.类库由类声明和实现构成.因为类组合了类数据表示和类方法,因此提供了比函数库更加完整的程序包(函数库里的函数,也可以放置在类中作为类方法). 例如,单个类就可以提供用于管理对话框的全部资源.   类库 通常是以源代码的方式提供的(传统的C函数库则是以函数库的形式,往往没有源代码).   C++提供了比修改代码更好的方式来扩展和修改类,这种方法叫做 类继承.   类继承可以从已有的类派生出新的类,而派生类继承了

我的Java开发学习之旅------&amp;gt;Java ClassLoader解析二(转)

一.什么是ClassLoader?          大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常.而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需