【问题标题】:How do I get a list of all package names loaded by the JVM如何获取 JVM 加载的所有包名称的列表
【发布时间】:2009-06-22 11:55:17
【问题描述】:

我需要获取 JVM 加载的所有 java 包的名称。这是为了显示一个包浏览器,就像在 IDE 中找到的一样。我可以通过访问 ClassLoader 类的受保护“包”字段来获取当前类加载器及其祖先的包列表。但是我无法让其他 webapps 加载包,因为它们有自己的类加载器。我正在 Weblogic 服务器上测试这个

【问题讨论】:

  • Package.getPackages() 会更传统。

标签: java weblogic classloader


【解决方案1】:

Weblogic 安全模型的预期行为是您无法访问其他 Web 应用程序的类加载器。这不是您真正可以解决的问题 - 请参阅 this article 了解更多信息。

【讨论】:

  • 我也想知道他在做什么。也许他正试图找到一种方法来扫描其他人的网络应用程序是否存在安全漏洞?
  • 他可能正试图找出几个 web 应用程序正在使用哪些库,以便将这些库分解到共享区域中。 JMX 管理器不能找出这类信息吗?
  • 我真的不确定 - 如果他们可以,发布它,你肯定会得到我的投票。
  • 是的,我试图获取部署在服务器上的所有应用程序使用的库名称。就我而言,这个答案是正确的,因为我找不到一种方法来引用其他 webapps 的类加载器。所以我最终扫描了部署的 ear、war、jars 和扩展文件夹。请参阅下面的答案。
【解决方案2】:

您需要使用getParent() 向上遍历类加载器树,找到所有扩展 ClassLoader 的类,找到所有当前实例(调试 API 应该在这里提供帮助)。但这可能不适用于 Web 服务器,因为安全策略(不允许 Web 应用互相窥视)。

对于 Tomcat,有一个选项可以在加载所有类时记录它们。这会大大降低服务器的速度,但它可能是开发服务器上的一个选项。

也就是说,我很好奇你为什么需要它。最简单的解决方案是列出您的应用附带的所有 JAR 文件,以及 jar tvf,并去掉路径的最后一部分(类文件)。

【讨论】:

    【解决方案3】:

    我能想到的唯一方法是修改每个 web 应用程序,以便您可以向每个应用程序发送一个请求以获取其加载的类信息。然后,您可以创建一个新的 Web 应用,将现有 Web 应用的响应组合起来进行显示。

    如果您在一些漂亮的 UI 中不需要这些信息,那么 Sun JVM 有许多 -XX vm 选项,它们将向您显示与类加载有关的情况。

    http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

    我对 JRockit 不太熟悉,但如果它没有类似的选项,我会感到惊讶。

    【讨论】:

      【解决方案4】:

      好的,我设法让它在 Weblogic 上运行。同样,我的目标是在给定 WebLogic 服务器上部署的所有应用程序中获取 java 包名称。为什么?我有我的理由:)

      首先,您必须掌握所有已部署应用的 ear、war 或 jar 文件位置。为此,我们从 WebLogic 获取 AppDeployment MBean 并进行迭代,如下所示。

          Set<ObjectName> set = utils.getConfigMBeansByType("AppDeployment");
          for (ObjectName objectName : set) {
              String name = objectName.getKeyProperty("Name");            
      
              if (!appCache.contains(name)) {
                  //System.out.println("Config bean: " + objectName);
                  Object path = utils.getPropertyValue(objectName,
                          "AbsoluteSourcePath");
                  //System.out.println("Path: " + path);
                  if(path != null){
                      PackageFinder finder = new PackageFinder();
                      packages.addAll(finder.findPackages(path.toString()));
                  }
                  appCache.add(name);
              }
          }
      

      在上面的代码中,我们获得了 war、ear、jar 或分解文件夹的路径,并将其传递给 PackageFinder 类的 findPakages 方法,该方法完成所有工作。

       public Set<String> findPackages(String path){
          File file = new File(path);
          if(file.exists() && file.isFile()){
              InputStream in = null;
              try {
                  in = new BufferedInputStream(new FileInputStream(file));
                  if(path.toLowerCase().endsWith(".war")){
                      processWar(in);
                  }else if(path.toLowerCase().endsWith(".ear")){
                      processEar(in);
                  }/*
          Rest of the method body removed, I guess you get the idea 
          */              
          return packageNames;
      
      }
      
      
      public void processJar(InputStream in){
          ZipInputStream zin = null;
          try {
              zin = new ZipInputStream(in);
              ZipEntry entry;
              while((entry = zin.getNextEntry()) != null){
                  if(entry.getName().endsWith(".class")){
                      addPackage(entry.getName());
                  }
              }
          } catch (Exception e) {
          }
      }
      

      【讨论】:

      • 注意:这不会返回 JVM 中所有已加载类的包名。它只返回与 WebLogic 服务器中所有已部署应用程序捆绑在一起的类的所有包名称,这符合我的目的。
      猜你喜欢
      • 2011-02-02
      • 1970-01-01
      • 2022-08-03
      • 2013-05-09
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 2015-09-28
      • 2014-04-28
      相关资源
      最近更新 更多