Obtenir les noms des classes dans un fichier JAR

1. Vue d'ensemble

La plupart des bibliothèques Java sont disponibles sous forme de fichiers JAR. Dans ce didacticiel, nous allons expliquer comment obtenir les noms de classes dans un fichier JAR donné à partir de la ligne de commande et d'un programme Java.

Ensuite, nous examinerons un exemple de programme Java de chargement des classes à partir d'un fichier JAR donné au moment de l'exécution.

2. Exemple de fichier JAR

Dans ce didacticiel, nous prendrons le fichier stripe-0.0.1-SNAPSHOT.jar comme exemple pour expliquer comment obtenir les noms de classe dans le fichier JAR:

3. Utilisation de la commande jar

JDK est livré avec une commande jar . Nous pouvons utiliser cette commande avec les options t et f pour lister le contenu d'un fichier JAR :

$ jar tf stripe-0.0.1-SNAPSHOT.jar META-INF/ META-INF/MANIFEST.MF ... templates/result.html templates/checkout.html application.properties com/baeldung/stripe/StripeApplication.class com/baeldung/stripe/ChargeRequest.class com/baeldung/stripe/StripeService.class com/baeldung/stripe/ChargeRequest$Currency.class ...

Puisque nous ne sommes intéressés que par les fichiers * .class de l'archive, nous pouvons filtrer la sortie en utilisant la commande grep :

$ 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 com/baeldung/stripe/CheckoutController.class

Cela nous donne une liste des fichiers de classe dans le fichier JAR.

4. Obtention des noms de classe d'un fichier JAR en Java

L'utilisation de la commande jar pour imprimer les noms de classe à partir d'un fichier JAR est assez simple. Cependant, nous voulons parfois charger certaines classes à partir d'un fichier JAR dans notre programme Java. Dans ce cas, la sortie de ligne de commande n'est pas suffisante.

Pour atteindre notre objectif, nous devons analyser le fichier JAR à partir d'un programme Java et obtenir les noms de classe.

Voyons comment extraire les noms de classe de notre exemple de fichier JAR à l'aide des classes JarFile et JarEntry :

public static Set getClassNamesFromJarFile(File givenFile) throws IOException { Set classNames = new HashSet(); try (JarFile jarFile = new JarFile(givenFile)) { Enumeration e = jarFile.entries(); while (e.hasMoreElements()) { JarEntry jarEntry = e.nextElement(); if (jarEntry.getName().endsWith(".class")) { String className = jarEntry.getName() .replace("/", ".") .replace(".class", ""); classNames.add(className); } } return classNames; } } 

Maintenant, regardons de plus près le code de la méthode ci-dessus et comprenons comment cela fonctionne:

  • try (JarFile jarFile = new JarFile (givenFile)) - Ici, nous avons utilisé une instruction try-with-resources pour obtenir le jarFile à partir de l' objet File donné
  • if (jarEntry.getName (). endsWith (“. class”)) {…} - Nous prenons chaque classe jarEntry , et changeons le chemin du fichier de classe dans le nom de classe qualifié, par exemple changez “package1 / package2 / SomeType. class » dans « package1.package2.SomeType »

Vérifions si la méthode peut extraire les noms de classe de notre exemple de fichier JAR via une méthode de test unitaire:

private static final String JAR_PATH = "example-jar/stripe-0.0.1-SNAPSHOT.jar"; private static final Set 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 public void givenJarFilePath_whenLoadClassNames_thenGetClassNames() throws IOException, URISyntaxException { File jarFile = new File( Objects.requireNonNull(getClass().getClassLoader().getResource(JAR_PATH)).toURI()); Set classNames = GetClassNamesFromJar.getClassNamesFromJarFile(jarFile); Assert.assertEquals(EXPECTED_CLASS_NAMES, classNames); } 

5. Récupération de classes à partir d'un fichier JAR en Java

Nous avons vu comment obtenir les noms de classe à partir d'un fichier JAR. Parfois, nous voulons charger dynamiquement certaines classes à partir d'un fichier JAR au moment de l'exécution.

Dans ce cas, nous pouvons d'abord obtenir les noms de classe à partir du fichier JAR donné en utilisant notre méthode getClassNamesFromJarFile .

Ensuite, nous pouvons créer un ClassLoader pour charger les classes requises par nom:

public static Set getClassesFromJarFile(File jarFile) throws IOException, ClassNotFoundException { Set classNames = getClassNamesFromJarFile(jarFile); Set classes = new HashSet(classNames.size()); try (URLClassLoader cl = URLClassLoader.newInstance( new URL[] { new URL("jar:file:" + jarFile + "!/") })) { for (String name : classNames) { Class clazz = cl.loadClass(name); // Load the class by its name classes.add(clazz); } } return classes; }

Dans la méthode ci-dessus, nous avons créé un objet URLClassLoader pour charger les classes. La mise en œuvre est assez simple.

Cependant, cela vaut probablement la peine d'expliquer un peu la syntaxe de l'URL JAR. Une URL JAR valide contient trois parties: « jar: + [l'emplacement du fichier JAR] + ! /».

Le « ! / » De fin indique que l'URL JAR fait référence à un fichier JAR entier. Voyons quelques exemples d'URL JAR:

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

Dans notre méthode getClassesFromJarFile , le fichier JAR est situé sur le système de fichiers local, par conséquent, le préfixe de l'URL est « file: ».

Maintenant, écrivons une méthode de test pour vérifier si notre méthode peut obtenir tous les objets Class attendus :

@Test public void givenJarFilePath_whenLoadClass_thenGetClassObjects() throws IOException, ClassNotFoundException, URISyntaxException { File jarFile = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAR_PATH)).toURI()); Set classes = GetClassNamesFromJar.getClassesFromJarFile(jarFile); Set names = classes.stream().map(Class::getName).collect(Collectors.toSet()); Assert.assertEquals(EXPECTED_CLASS_NAMES, names); } 

Une fois que nous avons les objets Class requis , nous pouvons utiliser la réflexion Java pour créer des instances de classes et appeler des méthodes.

6. Conclusion

Dans cet article, nous avons appris deux approches différentes pour obtenir des noms de classe à partir d'un fichier JAR donné.

La commande jar peut imprimer les noms de classe. C'est très pratique si nous devons vérifier si un fichier JAR contient une classe donnée. Cependant, si nous avons besoin d'obtenir les noms de classe à partir d'un programme Java en cours d'exécution, JarFile et JarEntry peuvent nous aider à y parvenir.

Enfin, nous avons également vu un exemple de programme Java pour charger des classes à partir d'un fichier JAR au moment de l'exécution.

Comme toujours, le code source complet de l'article est disponible à l'adresse over sur GitHub.