【问题标题】:How to get names of classes inside a jar file?如何在 jar 文件中获取类的名称?
【发布时间】:2013-03-21 04:36:40
【问题描述】:

我有一个 JAR 文件,我需要获取这个 JAR 文件中所有类的名称。我该怎么做?

我在谷歌上搜索了一下,看到了一些关于 JarFile 或 Java ClassLoader 的内容,但我不知道该怎么做。

【问题讨论】:

  • 你在使用一些IDE吗?因为如果你使用它会自动显示。
  • 我正在使用 Eclipse,但我需要使用代码来完成。
  • @LuiggiMendoza - 潜在的副本有示例的答案以及文档资源。搜索其中一个类名 + 示例将产生几个有用的结果。
  • @Alias 可能的重复说明了如何从 jar 中查找和获取文件,而问题是关于获取 jar 中的类名(可能是其中所有包中的类)。 ErikKaju 的答案中的链接指向使用JarInputStreamJarEntry 类的可能解决方案,我在您推荐的链接的任何答案中都找不到。

标签: java file class jar classloader


【解决方案1】:

您可以使用 Java jar 工具。将jar文件的内容以txt文件形式列出,即可看到jar中的所有类。

jar tvf jarfile.jar

-t 列出存档目录

-v 在标准输出上生成详细输出

-f 指定归档文件名

【讨论】:

  • 谢谢。这回答了 OP 中没有被问到的“只是获取一个类列表”部分。
  • 您也可以在紧要关头使用unzip -l jarfile.jar。 JAR 文件只是一个带有清单的 zip 文件!
  • 问题是他可能想在运行时获取 jar 中的类文件,给定一个类加载器实例(可能会查看该特定 jar 中加载了哪些类)。
  • 这太棒了!我在这里找到了办公室文档。 docs.oracle.com/javase/tutorial/deployment/jar/view.html
  • 另外,这将不允许您检查注释,如果您在运行时扫描类,这可能是您想要做的事情。
【解决方案2】:

不幸的是,Java 没有提供一种简单的方法来列出“本机”JRE 中的类。这给您留下了几个选择: (a) 对于任何给定的 JAR 文件,您可以列出该 JAR 文件中的条目,找到 .class 文件,然后确定每个 .class 文件代表哪个 Java 类;或者 (b) 你可以使用一个库来为你做这件事。

选项 (a):手动扫描 JAR 文件

在此选项中,我们将使用 /path/to/jar/file.jar 的 jar 文件中包含的所有 Java 类的列表填充 classNames

List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
    if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
        // This ZipEntry represents a class. Now, what class does it represent?
        String className = entry.getName().replace('/', '.'); // including ".class"
        classNames.add(className.substring(0, className.length() - ".class".length()));
    }
}

选项 (b):使用专门的反射库

番石榴

Guava 至少从 14.0 开始就有 ClassPath,我已经使用并喜欢它。 ClassPath 的一个优点是它不会加载它找到的类,这在您扫描大量类时很重要。

ClassPath cp=ClassPath.from(Thread.currentThread().getContextClassLoader());
for(ClassPath.ClassInfo info : cp.getTopLevelClassesRecurusive("my.package.name")) {
    // Do stuff with classes here...
}

反思

我没有亲自使用过the Reflections library,但它似乎很受欢迎。网站上提供了一些很好的示例,例如通过 any JAR 文件提供的包中加载所有类的快速方法,这也可能对您的应用程序有用。

Reflections reflections = new Reflections("my.project.prefix");

Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

【讨论】:

  • 如果从可执行 jar 运行,反射也不起作用。
  • 使用可执行 jar 的 Spring 解决方案:stackoverflow.com/a/21430849/4265610.
  • 随便用。 jar tvf jarfile.jar。你为什么要这么做。
【解决方案3】:

也许你正在寻找jar 命令来获取终端中的类列表,

$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar 
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/spark/
org/apache/spark/unused/
org/apache/spark/unused/UnusedStubClass.class
META-INF/maven/
META-INF/maven/org.spark-project.spark/
META-INF/maven/org.spark-project.spark/unused/
META-INF/maven/org.spark-project.spark/unused/pom.xml
META-INF/maven/org.spark-project.spark/unused/pom.properties
META-INF/NOTICE

在哪里,

-t  list table of contents for archive
-f  specify archive file name

或者,只需在结果上方 grep 即可查看 .classes

$ jar tf ~/.m2/repository/org/apache/spark/spark-assembly/1.2.0-SNAPSHOT/spark-assembly-1.2.0-SNAPSHOT-hadoop1.0.4.jar | grep .class
org/apache/spark/unused/UnusedStubClass.class

要查看classes 的数量,

jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079

【讨论】:

  • 这正是我所需要的,即使问题所有者需要基于代码的解决方案。谢谢!
【解决方案4】:

这是我正在使用的 hack:

您可以像这样使用java 的自动完成功能:

