如何在WebSphere Liberty、Tomcat 8及Java代码中查看类加载路径
问题:定位WebSphere Liberty与Tomcat中自研类和第三方类的加载来源
我想查看自研类与第三方类在WebSphere Liberty和Apache Tomcat中的加载来源。使用-verbose:class参数时,只看到大量Liberty相关路径,找不到目标第三方类的路径。比如想定位org/apache/log4j/Logger.class的位置,试过Reflections库,不确定是否适用;也试过通过ClassLoader获取资源的方法(代码如下),但没找到目标内容——编译时类是存在的,却没法通过这种方式找到第三方类路径。
尝试的代码
final ClassLoader loader = ServletVers2.class.getClassLoader(); System.out.println(loader.getResource("com/ca/services/servlet/ServletVers2.class")); System.out.println(loader.getResource("com/ca/apps/shared/utils/BuildVersion.class")); final ClassLoader classloader2 = ClassLoader.getSystemClassLoader(); final ClassLoader classloader3 = ClassLoader.getSystemClassLoader().getParent(); System.out.println(loader.getResource("org/apache/logging/log4j/LogManager.class")); System.out.println(loader.getResource("org/apache/log4j/Logger.class")); System.out.println(classloader2.getResource("org/apache/logging/log4j/LogManager.class")); System.out.println(classloader2.getResource("org/apache/log4j/Logger.class")); System.out.println(classloader3.getResource("org/apache/logging/log4j/LogManager.class")); System.out.println(classloader3.getResource("org/apache/log4j/Logger.class")); Reflections reflections = new Reflections("com.apps.shared.utils.BuildVersion", new SubTypesScanner(false));
解决方法
1. 正确使用-verbose:class参数
- WebSphere Liberty:在
server.xml中添加<jvmOptions>-verbose:class</jvmOptions>,启动服务器后,查看日志并过滤目标类,比如用grep "org.apache.log4j.Logger"(Linux)或findstr "org.apache.log4j.Logger"(Windows)快速定位。 - Tomcat:修改
catalina.sh(Linux)或catalina.bat(Windows),添加JAVA_OPTS="-verbose:class $JAVA_OPTS",启动后查看控制台或catalina.out日志,同样过滤目标类即可找到加载路径。
2. 优化ClassLoader获取类路径的代码
直接通过加载类后获取其代码源位置,比getResource更可靠:
// 获取Log4j Logger类的加载路径示例 try { Class<?> loggerClass = Class.forName("org.apache.log4j.Logger"); URL codeLocation = loggerClass.getProtectionDomain().getCodeSource().getLocation(); System.out.println("Logger类加载路径: " + codeLocation); } catch (ClassNotFoundException e) { e.printStackTrace(); }
注意:如果类由Bootstrap ClassLoader加载(如JDK核心类),getCodeSource()可能返回null,属于正常情况。
3. Reflections库的正确用法
Reflections适合扫描类资源,调整扫描规则后可以定位类路径:
// 扫描org.apache.log4j包下的所有class文件并输出路径 Reflections reflections = new Reflections("org.apache.log4j", new ResourcesScanner()); Set<String> classResources = reflections.getResources(Pattern.compile(".*\\.class")); for (String resPath : classResources) { URL resourceUrl = reflections.getResource(resPath); System.out.println(resPath + " 所在路径: " + resourceUrl); }
4. 容器专属工具
- WebSphere Liberty:使用
wsadmin工具执行dumpClassLoading命令,生成类加载详细报告,报告中会包含所有类的来源信息。 - Tomcat:在
conf/logging.properties中添加org.apache.catalina.loader.level = FINE,启用类加载日志,启动后查看日志即可获取类加载的详细路径。
内容的提问来源于stack exchange,提问作者Berlin Brown
相关产品推荐
相关产品推荐

