westeast
westeast

Reputation: 31

Get Methods From External Java .jar File

I am trying to retrieve a list of the methods within an external java .jar file. This external jar will not be included in my build path, I need to source the info entirely by referencing it in the code externally. The use case is to search for deprecated methods inside of .jars which have been loaded on an app I work with.

I have found a couple of solutions online and applied them, however they all expect something to either be native to java or on the buildpath. I will only be able to provide a file/filepath as an argument, and derive everything based on this.

My code for now is as below, I'm looking for solutions on how to use this the way I need to. Any help would be greatly appreciated!

public static void main(String[] args) throws IOException {

    Collection<Class<?>> classes = new ArrayList<Class<?>>();

    JarFile jar = new JarFile("C:\\app\\folder\\jar\\file.jar");

    for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
    {
        JarEntry entry = entries.nextElement();
        String file = entry.getName();

        if (file.endsWith(".class"))
        {

            String classname = file.replace('/','.').substring(0, file.length()-6);
        System.out.println(classname);

            try {
                Class<?> c = Class.forName(classname);
                classes.add(c);
            } catch (Throwable e) {
                System.out.println("WARNING: failed to instantiate " + classname + " from " + file);
            }
        }
    }
    for (Class<?> c: classes) 
        System.out.println(c);
}

Upvotes: 0

Views: 1670

Answers (1)

Roman Svystun
Roman Svystun

Reputation: 135

You can construct a URLClassLoader with your external jar file and that use it to load classed you discovered in the jar. When you have a class object you can call getMethods() and getDeclaredMethods() to get private, protected and public methods of a class.

public static void main(String[] args) throws Exception {
        Set<Class<?>> classes = new HashSet<>();

        URL jarUrl = new URL("file:///C:/app/folder/jar/file.jar");
        URLClassLoader loader = new URLClassLoader(new URL[]{jarUrl});
        JarFile jar = new JarFile("C:\\app\\folder\\jar\\file.jar");

        for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
        {
            JarEntry entry = entries.nextElement();
            String file = entry.getName();

            if (file.endsWith(".class"))
            {

                String classname =
                        file.replace('/', '.').substring(0, file.length() - 6).split("\\$")[0];
//                System.out.println(classname);

                try {
                    Class<?> c = loader.loadClass(classname);
                    classes.add(c);
                } catch (Throwable e) {
                    System.out.println("WARNING: failed to instantiate " + classname + " from " + file);
                }
            }
        }
        Map<String, List<Method>> collected =
                classes.stream().collect(Collectors.toMap(Class::getName, clz -> {
                    List<Method> methods = new ArrayList<>(Arrays.asList(clz.getDeclaredMethods()));
                    methods.addAll(Arrays.asList(clz.getMethods()));
                    return methods;
                }));

        collected.forEach((clz, methods) -> System.out.println("\n" + clz + "\n\n" + methods));
    }

Upvotes: 3

Related Questions