【问题标题】:How to find which jars and in what order are loaded by a classloader?如何查找类加载器加载哪些 jar 以及以什么顺序加载?
【发布时间】:2011-01-11 21:34:44
【问题描述】:

我在其他地方找不到这个问题的明确答案,所以我会在这里尝试:

是否有某种方式(编程方式或其他方式)来获取应用程序类加载器按照加载的精确顺序加载的 JAR/类列表? 应用程序类加载器是指在应用服务器(WLS、WAS、JBoss...)中加载 EAR 应用程序的类加载器,但显然,它适用于任何类加载器。

所以,概括地说,我想找出由指定类加载器加载的 JAR 的列表和顺序。不是单个类,通过调用 classloader.getPackages() 很容易找到,而是由这个类加载器加载的 JAR 文件列表。

【问题讨论】:

    标签: java jar classloader


    【解决方案1】:

    您是否尝试过使用 JVM 选项 -verbose:class。它显示所有加载的 JAR 文件和类。

    例子:

    [Opened C:\Program Files\JDK160~1\jre\lib\rt.jar]
    [Loaded java.lang.Object from C:\Program Files\JDK160~1\jre\lib\rt.jar]
    

    【讨论】:

    • 谢谢,史蒂夫 - 是的,我尝试了该选项,如果您只是想知道哪个类加载器以及从哪个 .jar 加载特定类,它就可以正常工作。但是,输出变得过于庞大,因为我们的应用程序有数千个类 :)。我使用了类似于 kdgregory 建议的方法 - 见下文。
    【解决方案2】:

    简短的回答是否定的。类加载器不需要公开它们的搜索逻辑。

    但是,如果您的类加载器实例恰好是 URLClassLoader 或子类,那么您确实可以通过 getURLs() 方法访问 jars/目录列表。根据此类的文档,将按顺序搜索这些 URL。

    在实践中,如果您试图找出从何处加载某个类,Steve 的答案可能更有用。

    【讨论】:

    • 谢谢,kdgregory。这是我最终使用的方法 - 基本上我编写了一个实用程序,它在运行时计算出类加载器层次结构,并使用 getURLs() 方法查询每个类加载器已加载的资源列表(如果可用)。它适用于 WLS 和 WAS。在 WLS 的情况下,它们自己的类加载器不扩展 URLClassloader,但它们确实有一个不同的方法 getClassPath(),它返回一个有序的类路径条目列表。并且所有 WAS 类加载器似乎都扩展了 URLClassloader,因此 getURLs() 工作正常。还没有在 JBoss 上尝试过。码头
    【解决方案3】:

    通过类的保护域(位置/证书组合)。例如对于 PDFParser.class 你得到它是这样的......

    PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString()
    

    如果它是从 jre 类或认可的目录加载的,它将抛出异常,因为这些类加载时没有保护...

    【讨论】:

      【解决方案4】:

      作为替代方法,您可以使用此代码 sn-p。结果是一个文件,其中包含与类加载器相关的 jar 文件和由对象的类加载器加载的类文件(类加载器链,包括其父类,直到根类加载器)。类加载器由星号分隔。

      Object obj = this;
      ClassLoader classLoader = obj.getClass().getClassLoader();
      File file = new File("classlodersClassesJars.txt");
      if(file.exists()) {
          file.delete();
      }
      if(classLoader != null) { // to escape from system classes that are loaded by bootstrap class-loader such as String.
          do {
              try {
                  Class clClass = classLoader.getClass();
                  while(clClass != ClassLoader.class){
                          clClass = clClass.getSuperclass();
                  }
                  java.lang.reflect.Field domainField = clClass.getDeclaredField("domains");
                  java.lang.reflect.Field classesField = clClass.getDeclaredField("classes");
                  domainField.setAccessible(true);
                  classesField.setAccessible(true);
                  HashSet domains = (HashSet<String>) domainField.get(classLoader);
                  Vector classes = (Vector) classesField.get(classLoader);
                  FileOutputStream fos = new FileOutputStream("classlodersClassesJars.txt", true);
                  fos.write(("\n******************** " + classLoader.toString() + "\n").getBytes());
                  fos.write(Arrays.toString(classes.toArray()).getBytes());
                  Object[] reverseDomains = domains.toArray();
                  org.apache.commons.lang.ArrayUtils.reverse(reverseDomains);
                  fos.write(Arrays.toString(reverseDomains).getBytes());
                  fos.close();
                  classLoader = classLoader.getParent();
              } catch (Exception exception) {
                  exception.printStackTrace();
                  // TODO
              }
          } while (classLoader.getParent() != null);
      }
      

      【讨论】:

        猜你喜欢
        • 2018-06-28
        • 2010-10-31
        • 2020-06-02
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        相关资源
        最近更新 更多