Bagaimana cara mendapatkan nama kelas di dalam file jar?

112

Saya memiliki file JAR dan saya perlu mendapatkan nama semua kelas di dalam file JAR ini. Bagaimana saya bisa melakukan itu?

Saya mencari di Google dan melihat sesuatu tentang JarFile atau Java ClassLoadertetapi saya tidak tahu bagaimana melakukannya.

sticksu
sumber
Apakah Anda menggunakan beberapa IDE? Karena akan otomatis ditampilkan jika Anda menggunakannya.
joey rohan
Saya menggunakan Eclipse, tetapi saya perlu melakukan ini dengan kode.
sticksu
@LuiggiMendoza - Calon duplikat memiliki jawaban dengan contoh serta sumber daya untuk dokumentasi. Mencari salah satu dari nama kelas + contoh tersebut akan menghasilkan beberapa hasil yang berguna.
Aiias
@Alias ​​kemungkinan duplikat menyatakan bagaimana menemukan dan mendapatkan file dari jar, sementara pertanyaannya adalah tentang memasukkan nama kelas di dalam jar (mungkin kelas di semua paket di dalamnya). Tautan dalam jawaban ErikKaju menunjuk ke solusi yang mungkin digunakan JarInputStreamdan JarEntrykelas-kelas yang tidak dapat saya temukan dalam jawaban apa pun dari tautan rujukan Anda.
Luiggi Mendoza

Jawaban:

68

Sayangnya, Java tidak menyediakan cara mudah untuk membuat daftar kelas di JRE "asli". Itu membuat Anda memiliki beberapa opsi: (a) untuk file JAR tertentu, Anda dapat membuat daftar entri di dalam file JAR tersebut, menemukan .classfile, dan kemudian menentukan kelas Java mana yang .classdiwakili oleh setiap file; atau (b) Anda dapat menggunakan perpustakaan yang melakukan ini untuk Anda.

Opsi (a): Memindai file JAR secara manual

Dalam opsi ini, kami akan mengisi classNamesdengan daftar semua kelas Java yang ada di dalam file jar di /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()));
    }
}

Opsi (b): Menggunakan pustaka refleksi khusus

Jambu biji

Jambu biji telah memiliki ClassPathsetidaknya 14.0, yang telah saya gunakan dan sukai. Satu hal yang menyenangkan ClassPathadalah bahwa ia tidak memuat kelas yang ditemukannya, yang penting saat Anda memindai sejumlah besar kelas.

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

Refleksi

Saya pribadi belum pernah menggunakan perpustakaan Refleksi , tetapi tampaknya sangat disukai. Beberapa contoh bagus disediakan di situs web seperti cara cepat ini untuk memuat semua kelas dalam paket yang disediakan oleh file JAR apa pun , yang mungkin juga berguna untuk aplikasi Anda.

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

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

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
sigpwned
sumber
Refleksi tidak berfungsi jika dijalankan dari stoples yang dapat dieksekusi.
Luke
Solusi Spring yang bekerja dari stoples yang dapat dieksekusi: stackoverflow.com/a/21430849/4265610 .
Lukas
1
Gunakan saja. jar tvf jarfile.jar. Mengapa Anda melakukan semua ini untuk.
Philip Rego
184

Anda dapat menggunakan jaralat Java . Buat daftar konten file jar dalam file txt dan Anda dapat melihat semua kelas di jar.

jar tvf jarfile.jar

-t daftar daftar isi untuk arsip

-v menghasilkan keluaran verbose pada keluaran standar

-f tentukan nama file arsip

Sanjeev Gupta
sumber
1
Terima kasih. Ini menjawab bagian "hanya mendapatkan daftar kelas" dari OP yang tidak diminta.
octopusgrabbus
9
Anda juga bisa menggunakannya unzip -l jarfile.jardalam keadaan darurat. File JAR hanyalah file zip dengan manifes!
sigpwned
3
Masalahnya adalah dia mungkin ingin mendapatkan file kelas di dalam jar pada saat runtime, mengingat instance classloader (kemungkinan untuk melihat kelas apa yang dimuat di dalam jar tertentu itu).
Richard Duerr
19

