title: Java ClassLoader stops working when used in new Thread (Runnable)
body: <p>I'm developing an eclipse plugin. When the plugin is run (e.g. in a debugging instance of eclipse), it loads certain classes from all java-projects in the debugging workspace. Reflection is used for this purpose. To get a better idea of what I'm doing here is some code:</p>
  
  <pre><code>for (IPath outDir : _outputDirs)
  {
      IPath fullTestPackageDir = outDir.append(testPackageDir);
      File dir = fullTestPackageDir.toFile();
      if (dir.exists() &amp;&amp; dir.isDirectory())
      {
          for (File classFile : dir.listFiles())
          {
              String binaryClassName = packageName + "." + FileUtils.getNameWithoutExtension(classFile);
              Class&lt;ITest&gt; testClass = tryLoadClass(binaryClassName, ITest.class);
              if (testClass != null)
              {
                  testClasses.add(testClass);
              }
          }
      }
  }
  </code></pre>
  
  <p>Following is my implementation of <code>tryLoadClass</code> used above, as requested in the comments (not much magic at all). The _urlClassLoader is created from an array of <code>URL</code>s (output folders of java-projects in the debugging workspace) and has current thread's context ClassLoader as parent.</p>
  
  <pre><code>@SuppressWarnings("unchecked")
  private &lt;T&gt; Class&lt;T&gt; tryLoadClass(String binaryClassName, Class&lt;T&gt; baseType)
  {
      try
      {
          Class&lt;?&gt; testClass = _urlClassLoader.loadClass(binaryClassName);
  
          if (!baseType.isAssignableFrom(testClass))
              return null;
  
          return (Class&lt;T&gt;)testClass;
      }
      catch (ClassNotFoundException e)
      {
          System.err.println("class not found");
          return null;
      }
  }
  </code></pre>
  
  <p>Later, these classes are instantiated and a function (<code>run</code>) is called:</p>
  
  <pre><code>Class&lt;ITest&gt; testClass = testClasses.get(i);
  
  try
  {
      ITest test = testClass.getConstructor(IRuntime.class).newInstance(_runtime);
      test.run();
  }
  catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e)
  {
      e.printStackTrace();
  }
  </code></pre>
  
  <p>In the bundle of the plugin there are several utility classes, e.g. <code>MyUtil</code>, which are exported by the plugin, and can be referenced by the classes loaded above. Precisely, <code>MyUtil</code> is referenced in the <code>run</code> function.</p>
  
  <p>Everything works fine with the code above. But if I'm moving <code>test.run()</code> into another Thread, I get a ClassNotFoundException for <code>MyUtil</code>. Here's the code again (it is almost the same as above, only the 6th line is replaced). <code>ITest</code> inherits from <code>Runnable</code>:</p>
  
  <pre><code>Class&lt;ITest&gt; testClass = testClasses.get(i);
  
  try
  {
      ITest test = testClass.getConstructor(IRuntime.class).newInstance(_runtime);
      Thread thread = new Thread(test, "TestThread");
      thread.start();
  }
  catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e)
  {
      e.printStackTrace();
  }
  </code></pre>
  
  <p>I already tried a lots of things, like getting the current thread's <code>ContextClassLoader</code> and passing it to the new thread, but not luck. What I found out is that I can use the current thread's <code>ContextClassLoader</code> explicitly to load <code>MyUtil</code>, but only when it is used from within the original thread. If I pass that ClassLoader into the new thread, it stops working.</p>
  
  <p>I think my problem is that I have some wrong understanding of how ClassLoaders work...</p>
  
  <p>Here are some more details about the Exception:</p>
  
  <pre><code>Caused by: java.lang.ClassNotFoundException: de.my.company.MyPlugin
      at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
      at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
      ... 2 more
  </code></pre>
  
  <p>Because there has been a question about how "de.my.company.MyPlugin" is being loaded: it's just in the bundle/plugin, which is required by java projects in the debugging workspace, thus I think it's on the "base" classpath (don't know the right terminology here...)</p>
  
  <p>/edit:
  I just realized that I did not mention something that might be important: <code>test.run()</code> (as well as starting the new thread) is done in the context of an Eclipse <code>Job</code>. But I think I already counted this out: the problem remains the same when I remove the <code>Job</code>-context (issue the code directly from within the Handler of an Eclipse command). However, the problem does not exist, if the <code>ITest</code> implementation is instantiated normally (i.e. in the eclipse debugging instance; I tested it within a simple <code>main()</code> function).</p>
  
  <p>I think the problem is caused by the fact that my custom <code>_urlClassLoader</code> is used to load <code>ITest</code>. Because Java tries to load any referenced classes using the class-loader that loaded the container class in the very beginning (afaik), my _urlClassLoader would be used again. The _urlClassLoader alone, however, cannot load the requested classes (it only has the output folders of other java projects on its "classpath"). Instead, its parent must be used. If I understood everything right this should happen automatically, but it is exactly this part that doesn't work with the new thread anymore...</p>