java -cp path_to.jar <Tab>

这将为您提供可作为起始课程传递的课程列表。当然,尝试使用没有主文件的类不会有任何作用,但您可以看到java 认为.jar 中的类被调用了。

【讨论】:

    【解决方案5】:

    你可以试试:

    jar tvf jarfile.jar 
    

    只有当您的 jar 是可执行的,即在清单中您已将某个类定义为主类时,这才会有帮助

    【讨论】:

    • 在示例 jar 上添加一些具体示例到您的答案中。
    【解决方案6】:

    你可以使用

    jar tf example.jar
    

    【讨论】:

      【解决方案7】:

      以下命令将列出 jar 文件的内容。

      命令:- unzip -l jarfilename.jar.

      样本 o/p :-

      Archive: hello-world.jar Length Date Time Name --------- ---------- ----- ---- 43161 10-18-2017 15:44 hello-world/com/ami/so/search/So.class 20531 10-18-2017 15:44 hello-world/com/ami/so/util/SoUtil.class --------- ------- 63692 2 files

      根据unzip的手册

      -l 列出归档文件(短格式)。指定文件的名称、未压缩文件大小和修改日期和时间为 打印,连同所有的总数 指定的文件。如果 UnZip 是在定义 OS2_EAS 的情况下编译的,则 -l 选项还会列出存储的 OS/2 大小的列 扩展属性 (EA) 和 OS/2 访问 控制列表 (ACL)。此外,还会显示 zipfile 注释和单个文件 cmets(如果有)。如果一个文件是 从单一案例文件系统归档 (例如,旧的 MS-DOS FAT 文件系统)并且给出了 -L 选项,文件名被转换为小写并且是 以插入符号 (^) 为前缀。

      【讨论】:

      • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of howwhy 这解决了问题。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。
      【解决方案8】:

      Mac 操作系统: 在终端上:

      vim <your jar location>
      
      after jar gets opened, press / and pass your class name and hit enter
      

      【讨论】:

        【解决方案9】:

        你可以试试这个:

        unzip -v /your/jar.jar
        

        只有当您的 jar 是可执行的,即在清单中您已将某个类定义为主类时,这才会有帮助

        【讨论】:

          【解决方案10】:

          使用这个 bash 脚本:

          #!/bin/bash
          
          for VARIABLE in *.jar
          do
             jar -tf $VARIABLE |grep "\.class"|awk -v arch=$VARIABLE '{print arch ":" $4}'|sed 's/\//./g'|sed 's/\.\.//g'|sed 's/\.class//g'
          done
          

          这将列出目录中 jars 中的类,格式如下:

          file1.jar:fullyqualifiedclassName
          file1.jar:fullyqualifiedclassName
          file1.jar:fullyqualifiedclassName
          file1.jar:fullyqualifiedclassName
          file2.jar:fullyqualifiedclassName
          file2.jar:fullyqualifiedclassName
          file2.jar:fullyqualifiedclassName
          

          样本输出:

          commons-io.jar:org.apache.commons.io.ByteOrderMark
          commons-io.jar:org.apache.commons.io.Charsets
          commons-io.jar:org.apache.commons.io.comparator.AbstractFileComparator
          commons-io.jar:org.apache.commons.io.comparator.CompositeFileComparator
          commons-io.jar:org.apache.commons.io.comparator.DefaultFileComparator
          commons-io.jar:org.apache.commons.io.comparator.DirectoryFileComparator
          commons-io.jar:org.apache.commons.io.comparator.ExtensionFileComparator
          commons-io.jar:org.apache.commons.io.comparator.LastModifiedFileComparator
          

          在windows中你可以使用powershell:

          Get-ChildItem -File -Filter *.jar |
          ForEach-Object{
              $filename = $_.Name
              Write-Host $filename
              $classes = jar -tf $_.Name |Select-String -Pattern '.class' -CaseSensitive -SimpleMatch
              ForEach($line in $classes) {
                 write-host $filename":"(($line -replace "\.class", "") -replace "/", ".")
              }
          }
          

          【讨论】:

            【解决方案11】:

            解决方案描述:Eclipse IDE 可以通过创建示例 java 项目并在项目构建路径中添加所有 jar 来实现此目的

            以下步骤

            1. 创建一个示例 Eclipse Java 项目。

            2. 您在其构建路径中拥有的所有 jars

            3. CTRL+SHIFT+T 并键入完整的类名。

            4. 结果将显示在窗口中,所有 jar 都具有该类。见附图。

            【讨论】:

              【解决方案12】:

              windows cmd: 如果您将所有 te jar 放在同一目录中并执行以下命令,这将起作用

              for /r %i in (*) do ( jar tvf %i | find /I "search_string")
              

              【讨论】:

                猜你喜欢
                • 2012-01-21
                • 2012-03-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-03-18
                • 1970-01-01
                • 1970-01-01
                • 2018-09-21
                相关资源
                最近更新 更多