Java-查看JVM从哪个JAR包中加载指定类

2021-08-16 16:18:29 浏览数 (1)

  • 背景
  • 方式一
  • 方式二

背景

有的时候,我们经常会碰到java.lang.NoSuchMethodError的错误信息。 究其根源,是由于JVM的 全盘负责委托机制导致的。 关于 全盘负责委托机制 ,请查看另一篇博文 全盘负责委托机制

特别是对于一些web项目,jar包很多,如何精确的查找呢?


方式一

将下面的JSP文件,放到web容器的根路径下,启动web容器,通过 http://ip:port/projectname/srcAdd.jsp?className=XXXXXX

比如:

运行web项目,访问

代码语言:javascript复制
http://localhost:8080/hello-spring4/srcAdd.jsp?className=org.springframework.beans.factory.annotation.Autowired

srcAdd.jsp

代码语言:javascript复制
<%@page contentType="text/html; charset=GBK"%>
<%@page import="java.security.*,java.net.*,java.io.*"%>
<%!
  public static URL getClassLocation(final Class cls) {
    if (cls == null)throw new IllegalArgumentException("null input: cls");
    URL result = null;
    final String clsAsResource = cls.getName().replace('.', '/').concat(".class");
    final ProtectionDomain pd = cls.getProtectionDomain();
    // java.lang.Class contract does not specify if 'pd' can ever be null;
    // it is not the case for Sun's implementations, but guard against null
    // just in case:
    if (pd != null) {
      final CodeSource cs = pd.getCodeSource();
      // 'cs' can be null depending on the classloader behavior:
      if (cs != null) result = cs.getLocation();
      if (result != null) {
        // Convert a code source location into a full class file location
        // for some common cases:
        if ("file".equals(result.getProtocol())) {
          try {
            if (result.toExternalForm().endsWith(".jar") ||
                result.toExternalForm().endsWith(".zip"))
              result = new URL("jar:".concat(result.toExternalForm())
                               .concat("!/").concat(clsAsResource));
            else if (new File(result.getFile()).isDirectory())
              result = new URL(result, clsAsResource);
          }
          catch (MalformedURLException ignore) {}
        }
      }
    }
    if (result == null) {
      // Try to find 'cls' definition as a resource; this is not
      // document.d to be legal, but Sun's implementations seem to         //allow this:
      final ClassLoader clsLoader = cls.getClassLoader();
      result = clsLoader != null ?
          clsLoader.getResource(clsAsResource) :
          ClassLoader.getSystemResource(clsAsResource);
    }
    return result;
  }
%>
<html>
<head>
<title>srcAdd.jartitle>
head>
<body bgcolor="#ffffff">
  使用方法,className参数为类的全名,不需要.class后缀,如
  srcAdd.jsp?className=java.net.URL
<%
try
{
  String classLocation = null;
  String error = null;
  String className = request.getParameter("className");

  classLocation =  "" getClassLocation(Class.forName(className));
  if (error == null) {
    out.print("类"   className   "实例的物理文件位于:");
    out.print("");
    out.print(classLocation);
  }
  else {
    out.print("类"   className   "没有对应的物理文件。");
    out.print("错误:"   error);
  }
}catch(Exception e)
{
  out.print("异常。" e.getMessage());
}
%>
body>
html>

方式二

工具类 ClassLocationUtils.java

代码语言:javascript复制
package com.xgj.master.ioc.classloaderUtil;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;

/**
 * 

 * @ClassName: ClassLocationUtils

 * @Description: tools to find which jar does the class come from 

 * 
 */
public class ClassLocationUtils {

    /**
     * find the location of the class come from
     * @param cls
     * @return
     */
    public static String where(final Class cls) {
        if (cls == null)throw new IllegalArgumentException("null input: cls");
        URL result = null;
        final String clsAsResource = cls.getName().replace('.', '/').concat(".class");
        final ProtectionDomain pd = cls.getProtectionDomain();
        if (pd != null) {
            final CodeSource cs = pd.getCodeSource();
            if (cs != null) result = cs.getLocation();
            if (result != null) {
                if ("file".equals(result.getProtocol())) {
                    try {
                        if (result.toExternalForm().endsWith(".jar") ||
                                result.toExternalForm().endsWith(".zip"))
                            result = new URL("jar:".concat(result.toExternalForm())
                                    .concat("!/").concat(clsAsResource));
                        else if (new File(result.getFile()).isDirectory())
                            result = new URL(result, clsAsResource);
                    }
                    catch (MalformedURLException ignore) {}
                }
            }
        }
        if (result == null) {
            final ClassLoader clsLoader = cls.getClassLoader();
            result = clsLoader != null ?
                    clsLoader.getResource(clsAsResource) :
                    ClassLoader.getSystemResource(clsAsResource);
        }
        System.out.println(result.toString());
        return result.toString();
    }

}

运行查找

代码语言:javascript复制
package com.xgj.master.ioc.classloader;

import com.xgj.master.ioc.classloaderUtil.ClassLocationUtils;

public class ClassLoaderTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ClassLocationUtils.where(java.lang.Thread.class);
    }

}

运行结果:

0 人点赞