Bir jar dosyası içindeki sınıfların isimleri nasıl alınır?


112

Bir JAR dosyam var ve bu JAR dosyasındaki tüm sınıfların adını almam gerekiyor. Bunu nasıl yapabilirim?

Google'da araştırdım ve JarFile veya Java hakkında bir şey gördüm ClassLoaderama nasıl yapılacağı hakkında hiçbir fikrim yok.


IDE kullanıyor musunuz? Birini kullanıyorsanız otomatik olarak görüntüleneceği için.
joey rohan

Eclipse kullanıyorum ama bunu kodla yapmam gerekiyor.
sticksu

@LuiggiMendoza - Olası kopyada örneklerle birlikte cevaplar ve dokümantasyon kaynakları var. Bu sınıf isimlerinden birini aramak + örnek birkaç yararlı sonuç verecektir.
Aiias

@Alias, olası kopya bir kavanozdan bir dosyanın nasıl bulunacağını ve alınacağını belirtirken, soru bir kavanozun içindeki sınıf adlarını (muhtemelen içindeki tüm paketlerdeki sınıflar) almakla ilgilidir. ErikKaju'nun cevabındaki bağlantı, başvurulan bağlantınızın herhangi bir cevabında bulamadığım olası bir çözüme JarInputStreamve JarEntrysınıflara işaret ediyor.
Luiggi Mendoza

Yanıtlar:


68

Maalesef Java, sınıfları "yerel" JRE'de listelemek için kolay bir yol sağlamaz. Bu size birkaç seçenek bırakır: (a) herhangi bir JAR dosyası için, bu JAR dosyasının içindeki girişleri listeleyebilir, .classdosyaları bulabilir ve ardından her .classdosyanın hangi Java sınıfını temsil ettiğini belirleyebilirsiniz; veya (b) bunu sizin için yapan bir kitaplık kullanabilirsiniz.

Seçenek (a): JAR dosyalarını manuel olarak tarama

Bu seçenekte, classNamesadresinde bir jar dosyasının içinde bulunan tüm Java sınıflarının listesini dolduracağız /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()));
    }
}

Seçenek (b): Özel yansıtma kitaplıklarını kullanma

Guava

Guava , ClassPathkullandığım ve sevdiğim en az 14.0'dan beri var. ClassPathBununla ilgili güzel bir şey , bulduğu sınıfları yüklememesidir; bu, çok sayıda sınıfı taradığınızda önemlidir.

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

Yansımalar

Reflections kütüphanesini kişisel olarak kullanmadım ama çok beğenilmiş görünüyor. Web sitesinde, herhangi bir JAR dosyası tarafından sağlanan bir paketteki tüm sınıfları yüklemenin bu hızlı yolu gibi bazı harika örnekler verilmiştir ve bu da uygulamanız için yararlı olabilir.

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

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

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

Yürütülebilir bir kavanozdan çalıştırıldığında da yansımalar çalışmaz.
Luke

Yürütülebilir kavanozlardan çalışan bir Yay çözümü: stackoverflow.com/a/21430849/4265610 .
Luke

1
Sadece kullan. jar tvf jarfile.jar. Tüm bunları neden yapıyorsun?
Philip Rego

184

Java jararacını kullanabilirsiniz . Bir txt dosyasında jar dosyasının içeriğini listeleyin ve kavanozdaki tüm sınıfları görebilirsiniz.

jar tvf jarfile.jar

-t arşiv için içindekiler tablosu

-v standart çıktıda ayrıntılı çıktı oluşturur

-f arşiv dosyası adını belirtin


1
Teşekkürler. Bu, OP'nin sorulmayan "sadece bir sınıf listesi alın" kısmını yanıtlar.
octopusgrabbus

9
unzip -l jarfile.jarBir tutam da kullanabilirsiniz . Bir JAR dosyası, bildirim içeren bir zip dosyasıdır!
sigpwned

3
Sorun, bir sınıf yükleyici örneği verildiğinde (büyük olasılıkla o belirli jar içine hangi sınıfların yüklendiğini görmek için) çalışma zamanında sınıf dosyalarını bir jar içine almak istemesiydi.
Richard Duerr

