Como carregar classs em tempo de execução de uma pasta ou JAR?

Eu estou tentando fazer uma ferramenta Java que irá analisar a estrutura de um aplicativo Java e fornecer algumas informações significativas. Para fazer isso, eu preciso ser capaz de escanear todos os arquivos .class do local do projeto (JAR / WAR ou apenas uma pasta) e usar a reflection para ler sobre seus methods. Isso está provando ser quase impossível.

Eu posso encontrar muitas soluções baseadas em URLClassloader que me permitem carregar classs específicas de um diretório / arquivo, mas nenhuma que me permita carregar classs sem ter nenhuma informação sobre o nome da class ou estrutura de pacotes.

EDIT: Acho que expressei isso mal. Meu problema não é que eu não posso obter todos os arquivos de class, eu posso fazer isso com recursion etc e localizá-los corretamente. Meu problema é obter um object de class para cada arquivo de class.

O código a seguir carrega todas as classs de um arquivo JAR. Não precisa saber nada sobre as classs. Os nomes das classs são extraídos do JarEntry.

JarFile jarFile = new JarFile(pathToJar); Enumeration e = jarFile.entries(); URL[] urls = { new URL("jar:file:" + pathToJar+"!/") }; URLClassLoader cl = URLClassLoader.newInstance(urls); while (e.hasMoreElements()) { JarEntry je = e.nextElement(); if(je.isDirectory() || !je.getName().endsWith(".class")){ continue; } // -6 because of .class String className = je.getName().substring(0,je.getName().length()-6); className = className.replace('/', '.'); Class c = cl.loadClass(className); } 

editar:

Como sugerido nos comentários acima, o javassist também seria uma possibilidade. Inicialize um ClassPool em algum lugar antes do loop while formar o código acima e, em vez de carregar a class com o carregador de classs, você pode criar um object CtClass:

 ClassPool cp = ClassPool.getDefault(); ... CtClass ctClass = cp.get(className); 

A partir do ctClass, você pode obter todos os methods, campos, classs aninhadas, …. Dê uma olhada na API do javassist: https://jboss-javassist.github.io/javassist/html/index.html

Listar todas as classs dentro do arquivo jar.

 public static List getClasseNames(String jarName) { ArrayList classs = new ArrayList(); if (debug) System.out.println("Jar " + jarName ); try { JarInputStream jarFile = new JarInputStream(new FileInputStream( jarName)); JarEntry jarEntry; while (true) { jarEntry = jarFile.getNextJarEntry(); if (jarEntry == null) { break; } if (jarEntry.getName().endsWith(".class")) { if (debug) System.out.println("Found " + jarEntry.getName().replaceAll("/", "\\.")); classs.add(jarEntry.getName().replaceAll("/", "\\.")); } } } catch (Exception e) { e.printStackTrace(); } return classs; } 

Para fazer isso, preciso poder verificar todos os arquivos .class do local do projeto (JAR / WAR ou apenas uma pasta)

A digitalização de todos os arquivos em uma pasta é simples. Uma opção é chamar File.listFiles() no File que denota a pasta e, em seguida, iterar a matriz resultante. Para percorrer trees de pastas aninhadas, use recursion.

A varredura dos arquivos de um arquivo JAR pode ser feita usando a API JarFile … e você não precisa recursar para percorrer as “pastas” aninhadas.

Nenhum destes é particularmente complicado. Apenas leia o javadoc e inicie a codificação.