Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load Classes at runtime from a folder or JAR?

I am trying to make a Java tool that will scan the structure of a Java application and provide some meaningful information. To do this, I need to be able to scan all of the .class files from the project location (JAR/WAR or just a folder) and use reflection to read about their methods. This is proving to be near impossible.

I can find a lot of solutions based on URLClassloader that allow me to load specific classes from a directory/archive, but none that will allow me to load classes without having any information about the class name or package structure.

EDIT: I think I phrased this poorly. My issue is not that I can't get all of the class files, I can do that with recursion etc. and locate them properly. My issue is obtaining a Class object for each class file.

like image 278
Sam Stern Avatar asked Jun 13 '12 13:06

Sam Stern


People also ask

How do I load a JAR file?

Step 2: Copy the JAR files you wish to import under the lib folder. Step 3: Right-click on the Project name and select Properties. Step 4: Select Java Build Path and click the Add JARs button. Step 5: Select the JAR files copied under the lib folder in Step 2 and click OK.


1 Answers

The following code loads all classes from a JAR file. It does not need to know anything about the classes. The names of the classes are extracted from the JarEntry.

JarFile jarFile = new JarFile(pathToJar); Enumeration<JarEntry> 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);  } 

edit:

As suggested in the comments above, javassist would also be a possibility. Initialize a ClassPool somewhere before the while loop form the code above, and instead of loading the class with the class loader, you could create a CtClass object:

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

From the ctClass, you can get all methods, fields, nested classes, .... Take a look at the javassist api: https://jboss-javassist.github.io/javassist/html/index.html

like image 87
Apfelsaft Avatar answered Oct 11 '22 22:10

Apfelsaft