Jak uzyskać nazwy klas w pliku jar?

112

Mam plik JAR i muszę uzyskać nazwę wszystkich klas w tym pliku JAR. Jak mogę to zrobić?

Wyszukałem w Google i zobaczyłem coś o JarFile lub Javie, ClassLoaderale nie mam pojęcia, jak to zrobić.

sticksu
źródło
Czy używasz jakiegoś środowiska IDE? Ponieważ zostanie ono automatycznie wyświetlone, jeśli używasz takiego.
joey rohan
Używam Eclipse, ale muszę to zrobić z kodem.
sticksu
@LuiggiMendoza - Potencjalny duplikat ma odpowiedzi z przykładami, a także zasoby do dokumentacji. Wyszukiwanie jednej z tych nazw klas + przykład da kilka przydatnych wyników.
Aiias
@Alias ​​możliwy duplikat określa, jak znaleźć i pobrać plik z jar, podczas gdy pytanie dotyczy pobrania nazw klas wewnątrz jar (prawdopodobnie klas we wszystkich pakietach w nim). Łącze w odpowiedzi ErikKaju wskazuje na możliwe rozwiązanie przy użyciu klas JarInputStreami JarEntry, których nie mogę znaleźć w żadnej odpowiedzi na Twój odsyłacz.
Luiggi Mendoza

Odpowiedzi:

68

Niestety Java nie zapewnia łatwego sposobu wyświetlania klas w „natywnym” środowisku JRE. To pozostawia kilka opcji: (a) dla dowolnego pliku JAR można wyświetlić listę wpisów w tym pliku JAR, znaleźć .classpliki, a następnie określić, którą klasę Java .classreprezentuje każdy plik; lub (b) możesz skorzystać z biblioteki, która zrobi to za Ciebie.

Opcja (a): Ręczne skanowanie plików JAR

W tej opcji wypełnimy classNameslistę wszystkich klas Java zawartych w pliku jar pod adresem /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()));
    }
}

Opcja (b): Korzystanie ze specjalistycznych bibliotek odbić

Guawa

Guawa ma ClassPathod co najmniej 14,0, którego używałem i lubiłem. Jedną z fajnych rzeczy ClassPathjest to, że nie ładuje znalezionych klas, co jest ważne, gdy skanujesz w poszukiwaniu dużej liczby klas.

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

Refleksje

Osobiście nie korzystałem z biblioteki Reflections , ale wydaje się, że jest ona lubiana. Na stronie internetowej znajdują się świetne przykłady, takie jak szybki sposób załadowania wszystkich klas w pakiecie dostarczonym przez dowolny plik JAR, który może być również przydatny dla twojej aplikacji.

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

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

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
sigpwned
źródło
Odbicia nie działają również, jeśli są uruchamiane z wykonywalnego pliku jar.
Łukasz
Rozwiązanie Spring działające z wykonywalnych plików jar: stackoverflow.com/a/21430849/4265610 .
Łukasz
1
Po prostu użyj. jar tvf jarfile.jar. Po co to wszystko robisz.
Philip Rego
184

Możesz użyć jarnarzędzia Java . Wypisz zawartość pliku jar w pliku txt, a zobaczysz wszystkie klasy w pliku jar.

jar tvf jarfile.jar

-t wyświetla spis treści dla archiwum

-v generuje szczegółowe wyjście na standardowe wyjście

-f określ nazwę pliku archiwum

Sanjeev Gupta
źródło
1
Dzięki. Odpowiada to na część PO „po prostu uzyskaj listę zajęć”, o którą nie pytano.
octopusgrabbus
9
Możesz także użyć unzip -l jarfile.jarw szczypanie. Plik JAR to po prostu plik zip z manifestem!
podpisany
3
Problem polega na tym, że prawdopodobnie chciał dostać pliki klas do jar w czasie wykonywania, biorąc pod uwagę instancję classloader (prawdopodobnie sprawdził, jakie klasy są ładowane w tym konkretnym jar).
Richard Duerr,
19

Może szukasz jarpolecenia, aby pobrać listę klas w terminalu,

$ 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

gdzie,

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

