Få navn på klasser inne i en JAR-fil

1. Oversikt

De fleste Java-biblioteker er tilgjengelige som JAR-filer. I denne opplæringen vil vi ta for oss hvordan du får navn på klasser i en gitt JAR-fil fra kommandolinjen og fra et Java-program.

Deretter ser vi på et Java-programeksempel for lasting av klassene fra en gitt JAR-fil ved kjøretid.

2. Eksempel på JAR-fil

I denne opplæringen tar vi stripe-0.0.1-SNAPSHOT.jar fil som et eksempel for å adressere hvordan du får klassenavnene i JAR-filen:

3. Bruke krukke Kommando

JDK leveres med en krukke kommando. Vi kan bruke denne kommandoen med t og f alternativer for å vise innholdet i en JAR-fil:

$ jar tf stripe-0.0.1-SNAPSHOT.jar META-INF / META-INF / MANIFEST.MF ... maler / resultat.html maler / kassa.html application.properties com / baeldung / stripe / StripeApplication.class com / baeldung / stripe / ChargeRequest.class com / baeldung / stripe / StripeService.class com / baeldung / stripe / ChargeRequest $ Currency.class ...

Siden vi bare er interessert i *.klasse filer i arkivet, kan vi filtrere utdataene ved hjelp av grep kommando:

$ jar tf stripe-0.0.1-SNAPSHOT.jar | grep '\ .class $' com / baeldung / stripe / StripeApplication.class com / baeldung / stripe / ChargeRequest.class com / baeldung / stripe / StripeService.class com / baeldung / stripe / ChargeRequest $ Currency.class com / baeldung / stripe /ChargeController.class no / baeldung / stripe / CheckoutController.class

Dette gir oss en liste over klassefiler i JAR-filen.

4. Få klassenavn på en JAR-fil i Java

Bruker krukke kommandoen for å skrive ut klassenavnene fra en JAR-fil er ganske grei. Noen ganger vil vi imidlertid laste noen klasser fra en JAR-fil i Java-programmet vårt. I dette tilfellet er ikke kommandolinjeproduksjonen nok.

For å nå vårt mål, må vi skann JAR-filen fra et Java-program og få klassenavnene.

La oss ta en titt på hvordan vi trekker ut klassenavn fra vårt eksempel på JAR-filen bruker JarFile og JarEntry klasser:

offentlig statisk sett getClassNamesFromJarFile (File givenFile) kaster IOException {Set classNames = new HashSet (); prøv (JarFile jarFile = ny JarFile (givenFile)) {Enumeration e = jarFile.entries (); mens (e.hasMoreElements ()) {JarEntry jarEntry = e.nextElement (); if (jarEntry.getName (). endsWith (". class")) {String className = jarEntry.getName () .replace ("/", ".") .replace (". class", ""); classNames.add (className); }} returner classNames; }} 

La oss nå se nærmere på koden i metoden ovenfor og forstå hvordan den fungerer:

  • prøv (JarFile jarFile = ny JarFile (givenFile)) - Her brukte vi en prøve-med-ressurs uttalelse for å få jarFile fra det gitte Fil gjenstand
  • hvis (jarEntry.getName (). endsWith (“. class”)) {…} - Vi tar hver klasse jarEntry, og endre banen til klassefilen til det kvalifiserte klassenavnet, for eksempel endre “Pakke1 / pakke2 / SomeType.class” inn i “Package1.package2.SomeType”

La oss verifisere om metoden kan trekke ut klassenavnene fra JAR-eksemplet vårt gjennom en enhetstestmetode:

privat statisk sluttstreng JAR_PATH = "eksempel-jar / stripe-0.0.1-SNAPSHOT.jar"; privat statisk slutt Sett EXPECTED_CLASS_NAMES = Sets.newHashSet ("com.baeldung.stripe.StripeApplication", "com.baeldung.stripe.ChargeRequest", "com.baeldung.stripe.StripeService", "com.baeldung.stripe.ChargeRequest $ Currency "," com.baeldung.stripe.ChargeController "," com.baeldung.stripe.CheckoutController "); @Test offentlig ugyldighet gittJarFilePath_whenLoadClassNames_thenGetClassNames () kaster IOException, URISyntaxException {File jarFile = ny fil (Objects.requireNonNull (getClass (). GetClassLoader (). GetResource (JAR_PATH)). Sett classNames = GetClassNamesFromJar.getClassNamesFromJarFile (jarFile); Assert.assertEquals (EXPECTED_CLASS_NAMES, classNames); } 

5. Få klasser fra en JAR-fil i Java

Vi har sett hvordan du får klassenavnene fra en JAR-fil. Noen ganger ønsker vi å laste inn noen klasser fra en JAR-fil dynamisk ved kjøretid.

I dette tilfellet kan vi først få klassenavnene fra den gitte JAR-filen ved hjelp av vår getClassNamesFromJarFile metode.

Deretter kan vi lage en ClassLoader for å laste nødvendige klasser med navn:

offentlig statisk sett getClassesFromJarFile (File jarFile) kaster IOException, ClassNotFoundException {Set classNames = getClassNamesFromJarFile (jarFile); Sett klasser = nytt HashSet (classNames.size ()); prøv (URLClassLoader cl = URLClassLoader.newInstance (new URL [] {new URL ("jar: file:" + jarFile + "! /")}) {for (String name: classNames) {Class clazz = cl.loadClass ( Navn); // Last klassen etter navneklasser.add (clazz); }} returnere klasser; }

I metoden ovenfor opprettet vi en URLClassLoader motsette seg for å laste klassene. Implementeringen er ganske grei.

Imidlertid er det sannsynligvis verdt å forklare syntaksen for JAR URL litt. En gyldig JAR-URL inneholder tre deler: “krukke: + [plasseringen av JAR-filen] + !/”.

Den avsluttende “!/”Indikerer at JAR URL refererer til en hel JAR-fil. La oss se noen eksempler på JAR URL:

jar: //www.example.com/some_jar_file.jar! / jar: file: /local/path/to/some_jar_file.jar! / jar: file: / C: /windows/path/to/some_jar_file.jar! /

I vår getClassesFromJarFile metode, ligger JAR-filen på det lokale filsystemet, og derfor er prefikset til URL-en “fil:“.

La oss nå skrive en testmetode for å verifisere om metoden vår kan oppnå alt forventet Klasse gjenstander:

@Test offentlig ugyldighet gittJarFilePath_whenLoadClass_thenGetClassObjects () kaster IOException, ClassNotFoundException, URISyntaxException {File jarFile = ny fil (Objects.requireNonNull (getClass (). GetClassLoader ().). Sett klasser = GetClassNamesFromJar.getClassesFromJarFile (jarFile); Sett navn = klasser.strøm (). Kart (Klasse :: getName). Samle (Collectors.toSet ()); Assert.assertEquals (EXPECTED_CLASS_NAMES, navn); } 

Når vi har fått det nødvendige Klasse objekter, kan vi bruke Java-refleksjon for å lage forekomster av klasser og påkalle metoder.

6. Konklusjon

I denne artikkelen har vi lært to forskjellige tilnærminger for å få klassenavn fra en gitt JAR-fil.

De krukke kommando kan skrive ut klassenavnene. Det er ganske praktisk hvis vi trenger å sjekke om en JAR-fil inneholder en gitt klasse. Men hvis vi trenger å få klassenavnene fra et Java-program som kjører, JarFile og JarEntry kan hjelpe oss med å oppnå det.

Til slutt har vi også sett et eksempel på et Java-program for å laste klasser fra en JAR-fil ved kjøretid.

Som alltid er hele kildekoden til artikkelen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found