Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all of the Classes in the Classpath

How can I get list of all available classes in CLASSPATH at runtime?
In Eclipse IDE, you can do this by pressing Ctrl+Shift+T.
Is there any method in Java to get it done?

like image 588
arash Avatar asked Jul 11 '10 10:07

arash


People also ask

How do I get all classpath JARs?

In general, to include all of the JARs in a given directory, you can use the wildcard * (not *. jar ). The wildcard only matches JARs, not class files; to get all classes in a directory, just end the classpath entry at the directory name.

How can you directly access all classes in the package in Java?

Since Java enforces the most restrictive access, we have to explicitly declare packages using the export or open module declaration to get reflective access to the classes inside the module.

Can you find all classes in a package using reflection?

If there are classes that get generated, or delivered remotely, you will not be able to discover those classes. The normal method is instead to somewhere register the classes you need access to in a file, or reference them in a different class. Or just use convention when it comes to naming.


2 Answers

You can get all classpath roots by passing an empty String into ClassLoader#getResources().

Enumeration<URL> roots = classLoader.getResources(""); 

You can construct a File based on URL as follows:

File root = new File(url.getPath()); 

You can use File#listFiles() to get a list of all files in the given directory:

for (File file : root.listFiles()) {     // ... } 

You can use the standard java.io.File methods to check if it's a directory and/or to grab the filename.

if (file.isDirectory()) {     // Loop through its listFiles() recursively. } else {     String name = file.getName();     // Check if it's a .class file or a .jar file and handle accordingly. } 

Depending on the sole functional requirement, I guess that the Reflections library is much more exactly what you want.

like image 142
BalusC Avatar answered Oct 01 '22 03:10

BalusC


Here's what I wrote to do it. I'm sure it doesn't get everything if you're doing anything weird with the classpath, but it seems to work well for me. Note that it doesn't actually load the classes, it just returns their names. This is so that it won't load all classes into memory, and because some classes in my company's codebase were causing initialization errors if loaded at the wrong time...

public interface Visitor<T> {     /**      * @return {@code true} if the algorithm should visit more results,      * {@code false} if it should terminate now.      */     public boolean visit(T t); }  public class ClassFinder {     public static void findClasses(Visitor<String> visitor) {         String classpath = System.getProperty("java.class.path");         String[] paths = classpath.split(System.getProperty("path.separator"));          String javaHome = System.getProperty("java.home");         File file = new File(javaHome + File.separator + "lib");         if (file.exists()) {             findClasses(file, file, true, visitor);         }          for (String path : paths) {             file = new File(path);             if (file.exists()) {                 findClasses(file, file, false, visitor);             }         }     }      private static boolean findClasses(File root, File file, boolean includeJars, Visitor<String> visitor) {         if (file.isDirectory()) {             for (File child : file.listFiles()) {                 if (!findClasses(root, child, includeJars, visitor)) {                     return false;                 }             }         } else {             if (file.getName().toLowerCase().endsWith(".jar") && includeJars) {                 JarFile jar = null;                 try {                     jar = new JarFile(file);                 } catch (Exception ex) {                  }                 if (jar != null) {                     Enumeration<JarEntry> entries = jar.entries();                     while (entries.hasMoreElements()) {                         JarEntry entry = entries.nextElement();                         String name = entry.getName();                         int extIndex = name.lastIndexOf(".class");                         if (extIndex > 0) {                             if (!visitor.visit(name.substring(0, extIndex).replace("/", "."))) {                                 return false;                             }                         }                     }                 }             }             else if (file.getName().toLowerCase().endsWith(".class")) {                 if (!visitor.visit(createClassName(root, file))) {                     return false;                 }             }         }          return true;     }      private static String createClassName(File root, File file) {         StringBuffer sb = new StringBuffer();         String fileName = file.getName();         sb.append(fileName.substring(0, fileName.lastIndexOf(".class")));         file = file.getParentFile();         while (file != null && !file.equals(root)) {             sb.insert(0, '.').insert(0, file.getName());             file = file.getParentFile();         }         return sb.toString();     } } 

To use it:

ClassFinder.findClasses(new Visitor<String>() {     @Override     public boolean visit(String clazz) {         System.out.println(clazz)         return true; // return false if you don't want to see any more classes     } }); 
like image 32
Andy Avatar answered Oct 01 '22 03:10

Andy