Lub po prostu grep powyżej wyniku, aby zobaczyć .classtylko 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

Aby zobaczyć liczbę classes,

jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079
prayagupd
źródło
2
to było dokładnie to, czego potrzebowałem, nawet jeśli właściciel pytania potrzebował rozwiązania opartego na kodzie. Dzięki!
Providencemac
10

To jest hack, którego używam:

Możesz użyć javaautouzupełniania w następujący sposób:

java -cp path_to.jar <Tab>

W ten sposób otrzymasz listę klas dostępnych do zaliczenia jako klasa początkowa. Oczywiście próba użycia takiej, która nie ma pliku głównego, nic nie da, ale możesz zobaczyć, co javawedług nich .jarsą wywoływane klasy wewnątrz .

stanm
źródło
7

Możesz użyć

jar tf example.jar
samotna gwiazda
źródło
6

Możesz spróbować:

jar tvf jarfile.jar 

Będzie to pomocne tylko wtedy, gdy twój jar jest wykonywalny, tj. W manifeście zdefiniowałeś jakąś klasę jako klasę główną

Pallav
źródło
Dodaj konkretny przykład na przykładowym słoiku do swojej odpowiedzi.
Juru
4

Poniższe polecenie wyświetli zawartość pliku jar .

polecenie: - unzip -l jarfilename.jar.

próbka 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

Zgodnie z instrukcją unzip

-l wyświetla listę plików archiwalnych (krótki format). Drukowane są nazwy, rozmiary nieskompresowanych plików oraz daty i godziny modyfikacji określonych plików, a także sumy wszystkich określonych plików. Jeśli UnZip został skompilowany ze zdefiniowanym OS2_EAS, opcja -l wyświetla także kolumny dla rozmiarów przechowywanych atrybutów rozszerzonych OS / 2 (EA) i list kontroli dostępu (ACL) OS / 2. Ponadto wyświetlany jest komentarz do pliku zip i komentarze do poszczególnych plików (jeśli istnieją). Jeśli plik został zarchiwizowany z systemu plików z pojedynczą wielkością liter (na przykład stary system plików MS-DOS FAT) i podano opcję -L, nazwa pliku jest konwertowana na małe litery i poprzedzona znakiem daszka (^).

Opster Elasticsearch Ninja
źródło
Choć ten fragment kodu jest mile widziany i może zapewnić jakąś pomoc, byłoby znacznie się poprawiła, gdyby obejmowała wyjaśnienie z how i dlaczego to rozwiązuje problem. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a nie tylko osoba, która zapyta teraz! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight,
2

Możesz spróbować tego:

unzip -v /your/jar.jar

Będzie to pomocne tylko wtedy, gdy twój jar jest wykonywalny, tj. W manifeście zdefiniowałeś jakąś klasę jako klasę główną

Abhimanyu Dutta
źródło
1

Użyj tego skryptu 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

to wyświetli listę klas wewnątrz jars w twoim katalogu w postaci:

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

Przykładowe dane wyjściowe:

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

W Windows możesz użyć 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 "/", ".")
    }
}
ESPRIELLA_GREGORIO QUINTERO_DE
źródło
0

Opis rozwiązania : Eclipse IDE można w tym celu wykorzystać, tworząc przykładowy projekt java i dodając wszystkie pliki JAR w ścieżce Project Build

KROKI poniżej :

  1. Utwórz przykładowy projekt Eclipse Java.

  2. Wszystkie słoiki, które masz na swojej ścieżce budowania

  3. CTRL + SHIFT + T i wpisz pełną nazwę klasy.

  4. Wyniki zostaną wyświetlone w oknie ze wszystkimi słoikami posiadającymi tę klasę. Zobacz załączone zdjęcie. wprowadź opis obrazu tutaj

Arokiadoss Asirvatham
źródło
0

cmd windows: To zadziała, jeśli masz wszystkie te jars w tym samym katalogu i wykonasz poniższe polecenie

for /r %i in (*) do ( jar tvf %i | find /I "search_string")
Vikas
źródło
0

Mac OS: w terminalu:

vim <your jar location>

after jar gets opened, press / and pass your class name and hit enter
Rajiv Singh
źródło