import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;


public class Test {

	public Test() {}
	
	public static void test(Class testClass, long[] times) {
		long start = System.nanoTime();
		try {
			testClass.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		long time = System.nanoTime() - start;
		times[0] += time;
		
		start = System.nanoTime();
		new Test();
		time = System.nanoTime() - start;
		times[1] += time;
	}
	
	public static void main(String[] args) {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			BufferedInputStream bin = new BufferedInputStream(Test.class.getResourceAsStream("Test.class"));
			try {
				int r = bin.read();
				while(r != -1) {
					bos.write(r);
					r = bin.read();
				}
			} catch(IOException e) {
				e.printStackTrace();
				System.exit(1);
			}
			byte[] testClassBytes = bos.toByteArray();
			long[] times = new long[] { 0, 0 };
			long ntimes = 50000;
			for(long i = 0; i < ntimes; i++) {
				Class testClass1 = new URLClassLoader(new URL[] { Test.class.getResource("Test.class") }).loadClass("Test");
				Method testMethod = testClass1.getMethod("test", Class.class, long[].class);
				
				Class testClass2 = new JavaClassLoader().loadClassFromByteArray("Test", testClassBytes);
				testMethod.invoke(null, testClass2, times);
			}
			System.out.println("REFLECTION: " + times[0]);
			System.out.println("NEW: " + times[1]);
			System.out.println("% SLOWER: " + (times[0] * 100) / times[1]);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
