2

I have been trying to figure out how to dynamically load classes from a jar file during runtime, knowing the name of the package to load them from. I have tried this: How to get all classes names in a package? It didnt work, I later realized it was for programs outside of jar files. I also took this snippet of code from another question, which I like a lot more:

URL[] urls = ....
URLClassLoader loader = new URLClassLoader(urls);
Class<?> cls = loader.loadClass("com.example.core.Main");
Module module = (Module) cls.newInstance();

But I don't see a way to load all classes in a defined package, like

Class<?>[] cls = loader.loadPackage("com.example.core");

How is this best solved? I have researched quite a bit and thought I was going at it the wrong way perhaps. Ultimately I just want to load all the classes in a package, without knowing anything but the package name, for an easier "Drop the class in" editing method.

Community
  • 1
  • 1
  • 1
    Why do you want to blindly load all classes in a particular package? You can't use them unless you know the fully-qualified class name anyway. – Jeffrey Mixon Nov 02 '14 at 17:03
  • I have another class which loads them as objects, stores the object in a list with an assigned ID, and they are used as "Definitions" rather than actual classes that execute code. EDIT: they also all extend the same class, which is why they are useful to me. – Mad3ngineer Nov 02 '14 at 17:11
  • "...rather than actual classes that execute code". If you aren't going to use a Class to execute code, you don't need a Class. There is almost certainly a better way to accomplish your desired effect. – Jeffrey Mixon Nov 02 '14 at 17:23
  • I am trying to use these classes as definitions for objects, like blocks, and I am not sure what would be a better way to solve this. How would you solve this problem? I have definately seen a lot of problems with this method, which I have found solutions for, but it still seems arbitrary, and wierd, like you said. I am probably just not experienced enough with java to see an easier solution, so would you give me a hint on which way to take this? – Mad3ngineer Nov 02 '14 at 17:26
  • It's difficult to say without a more detailed explanation of what you are trying to accomplish exactly. SO also isn't really suited for questions on advice or opinion. However, there is a solution to your question and in the spirit of SO I will provide it to you despite my... moral misgivings. ^_^ – Jeffrey Mixon Nov 02 '14 at 18:01

1 Answers1

0

This is technically feasible as follows:

private List<Class<?>> loadClassesInPackage(String packageName) {

    ClassLoader loader = getClassLoader();
    List<Class<?>> list = new ArrayList<Class<?>>();
    // com\.package\.subpackage(?!.*\$).*
    String regex = Pattern.quote(packageName) + "(?!.*\\$).*";

    try {
        DexFile df = new DexFile(getPackageCodePath());
        for (Enumeration<String> e = df.entries(); e.hasMoreElements(); ) {
            String s = e.nextElement();

            if (s.matches(regex)) {
                Log.d(TAG, "match: " + s);

                list.add(loader.loadClass(s));
            }

        }
    } catch (Exception e) {
        Log.w(TAG, "exception while building class list", e);
    }

    return list;
}

It will exclude inner/anonymous classes as it is. Also, there are plenty of caveats, such as loading classes without default constructors, abstract classes, etc. This should work for any class that exists in your app's APK, including library references.

Jeffrey Mixon
  • 12,846
  • 4
  • 32
  • 55