这是调用代码 URLClassLoader urlLoader = (URLClassLoader)this.getClass().getClassLoader(); URL servlet = urlLoader.findResource( "../lib/serlet-api.jar" );//这句是必须的吗? URL[] u = { urlLoader.getURLs()[0] , servlet }; URLClassLoader classLoader = new URLClassLoader( u );//没有上面那句的话,这句就会报错 Class cls = classLoader.loadClass( "com.userlibrary.Demo" ); Class[] ptypes = new Class[]{ HttpServletResponse.class , HttpServletRequest.class , cuser.class }; Method main = cls.getDeclaredMethod( "Execute" , ptypes );//现在这里就出错了 main.invoke( cls.newInstance() , new Object[]{ response , request , CurUser} )
现在我使用下面这个方法来读取类,后续语句不变,执行就没有问题. Class cls = Class.forName( "com.userlibrary.Demo" );真是百思不得其解,还望高人指点.
类似的怪问题,我也碰到过,至今不得其解曾经用过一个XML的DB, sonic eXtensive Information Server, 里面用到的一个class,和xerces里面的class重名,但属于不同package, 结果在指定classpath的时候,尽然哪个lib放前面,就去找哪个class,结果导致老是NoSuchMethod
另外,我在被调用类中import了javax.servlet.http.*,结果在初始化URLClassLoader时,一定要将servlet-api.jar也加入到URL路径中去,否则在classLoader时会报错,这难道是必须的吗?
我的运行环境是Tomcat5.0.16,jdk1.4.2
package com.userlibrary;
import javax.servlet.http.*;
import com.user.*;
public class Demo
{
public Demo()
{
}
public Boolean Execute( HttpServletResponse response , HttpServletRequest request , cuser CurUser )
{
try
{
System.out.print( request.getParameter( "username" ) );
System.out.print( CurUser.CurrentUserName );
}
catch( Exception e )
{
return Boolean.FALSE;
}
return Boolean.TRUE;
}
}
URLClassLoader urlLoader = (URLClassLoader)this.getClass().getClassLoader();
URL servlet = urlLoader.findResource( "../lib/serlet-api.jar" );//这句是必须的吗?
URL[] u = { urlLoader.getURLs()[0] , servlet };
URLClassLoader classLoader = new URLClassLoader( u );//没有上面那句的话,这句就会报错
Class cls = classLoader.loadClass( "com.userlibrary.Demo" );
Class[] ptypes = new Class[]{ HttpServletResponse.class , HttpServletRequest.class , cuser.class };
Method main = cls.getDeclaredMethod( "Execute" , ptypes );//现在这里就出错了
main.invoke( cls.newInstance() , new Object[]{ response , request , CurUser} )
Class cls = Class.forName( "com.userlibrary.Demo" );真是百思不得其解,还望高人指点.
URL url = new URL("../lib/serlet-api.jar");
URL[] urls = new URL[]{url};
URLClassLoader classLoader = new URLClassLoader(urls,this.getClass().getClassLoader());
Class cls = classLoader.loadClass( "com.userlibrary.Demo" );
主要就是URLClassLoader classLoader = new URLClassLoader( urls , this.getClass().getClassLoader() );这句的问题.我原先没有加this.getClass().getClassLoader()这个参数,所以执行不了.加了这个参数后,不但执行可以了.URL servlet = urlLoader.findResource( "../lib/serlet-api.jar" );这句也就不用加了.
那能不能解释一下,加这个参数的作用是什么?(我的理解是把urls里要加载的类装载到this.getClass().getClassLoader()的执行环境中,使它们在同一环境中运行.)
还希望能说明一下,Class.forName()也可以达到同样的效果,那这两种方法有什么区别,谁更好些(从代码上看Class.forName()方法要简洁些).
URL servlet = urlLoader.findResource( "../lib/serlet-api.jar" );
得出得URL应该是空的吧.
如果要ucl包括指定的资源,需要在创建它的时候就指定,所以开始就创建一个URL作为构造函数的参数给它,是定位资源包的唯一手段.
还有一个可能,就是每个类载入器一般都有一个父载入器,而他可能会从父载入器继承一些特性,这个我就没有试了,你可以试一下看把ucl构造函数中的this.getClass().getClassLoader()参数去掉,看行不行?
以上是我的理解,不知对不对,大家给些意见