• Jar包冲突及java.lang.NoSuchMethodError异常解决方案(转载)


    问题

    在编码过程中,往往会遇到jar包冲突的问题。问题的表现特征一般都是抛出java.lang.NoSuchMethodError异常。那么,今天就聊聊怎么解决此类问题。

    分析

    此问题跟java的类加载机制有关。JVM装载类时使用“全盘负责委托机制”,此问题跟“委托机制”有关。它是指先委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。

    然而,如果在类路径下放置了多个不同版本的类包,如commons-lang 2.x.jar和commons-lang3.x.jar都位于类路径中,代码中用到了commons-lang3.x类的某个方法,而这个方法在commons-lang2.x中并不存在,JVM加载类时碰巧又从commons-lang 2.x.jar中加载类,运行时就会抛出NoSuchMethodError的错误。

    问题排查

    这种问题的排查是比较棘手的,特别是在Web应用的情况下,可作为类路径的系统目录比较多,特别在类包众多时,情况尤其复杂:你不知道JVM到底从哪个类包中加载类文件。

    下面提供一个srcAdd.jsp的程序,你把它放到Web应用的根路径下,通过如下方式即可查看JVM从哪个类包加载指定类(其中className为className参数为类的全名,不需要.class后缀,端口号为web项目的端口号,此处为80):

        http://localhost/srcAdd.jsp?className=java.net.URL 
    • 1

    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>

    原文链接:http://blog.csdn.net/wo541075754/article/details/48243403

  • 相关阅读:
    webpack指南(四)shimming
    webpack指南(三)缓存
    webpack指南(二)code spliting+懒加载
    webpack配置篇
    React组件setState
    React 生命周期
    React学习随笔
    @vue/cli 4.0+express 前后端分离实践
    @vue/cli 4.0.5 学习记录
    VMware Workstation 与 Device/Credential Guard 不兼容
  • 原文地址:https://www.cnblogs.com/CryOnMyShoulder/p/8464532.html
Copyright © 2020-2023  润新知