title: ClassNotFoundException when using custom ClassLoader to replace classes
body: <p>I'm using a library that loads some classes using Class#forName, but I need to change the implementation of some classes it loads. So I wrote a custom ClassLoader to replace the classes, but when invoking Class#forName it throws ClassNotFoundException even though the ClassLoader returned a Class object when requested.</p>
  <p>Is that because the name of the classes mismatch? Is there a workaround while still using Class#forName?</p>
  <p>I'm not able to reuse the package and name of the original class in the new one, otherwise I would've done that in compile time. But both classes extend the same class and only the interface of the super class is used throughout the code, so no incompatibility between them.</p>
  <h2>Example</h2>
  <h4>REPL</h4>
  <p><a href="https://replit.com/@t0rr3sp3dr0/Replace-Class-with-Custom-ClassLoader?v=1" rel="nofollow noreferrer">https://replit.com/@t0rr3sp3dr0/Replace-Class-with-Custom-ClassLoader?v=1</a></p>
  <h4>Source</h4>
  <pre class="lang-java prettyprint-override"><code>public class Main {
      public static void main(String[] args) throws Throwable {
          ClassLoader cl = new CL(Main.class.getClassLoader());
  
          Class&lt;?&gt; clazzA = Class.forName(&quot;A&quot;, true, cl);
          System.out.println(clazzA);
  
          Class&lt;?&gt; clazzB = Class.forName(&quot;B&quot;, true, cl);
          System.out.println(clazzB);
  
          Class&lt;?&gt; clazzC = Class.forName(&quot;C&quot;, true, cl);
          System.out.println(clazzC);
      }
  }
  </code></pre>
  <pre class="lang-java prettyprint-override"><code>public class CL extends ClassLoader {
      public CL(final ClassLoader parent) {
          super(parent);
      }
  
      @Override
      public Class&lt;?&gt; loadClass(final String name) throws ClassNotFoundException {
          System.out.printf(&quot;name: %s%n&quot;, name);
  
          switch (name) {
              case &quot;B&quot;, &quot;C&quot;:
                  System.out.println(&quot;case: B or C&quot;);
                  return B.class;
  
              default:
                  System.out.println(&quot;case: default&quot;);
                  return super.loadClass(name);
          }
      }
  }
  </code></pre>
  <pre class="lang-java prettyprint-override"><code>public class A {
      public int i;
  }
  </code></pre>
  <pre class="lang-java prettyprint-override"><code>public class B {
      public double d;
  }
  </code></pre>
  <h4>Output</h4>
  <pre><code>name: A
  case: default
  class A
  name: B
  case: B or C
  class B
  name: C
  case: B or C
  Exception in thread &quot;main&quot; java.lang.ClassNotFoundException: C
      at java.base/java.lang.Class.forName0(Native Method)
      at java.base/java.lang.Class.forName(Class.java:467)
      at Main.main(Main.java:8)
  </code></pre>