import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;

public class DefineClass {
  private static File findHello(File directory) {
    File[] files = directory.listFiles();
    for (File file: directory.listFiles()) {
      if (file.isFile()) {
        if (file.getName().equals("Hello.class")) {
          return file;
        }
      } else if (file.isDirectory()) {
        File result = findHello(file);
        if (result != null) {
          return result;
        }
      }
    }
    return null;
  }

  private static byte[] read(File file) throws IOException {
    byte[] bytes = new byte[(int) file.length()];
    FileInputStream in = new FileInputStream(file);
    try {
      if (in.read(bytes) != (int) file.length()) {
        throw new RuntimeException();
      }
      return bytes;
    } finally {
      in.close();
    }
  }

  public static void main(String[] args) throws Exception {
    byte[] bytes = read(findHello(new File(System.getProperty("user.dir"))));
    Class c = new MyClassLoader(DefineClass.class.getClassLoader()).defineClass
      ("Hello", bytes);
    c.getMethod("main", String[].class).invoke(null, (Object) new String[0]);
  }

  private static class MyClassLoader extends ClassLoader {
    public MyClassLoader(ClassLoader parent) {
      super(parent);
    }

    public Class defineClass(String name, byte[] bytes) {
      return super.defineClass(name, bytes, 0, bytes.length);
    }
  }
}

@@ -128,22 +128,35 @@
 ile find
-Hello(
+Class(String name, 
 File dir
@@ -313,22 +313,24 @@
 .equals(
-%22Hello
+name + %22
 .class%22)
@@ -431,22 +431,28 @@
 t = find
-Hello(
+Class(name, 
 file);%0A 
@@ -893,21 +893,22 @@
 %0A  p
-ublic
+rivate
  static 
 void
@@ -907,86 +907,167 @@
 tic 
-void main(String%5B%5D args) throws Exception %7B%0A    byte%5B%5D bytes = read(findHello(
+Class loadClass(String name) throws Exception %7B%0A    return new MyClassLoader(DefineClass.class.getClassLoader()).defineClass%0A      (name, read(findClass(name, 
 new 
@@ -1108,119 +1108,111 @@
 ))))
+)
 ;%0A  
-  Class c = new MyClassLoader(DefineClass.class.getClassLoader()).defineClass%0A      (%22Hello%22, bytes);
+%7D%0A%0A  private static void testStatic() throws Exception %7B%0A    loadClass(%22DefineClass$Hello%22)
 %0A    
-c
+  
 .get
@@ -1306,243 +1306,874 @@
 tic 
-class MyClassLoader extends ClassLoader %7B%0A    public MyClassLoader(ClassLoader parent) %7B%0A      super(parent);%0A    %7D%0A%0A    public Class defineClass(String name, byte%5B%5D bytes) %7B%0A      return super.defineClass(name, bytes, 0, bytes.length)
+void testDerived() throws Exception %7B%0A    System.out.println%0A      (String.valueOf%0A       (((Base) loadClass(%22DefineClass$Derived%22).newInstance()).zip()));%0A  %7D%0A%0A  public static void main(String%5B%5D args) throws Exception %7B%0A    testStatic();%0A    testDerived();%0A  %7D%0A%0A  private static class MyClassLoader extends ClassLoader %7B%0A    public MyClassLoader(ClassLoader parent) %7B%0A      super(parent);%0A    %7D%0A%0A    public Class defineClass(String name, byte%5B%5D bytes) %7B%0A      return super.defineClass(name, bytes, 0, bytes.length);%0A    %7D%0A  %7D%0A%0A  public static class Hello %7B%0A    public static void main(String%5B%5D args) %7B%0A      System.out.println(%22hello, world!%22);%0A    %7D%0A  %7D%0A%0A  public abstract static class Base %7B%0A    public int foo;%0A    %0A    public void bar() %7B %7D%0A%0A    public abstract int zip();%0A  %7D%0A%0A  public static class Derived extends Base %7B%0A    public int zip() %7B%0A      return 42
 ;%0A  

update DefineClass to exercise Class.newInstance