19

Belki de jarterminaldeki sınıfların listesini almak için komut arıyorsunuz ,

$ 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

nerede,

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

Ya da, sadece görmek için sonuç yukarıda grep .classes yalnızca

$ 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

E sayısını görmek için class,

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

2
Soru sahibinin kod tabanlı bir çözüme ihtiyacı olsa bile ihtiyacım olan buydu. Teşekkürler!
Providencemac

10

Bu, kullandığım bir hack:

javaAdlı kullanıcının otomatik tamamlamasını şu şekilde kullanabilirsiniz :

java -cp path_to.jar <Tab>

Bu size başlangıç ​​sınıfı olarak geçebileceğiniz sınıfların bir listesini verecektir. Tabii ki, ana dosyası olmayan birini kullanmaya çalışmak hiçbir şey yapmaz, ancak javaiçindeki sınıfların .jarçağrıldığını düşündüğünü görebilirsiniz .



6

Deneyebilirsin:

jar tvf jarfile.jar 

Bu, yalnızca jar'ınız çalıştırılabilirse yardımcı olacaktır, yani manifest'te bazı sınıfları ana sınıf olarak tanımladıysanız


Cevabınıza örnek bir kavanozda belirli bir örnek ekleyin.
Juru

4

Aşağıdaki komut bir jar dosyasının içeriğini listeleyecektir .

komut: - unzip -l jarfilename.jar.

örnek 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

Kılavuzuna göre unzip

-l arşiv dosyalarını listeler (kısa format). Belirtilen dosyaların adları, sıkıştırılmamış dosya boyutları ve değişiklik tarihleri ​​ve saatleri, belirtilen tüm dosyalar için toplamlarla birlikte yazdırılır. UnZip, OS2_EAS tanımlı olarak derlenmişse, -l seçeneği, depolanan OS / 2 genişletilmiş özniteliklerin (EA'lar) ve OS / 2 erişim kontrol listelerinin (ACL'ler) boyutları için sütunları da listeler. Ek olarak, zip dosyası yorumu ve bağımsız dosya yorumları (varsa) görüntülenir. Bir dosya tek durumlu bir dosya sisteminden arşivlenmişse (örneğin, eski MS-DOS FAT dosya sistemi) ve -L seçeneği verilmişse, dosya adı küçük harfe dönüştürülür ve bir düzeltme işareti (^) ile başlar.


Bu kod parçacığı açığız ve bazı yardım sağlamak görülebilir fakat bunun olacağını bunun bir açıklama dahil eğer büyük ölçüde geliştirilmiş bir nasıl ve niçin bu çözer sorunu. Sadece şimdi soran kişi değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın! Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğuna dair bir gösterge verin.
Toby Speight

2

Bunu deneyebilirsiniz:

unzip -v /your/jar.jar

Bu, yalnızca jar'ınız çalıştırılabilirse yardımcı olacaktır, yani manifest'te bazı sınıfları ana sınıf olarak tanımladıysanız


1

Bu bash komut dosyasını kullanın:

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

bu, dizininizdeki kavanozların içindeki sınıfları şu şekilde listeler:

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

Örnek çıktı:

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'ta powershell'i kullanabilirsiniz:

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

Çözümün Açıklaması : Eclipse IDE, örnek bir java projesi oluşturarak ve tüm kavanozları Proje Oluşturma yoluna ekleyerek bunun için kullanılabilir

Aşağıdaki ADIMLAR :

  1. Örnek bir Eclipse Java projesi oluşturun.

  2. Yapım Yolunda sahip olduğunuz tüm kavanozlar

  3. CTRL + ÜST KRKT + T ve tam sınıf adını yazın.

  4. Sonuçlar, o sınıfa sahip tüm kavanozlarla birlikte pencerede görüntülenecektir. Ekteki resme bakın. görüntü açıklamasını buraya girin


0

windows cmd: Bu, aynı dizinde tüm kavanozlara sahipseniz ve aşağıdaki komutu çalıştırırsanız işe yarar

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

0

Mac OS: Terminalde:

vim <your jar location>

after jar gets opened, press / and pass your class name and hit enter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.