Як знайти назви класів всередині файлу jar?


112

У мене є файл JAR, і мені потрібно отримати назву всіх класів всередині цього файлу JAR. Як я можу це зробити?

Я погуглив його і побачив щось про JarFile або Java, ClassLoaderале поняття не маю, як це зробити.


Використовуєте якийсь IDE? Так як він буде автоматично відображатися, якщо ви використовуєте його.
joey rohan

Я використовую Eclipse, але мені потрібно це зробити з кодом.
sticksu

@LuiggiMendoza - потенційний дублікат містить відповіді з прикладами, а також ресурси для документації. Пошук одного з таких назв класів + приклад дасть кілька корисних результатів.
Айяс

@Alias ​​можливий дублікат визначає, як знайти та отримати файл з банку, тоді як питання полягає у тому, щоб назви класів всередині банку (можливо, класів у всіх пакунках всередині нього). Посилання у відповіді ErikKaju вказує на можливе рішення з використанням JarInputStreamта JarEntryкласів, які я не можу знайти в жодній відповіді вашого згаданого посилання.
Луїджі Мендоса

Відповіді:


68

На жаль, Java не пропонує простий спосіб перерахування класів у "рідному" JRE. Це дає вам декілька варіантів: (a) для будь-якого файлу JAR ви можете перелічити записи всередині цього файлу JAR, знайти .classфайли та визначити, який клас Java .classпредставляє кожен файл; або (b) ви можете використовувати бібліотеку, яка робить це за вас.

Варіант (a): Сканування файлів JAR вручну

У цьому варіанті ми заповнимо classNamesсписок усіх класів Java, що містяться у файлі jar на /path/to/jar/file.jar.

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): Використання спеціалізованих бібліотек відображень

Гуава

З тих ClassPathпір Guava принаймні 14,0, що я використовував і любив. Одне приємне в тому ClassPath, що він не завантажує знайдені класи, що важливо, коли ви скануєте велику кількість класів.

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

Роздуми

Я особисто не користувався бібліотекою Reflections , але це здається вподобаним. На веб-сайті наведено кілька чудових прикладів, як цей швидкий спосіб завантаження всіх класів у пакеті, наданому будь-яким файлом JAR, який також може бути корисним для вашої програми.

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

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

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

Роздуми не спрацьовують і при запуску з виконуваної банки.
Лука

Весняне рішення, що працює з виконуваних банок: stackoverflow.com/a/21430849/4265610 .
Лука

1
Просто використовуйте. jar tvf jarfile.jar. Для чого ти все це робиш.
Філіп Рего

184

Ви можете використовувати jarінструмент Java . Перерахуйте вміст файлу jar у файлі txt, і ви можете побачити всі класи в банку.

jar tvf jarfile.jar

-t список вмісту для архіву

-v генерувати багатослівний вихід на стандартному виході

-f вкажіть ім'я файлу архіву


1
Дякую. Це дає відповідь на частину ОП, яку не запитували.
восьминоги граббус

9
Ви також можете використовувати unzip -l jarfile.jarв щіпці. Файл JAR - це лише поштовий файл з маніфестом!
підписано

3
Проблема полягає в тому, що він, ймовірно, хотів отримати файли класів всередині банку під час виконання, враховуючи екземпляр завантажувача класів (ймовірно, побачити, які класи завантажуються всередині цієї конкретної банки).
Річард Дуерр

19

Можливо, ви шукаєте 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

Або просто проклейте верхній результат, щоб побачити .classлише es

$ 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

Щоб побачити кількість classес,

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

2
це саме те, що мені було потрібно, навіть якщо власнику запитання було потрібно рішення на основі коду. Дякую!
Провіденсмак

10

Це злом, який я використовую:

Ви можете використовувати javaавтозаповнення так:

java -cp path_to.jar <Tab>

Це дасть вам список класів, доступних для проходження як початковий клас. Звичайно, намагання використовувати той, у якого немає головного файлу, нічого не зробить, але ви можете бачити, що javaвважають, що .jarназиваються класи всередині .



5

Ви можете спробувати:

jar tvf jarfile.jar 

Це буде корисно лише в тому випадку, якщо ваш jar виконується, тобто в маніфесті ви визначили деякий клас як основний клас


Додайте якийсь конкретний приклад на прикладі баночки до своєї відповіді.
Джуру

4

Внизу команди буде перераховано вміст файлу 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

- список архівних файлів (короткий формат). Друкуються імена, нестиснені розміри файлів та дати модифікації та час вказаних файлів разом із загальними підсумками для всіх вказаних файлів. Якщо UnZip був складений із визначеним OS2_EAS, опція -l також містить списки стовпців для розмірів збережених OS / 2 розширених атрибутів (EA) та списків контролю доступу OS / 2 (ACL). Крім того, відображаються коментарі до zipfile та окремі коментарі до файлів (якщо такі є). Якщо файл був заархівований з однофакторної файлової системи (наприклад, старої файлової системи MS-DOS FAT) та був наданий варіант -L, ім'я файлу перетворюється на малі регістри та встановлюється за допомогою каретки (^).


У той час як цей фрагмент коду вітається, і може забезпечити деяку допомогу, було б значно покращено , якщо вона була придбана пояснення про те , як і те, чому це вирішує проблему. Пам’ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз запитує! Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Toby Speight

2

Ви можете спробувати це:

unzip -v /your/jar.jar

Це буде корисно лише в тому випадку, якщо ваш jar виконується, тобто в маніфесті ви визначили деякий клас як основний клас


1

Використовуйте цей скрипт 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

це перерахує класи у банках у вашому каталозі у вигляді:

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

У вікнах ви можете використовувати 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 "/", ".")
    }
}

0

Опис рішення : ID Eclipse можна використовувати для цього, створивши зразок java-проекту та додавши всі банки на шляху побудови проекту

КРОКИ нижче :

  1. Створіть зразок проекту Eclipse Java.

  2. Всі баночки, які ви маєте на своєму Build Path

  3. CTRL + SHIFT + T і введіть повне ім’я класу.

  4. Результати будуть відображатися у вікні з усіма банками, що мають цей клас. Дивіться додане зображення. введіть тут опис зображення


0

windows cmd: Це спрацює, якщо у вас є всі банки в одному каталозі та виконується команда нижче

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.