近期研究classloader,
有个疑问:
有人说:每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能 出现两个同名的类。 有些疑问,同名类是指的类名相同,如果包路径不同的话算不算同名类,这种类加载时会不会出现问题。
自己在自己的系统中写了一套测试内容,使用main方法执行自定义classloader加载系统所有的类,遇到2个类名相同,但是包路径不同,加载出现java.lang.LinkageError: duplicate class definition异常。
但是如果使用tomcat启动的时候这两个类却可以顺利通过加载,看了下tomcat启动的时候加载类使用的是WebappClassloader。
为什么? 大家说说呗。
问题补充:自定义的loader代码:
package cn.sforce.test.startup.classloader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import cn.sforce.test.startup.TestOut;
import cn.sforce.test.startup.TestURLStreamHandler;
import cn.sforce.test.startup.Util;
public class UnitClassLoader extends ClassLoader
{
protected static TestOut log = TestOut.getLogger( UnitClassLoader.class.getName() );
/**
* 驱动程序列表
*/
private static String driverLibList[] = null;
/**
* WEB公共库
*/
private static String freezeLibList[] = null;
/**
* 应用的类路径
*/
protected String webPath = null;
protected String webClazzPath = null;
/**
* 父装载器
*/
private ClassLoader parent = null;
// 从库中加载的类
private HashMap clazzList = new HashMap();
private HashMap fileList = new HashMap();
// 工程类装载器
private ArrayList jarLoaderList = new ArrayList();
public UnitClassLoader( ClassLoader parent, String webPath, String... projPath ) throws Exception
{
super( parent );
this.parent = parent;
this.webPath = webPath;
this.webClazzPath = webPath + "/WEB-INF/classes/";
// 加载系统JAR文件
loadAllJar();
// 初始化类装载器
URL root = System.class.getResource( "/" );
String classPath = root.getPath().replace( '\\', '/' );
if( classPath != null ){
//linkProjSource( classPath );
}
// 关联类的装载器
if( projPath != null ){
for( String path : projPath ){
//linkProjSource( path );
}
}
}
/**
* 加载系统JAR文件
* @throws Exception
*/
private void loadAllJar() throws Exception
{
String driverPath = this.getClass().getResource("/").getFile();
if( driverPath.endsWith("/bin/") ){
driverPath = driverPath.substring( 0, driverPath.length()-4 );
}
else if( driverPath.endsWith("/classes/") ){
driverPath = driverPath.substring( 0, driverPath.length()-8 );
}
driverPath += "lib/";