利用反射模拟Tomcat类加载器的toString方法
一直认为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
利用反射模拟Tomcat类加载器的toString方法相关推荐
- Tomcat类加载器机制
Tomcat为什么需要定制自己的ClassLoader: 1.定制特定的规则:隔离webapp,安全考虑,reload热插拔 2.缓存类 3.事先加载 要说Tomcat的Classloader机制,我 ...
- JVM类加载理解(线程上下文类加载器、Tomcat类加载器)
类加载机制概念 Java虚拟机把描述类的class文件加载到内存,对其进行校验.转换解析.初始化等操作,最终得到可以被虚拟机直接使用的java类型,这就是虚拟机的加载机制. 主要有五个步骤: 加载 将 ...
- Tomcat类加载器为何违背双亲委派模型
本文来说下Tomcat类加载器为何违背双亲委派模型 文章目录 什么是类加载机制 什么是双亲委派模型 如何破坏双亲委任模型 Tomcat的类加载器是怎么设计的 本文小结 什么是类加载机制 代码编译的结果 ...
- 接口多个实现类加载哪个_深入理解JVM虚拟机7:JNDI,OSGI,Tomcat类加载器实现
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...
- python post请求 上传图片_利用python模拟实现POST请求提交图片的方法
本文主要给大家介绍的是关于利用python模拟实现POST请求提交图片的方法,分享出来供大家参考学习,下面来一看看详细的介绍: 使用requests来模拟HTTP请求本来是一件非常轻松的事情,比如上传 ...
- python paste_利用Python模拟登录pastebin.com的实现方法
任务 在https://pastebin.com网站注册一个账号,利用python实现用户的自动登录和创建paste.该任务需要分成如下两步利用python实现: 1.账号的自动登录 2.paste的 ...
- 类加载机制:双亲委任模型和tomcat类加载器
简介 类是如何加载的,那么必须要面对的几个问题如下 什么是类加载机制? 什么是双亲委任模型? 如何破坏双亲委任模型? Tomcat 的类加载器是怎么设计的? 类加载机制 Java 中的类加载器大致可以 ...
- Tomcat源码解析六:Tomcat类加载器机制
要说Tomcat的Classloader机制,我们还得从Bootstrap开始.在BootStrap初始化的时候,调用了org.apache.catalina.startup.Bootstrap#in ...
- Javascript 的函数式对象(三)利用闭包模拟类的静态变量和方法
除了模拟类的私有变量和私有方法.闭包还可用来模拟类的静态变量和方法. 除了再次利用js的闭包特性,还需要借助js语法上的一些特点. 执行上述代码后,浏览器控制台将会输出如下字符串: Created 1 ...
最新文章
- IP 网络性能的度量标准
- python快速入门答案-Python 快速入门笔记(1):简介
- 软件工程方法论为我们经软件开发有多大用处?谈谈你的看法。
- LInux之建立文件和目录
- 软考系统架构师笔记-最后知识点总结(一)
- 【英语学习】【WOTD】liaison 释义/词源/示例
- Checkbox与RadioGroup的使用方法
- ICC_lab总结——ICC_lab3:布局
- 2013年最新黑马程序员全套视频-.net视频40G免费下
- 条码检测系统——基于MATLAB的一维条码识别
- 简洁UI好玩的文字转换emoji表情微信小程序源码下载支持句子词语转换
- 笔记本(无线网卡)配置虚拟机上网
- 沧海云帆服务器哪里的,11月沧海云帆大区天涯合璧-数据互通(合服)服务器维护公告(已完成)...
- 2022 Medtec中国展参观渠道开放,800+参展企业将助力稳定供应链
- 树莓派控制4路5v继电器开关
- 微型计算机原理中BX是什么,微型计算机原理第7章答案
- HDU 2448 Mining Station on the Sea 最短路+KM
- 各类3D建模格式转换gltf格式【来源一个建模APP客户问题解决】
- 2019软件测试自学必看
- Linux傲腾DC128G内存设置,Intel发布傲腾DC非易失性内存:3DXpoint、128GB起、服务器专用...