0
点赞
收藏
分享

微信扫一扫

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

酷子腿长一米八 2022-03-24 阅读 178



  • ​​背景​​
  • ​​方式一​​
  • ​​方式二​​


背景

有的时候,我们经常会碰到java.lang.NoSuchMethodError的错误信息。

究其根源,是由于JVM的 全盘负责委托机制导致的。

关于 全盘负责委托机制 ,请查看另一篇博文 全盘负责委托机制

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

方式一

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

比如:

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

运行web项目,访问

http://localhost:8080/hello-spring4/srcAdd.jsp?className=org.springframework.beans.factory.annotation.Autowired

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

srcAdd.jsp

<%@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.jar</title>
</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("<hr>");
out.print(classLocation);
}
else {
out.print("类" + className + "没有对应的物理文件。<br>");
out.print("错误:" + error);
}
}catch(Exception e)
{
out.print("异常。"+e.getMessage());
}
%>
</body>
</html>

方式二

工具类 ClassLocationUtils.java

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();
}

}

运行查找

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);
}

}

运行结果:

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



举报

相关推荐

0 条评论