Mungkin Anda mencari jarperintah untuk mendapatkan daftar kelas di terminal,

$ 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

dimana,

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

Atau, grep saja hasil di atas untuk melihat .classesnya saja

$ 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

Untuk melihat jumlah classes,

jar tvf launcher/target/usergrid-launcher-1.0-SNAPSHOT.jar | grep .class | wc -l
61079
prayagupd.dll
sumber
2
inilah yang saya butuhkan, bahkan jika pemilik pertanyaan membutuhkan solusi berbasis kode. Terima kasih!
providencemac
10

Ini adalah peretasan yang saya gunakan:

Anda dapat menggunakan javapelengkapan otomatis seperti ini:

java -cp path_to.jar <Tab>

Ini akan memberi Anda daftar kelas yang tersedia untuk dilalui sebagai kelas awal. Tentu saja, mencoba menggunakan salah satu yang tidak memiliki file utama tidak akan melakukan apa-apa, tetapi Anda dapat melihat apa yang javamenurut kelas di dalam .jardipanggil.

stanm
sumber
7

Anda bisa menggunakan

jar tf example.jar
loneStar
sumber
5

Anda dapat mencoba:

jar tvf jarfile.jar 

Ini akan berguna hanya jika jar Anda dapat dieksekusi, yaitu dalam manifes Anda telah menetapkan beberapa kelas sebagai kelas utama

Pallav
sumber
Tambahkan beberapa contoh spesifik pada contoh toples ke jawaban Anda.
Juru
4

Perintah di bawah ini akan mencantumkan konten file jar .

perintah: - unzip -l jarfilename.jar.

sampel 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

Menurut manual unzip

-l daftar file arsip (format pendek). Nama, ukuran file yang tidak dikompresi dan tanggal dan waktu modifikasi dari file yang ditentukan dicetak, bersama dengan total untuk semua file yang ditentukan. Jika UnZip dikompilasi dengan OS2_EAS yang ditentukan, opsi -l juga mencantumkan kolom untuk ukuran penyimpanan OS / 2 atribut tambahan (EA) dan daftar kontrol akses (ACL) OS / 2. Selain itu, komentar zipfile dan komentar file individu (jika ada) akan ditampilkan. Jika file diarsipkan dari sistem file kasus tunggal (misalnya, sistem file MS-DOS FAT lama) dan opsi -L diberikan, nama file diubah menjadi huruf kecil dan diawali dengan tanda sisipan (^).

Opster Elasticsearch Ninja
sumber
Meskipun cuplikan kode ini diterima, dan mungkin memberikan sedikit bantuan, akan sangat ditingkatkan jika menyertakan penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang! Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Toby Speight
2

Anda bisa mencoba ini:

unzip -v /your/jar.jar

Ini akan berguna hanya jika jar Anda dapat dieksekusi, yaitu dalam manifes Anda telah menetapkan beberapa kelas sebagai kelas utama

Abimanyu Dutta
sumber
1

Gunakan skrip bash ini:

#!/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

ini akan mencantumkan kelas-kelas di dalam toples di direktori Anda dalam bentuk:

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

Output sampel:

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

Di windows Anda dapat menggunakan 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
sumber
0

Deskripsi Solusi : Eclipse IDE dapat digunakan untuk ini dengan membuat proyek java sampel dan menambahkan semua botol di jalur Project Build

LANGKAH di bawah ini :

  1. Buat contoh proyek Eclipse Java.

  2. Semua toples yang Anda miliki di Build Path-nya

  3. CTRL + SHIFT + T dan Ketik nama kelas lengkap.

  4. Hasil akan ditampilkan di jendela dengan semua toples memiliki kelas itu. Lihat gambar terlampir. masukkan deskripsi gambar di sini

Arokiadoss Asirvatham
sumber
0

windows cmd: Ini akan berfungsi jika Anda memiliki semua toples te di direktori yang sama dan menjalankan perintah di bawah ini

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

Mac OS: Di Terminal:

vim <your jar location>

after jar gets opened, press / and pass your class name and hit enter
Rajiv Singh
sumber