一直认为tomcat5的类加载器的toString方法很酷,为什么呢?因为它的toString方法列出了所有的父类加载器以及类加载器加载的资源(即classpath).可能有些朋友还没有注意过,如果想看看它到底有多酷的话可以随便找个jsp
<%System.out.println(com.syj.Test.class.getClassLoader());%>
WEB-INF/classes/com/syj/Test
启动tomcat访问jsp,看看控制台:
信息: Exposing service with name {http://ws.syj.com}Demo
2008-9-20 16:15:32 org.apache.coyote.http11.Http11Protocol start
信息: Starting Coyote HTTP/1.1 on http-8080
2008-9-20 16:15:33 org.apache.jk.common.ChannelSocket init
信息: JK2: ajp13 listening on /0.0.0.0:8009
2008-9-20 16:15:33 org.apache.jk.server.JkMain start
信息: Jk running ID=0 time=15/78 config=D:/SYJ.WORK/SYJ.SERVER/tomcat5/conf/jk2.properties
2008-9-20 16:15:33 org.apache.catalina.startup.Catalina start
信息: Server startup in 6907 ms
转载请注明出处http://blog.csdn.net/sunyujia/
WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
StandardClassLoader
delegate: true
repositories:
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/shared/classes/
----------> Parent Classloader:
StandardClassLoader
delegate: true
repositories:
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/classes/
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/ant-launcher.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/ant.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/commons-collections-3.1.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/commons-dbcp-1.2.1.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/commons-el.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/commons-pool-1.2.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/jasper-compiler.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/jasper-runtime.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/jsp-api.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/mssql_All.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/naming-common.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/naming-factory.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/naming-java.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/naming-resources.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/servlet-api.jar
file:D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/tools.jar
----------> Parent Classloader:
sun.misc.Launcher$AppClassLoader@18d107f
非常清晰的调试信息,classpath一目了然,在一些复杂的类加载场景非常有用,
反编译tomcat5/server/lib/catalina.jar/WebappClassLoader.class 类查看源码
- public String toString()
- {
- StringBuffer sb = new StringBuffer("WebappClassLoader/r/n");
- sb.append(" delegate: ");
- sb.append(_flddelegate);
- sb.append("/r/n");
- sb.append(" repositories:/r/n");
- if(repositories != null)
- {
- for(int i = 0; i < repositories.length; i++)
- {
- sb.append(" ");
- sb.append(repositories[i]);
- sb.append("/r/n");
- }
- }
- if(parent != null)
- {
- sb.append("----------> Parent Classloader:/r/n");
- sb.append(parent.toString());
- sb.append("/r/n");
- }
- return sb.toString();
- }
so easy,于是就想写个Util类,搞个 public static String toString(ClassLoader classLoader) 方法,说干就干,不过repositories这个属性是tomcat自己搞的,在sun提供的类加载器中,哪个属性存储了classpath呢?我可没兴趣翻阅tomcat类加载过程的源码,于是在debug下,内存里面找了一通,发现原来是存储在URLClassLoader的URLClassPath ucp属性中,虽然不是public的,但是没有关系,因为可以靠反射取得,反射可是干这个的强项,呵呵,代码不多,贴出来和大家一起分享成果.
- import java.io.File;
- import java.lang.reflect.Field;
- import java.net.URL;
- import java.net.URLClassLoader;
- import java.util.List;
- /**
- * <p>
- * Title:调试辅助类
- * </p>
- *
- * <p>
- * Description:
- * </p>
- *
- * <p>
- * Copyright: 转载请注明出处http://blog.csdn.net/sunyujia/
- * </p>
- *
- * @author 孙钰佳
- * @main sunyujia@yahoo.cn
- * @date Sep 20, 2008 3:27:23 PM
- */
- public class DebugUtil {
- /**
- *
- * Description:将类加载器转换为字符串,用于打印,调试程序使用.
- * 转载请注明出处http://blog.csdn.net/sunyujia/
- *
- * @mail sunyujia@yahoo.cn
- *
- * @since:Sep 20, 2008 3:29:59 PM
- */
- public static String toString(ClassLoader classLoader) {
- StringBuffer sb = new StringBuffer(classLoader.getClass().getName());
- sb.append("/r/n");
- try {
- Field[] fields = URLClassLoader.class.getDeclaredFields();// 取出URLClassLoader类加载器的全部属性
- for (int i = 0; i < fields.length; i++) {// 遍历属性
- Field field = fields[i];
- if (field.getName().equals("ucp")) {// 找到ucp属性Field对象
- field.setAccessible(true);// 打开访问权限
- final Object ucp = field.get(classLoader);// 取得类加载器中的ucp对象
- Field[] ucpFields = ucp.getClass().getDeclaredFields();// 取ucp对象的全部属性
- for (int k = 0; k < ucpFields.length; k++) {// 遍历ucp对象的属性
- ucpFields[k].setAccessible(true);// 打开访问权限
- if (ucpFields[k].getName().equals("path")) {// 取得ucp对象中的path属性Field对象
- List list = (List) ucpFields[k].get(ucp);// 取得ucp对象中的path对象
- sb.append(" repositories:/r/n");
- for (int j = 0; j < list.size(); j++) {
- sb.append(" ");
- sb.append(list.get(j));
- sb.append("/r/n");
- }
- }
- }
- }
- }
- if (classLoader.getParent() != null) {
- sb.append("----------> Parent Classloader:/r/n");
- sb.append(toString(classLoader.getParent()));// 递归
- sb.append("/r/n");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return sb.toString();
- }
- public static void main(String[] args) throws Exception {
- File file1 = new File(
- "D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/ant.jar");
- File file2 = new File(
- "D:/SYJ.WORK/SYJ.SERVER/tomcat5/webapps/WebServicesDemo/WEB-INF/classes");
- URLClassLoader mcl = new URLClassLoader(new URL[] {
- file1.toURI().toURL(), file2.toURI().toURL() });
- System.out.println("演示1:");
- System.out
- .println(DebugUtil.toString(DebugUtil.class.getClassLoader()));
- System.out.println("演示2:");
- Class clazz = mcl.loadClass("com.syj.Test");
- System.out.println(DebugUtil.toString(clazz.getClassLoader()));
- }
- }
程序输出结果:
演示1:
sun.misc.Launcher$AppClassLoader
repositories:
file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/MyblogTest/bin/
----------> Parent Classloader:
sun.misc.Launcher$ExtClassLoader
repositories:
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/dnsns.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/localedata.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunjce_provider.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunmscapi.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunpkcs11.jar
演示2:
java.net.URLClassLoader
repositories:
file:/D:/SYJ.WORK/SYJ.SERVER/tomcat5/common/lib/ant.jar
file:/D:/SYJ.WORK/SYJ.SERVER/tomcat5/webapps/WebServicesDemo/WEB-INF/classes/
----------> Parent Classloader:
sun.misc.Launcher$AppClassLoader
repositories:
file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/MyblogTest/bin/
----------> Parent Classloader:
sun.misc.Launcher$ExtClassLoader
repositories:
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/dnsns.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/localedata.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunjce_provider.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunmscapi.jar
file:/D:/SYJ.WORK/SYJ.ENV/jdk6.0/jre/lib/ext/sunpkcs11.jar