title: Dynamically load top-level class in a jar outside of classpath
body: <p><strong>UPDATE</strong> - All of the files in my project now declare the same package.  However, the jar I'm loading has to be outside of the classpath.  I've tried <code>child.loadClass(className)</code> and <code>Class.forName(className, false, child);</code>, but neither of them seem to be able to find it.</p>
  
  <p>I'm writing a program that wants to take plugins or modules in the form of jars and use them as if they were embedded in the classpath.</p>
  
  <p>I've seen a lot of similar questions on here and other sites, so I apologize for the duplication.  But, so far, every answer I've seen hasn't worked.  Am I doing something wrong?</p>
  
  <p>I have a folder full of jars.  I know that each jar has one top-level class that extends my Module class.  But, I don't know what those classes are called.</p>
  
  <p>First, I find all the files in the directory.  That works fine.  Then, for each file, I try to get an instance of its top-level class using the following code:</p>
  
  <p>(First it opens the jar as a zip to get the names of all the classes, then looks at the name to tell if it's a top-level class, then, if so, is supposed to load, instantiate and return it.)</p>
  
  <pre><code>private static Module jarLoader(String jar){
      try{
          ZipInputStream zip = new ZipInputStream(new FileInputStream(ModulesDir+"/"+jar));
          URL[] myJarFile = new URL[]{new URL("jar","","file:"+ModulesDir)};
          URLClassLoader child = new URLClassLoader (myJarFile , Main.class.getClassLoader());
          for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
              if (!entry.isDirectory() &amp;&amp; entry.getName().endsWith(".class")) {
                  // This ZipEntry represents a class. Now, what class does it represent?
                  String className = entry.getName().replace('/', '.'); // including ".class"
                  className = className.substring(0, className.length() - ".class".length());
  
  
                  String[] classNameParts = className.replace('$', ':').split(":");//I don't know why i have to do this, but it won't split on "$"
                  if(classNameParts.length == 1){
                      System.out.println("trying to load "+className);
                      Class classToLoad = Class.forName(className, false, child);
                      System.out.println("loaded class "+classToLoad.getName());
                      if(classToLoad.getSuperclass() == Module.class){
                          Module instance = (Module) classToLoad.newInstance();
                          return instance;
                      }
                  }
              }
          }
          zip.close();
      }catch (Exception e){
          e.printStackTrace();
      }
      return null;
  }
  </code></pre>
  
  <p>It gets as far as "trying to load ..." and it shows the name of the class as I would expect it to, and then throws a <code>java.lang.ClassNotFoundException</code>.</p>
  
  <p>Using the same name to load the class worked fine when i put it in a .java file in the source dir, but it wont get it from a jar.</p>
  
  <p>Am I doing something wrong? I suspect the class name may need some kind of prefix or suffix but I cant figure out what.</p>
  
  <p>Thanks for you help!</p>