0

I have a Jar in java which is containing 2 classes and 1 Interface. How can i get the interface and class names from the jar. Currently I am able to get the class names, but not the interface name.

   List jClasses = getClasseNames("D://Test.jar");

            System.out.println(jClasses.size());

            for (int i = 0; i < jClasses.size(); i++) {

                System.out.println("Print Classes ::" + jClasses.get(i));

                if(( null != jClasses.getClass().getInterfaces()[i])) {
                    System.out.println(jClasses.getClass().getInterfaces()[i]);
                } else {
                    System.out.println("No connection");
                }
             }

   public static List getClasseNames(String jarName) {
        ArrayList classes = new ArrayList();

        try {
            JarInputStream jarFile = new JarInputStream(new FileInputStream(
                    jarName));
            JarEntry jarEntry;

            while (true) {
                jarEntry = jarFile.getNextJarEntry();
                if (jarEntry == null) {
                    break;
                }
                if (jarEntry.getName().endsWith(".class")) {

                    classes.add(jarEntry.getName().replaceAll("/", "\\."));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classes;
    }

output :

Print Classes ::com.java.testclient.PTest1.class
interface java.util.List
 ====== 
Print Classes ::com.java.testclient.ClassSpy.class
interface java.util.RandomAccess
 ====== 
Print Classes ::com.java.testclient.myInt.class
interface java.lang.Cloneable
 ====== 
Print Classes ::com.java.testclient.PTest.class
interface java.io.Serializable

Please suggest.

4
  • What is getClasseNames and this jClasses.getClass().getInterfaces()[i] is suspicious, jClasses.get(i).getClass().getInterfaces() maybe Commented Dec 26, 2016 at 16:52
  • getClasseNames is actually included in the posted code. Commented Dec 26, 2016 at 16:56
  • @lexicore it wasn't before :p Commented Dec 26, 2016 at 16:58
  • 1
    You should really avoid using raw types. That would auto-document your code. jClasses is a List<String>. Calling getClass() on it returns List.class, and does nothing with the actual class names in the list. You would need to use a ClassLoader, that would load classes from the jar by name (and hope they don't have dependencies from another jar), and then check if the loaded class is a regular class or an interface. Or you would need to actually analyze the bytecode of the entries of the jar file to decide if the class is a regular class or an interface. Commented Dec 26, 2016 at 17:01

1 Answer 1

2

You can use this class:

package io.github.gabrielbb.java.utilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

/**
 * @author Gabriel Basilio Brito
 * @since 12/26/2016
 * @version 1.1
 */
public class ClassesAndInterfacesFromJar {

    public static List<Class> getJarClasses(String jarPath) throws IOException, ClassNotFoundException {
        File jarFile = new File(jarPath);
        return getJarClasses(jarFile);
    }

    public static List<Class> getJarClasses(File jar) throws IOException, ClassNotFoundException {
        ArrayList<Class> classes = new ArrayList();
        JarInputStream jarInputStream = null;
        URLClassLoader cl;

        try {
            cl = URLClassLoader.newInstance(new URL[]{new URL("jar:file:" + jar + "!/")}); // To load classes inside the jar, after getting their names

            jarInputStream = new JarInputStream(new FileInputStream(
                    jar)); // Getting a JarInputStream to iterate through the Jar files 

            JarEntry jarEntry = jarInputStream.getNextJarEntry();

            while (jarEntry != null) {
                if (jarEntry.getName().endsWith(".class")) { // Avoiding non ".class" files
                    String className = jarEntry.getName().replaceAll("/", "\\."); // The ClassLoader works with "." instead of "/"
                    className = className.substring(0, jarEntry.getName().length() - 6);  // Removing ".class" from the string
                    Class clazz = cl.loadClass(className); // Loading the class by its name
                    classes.add(clazz);
                }

                jarEntry = jarInputStream.getNextJarEntry(); // Next File
            }
        } finally {
            if (jarInputStream != null) {
                jarInputStream.close(); // Closes the FileInputStream
            }
        }
        return classes;
    }

    // Main Method for testing purposes
    public static void main(String[] args) {
        try {
            String jarPath = "C://Test.jar";
            List<Class> classes = getJarClasses(jarPath);

            for (Class c : classes) {
                // Here we can use the "isInterface" method to differentiate an Interface from a Class
                System.out.println(c.isInterface() ? "Interface: " + c.getName() : "Class: " + c.getName());
            }
        } catch (Exception ex) {
            System.err.println(ex);
        }
    }

It can be found at:

https://github.com/GabrielBB/Java-Utilities/blob/master/ClassesAndInterfacesFromJar.java

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Gabriel. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.