<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: bytecode code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Mon, 13 Oct 2008 18:35:42 GMT</pubDate>
    <description>DZone Snippets: bytecode code</description>
    <item>
      <title>Microbenchmark for Bridge vs reflection vs direct access</title>
      <link>http://snippets.dzone.com/posts/show/4806</link>
      <description>&lt;code&gt;import java.lang.reflect.Method;&lt;br /&gt;&lt;br /&gt;public class TimingTest {&lt;br /&gt;	public interface IFoo { public void foo(); }&lt;br /&gt;	public interface PubFoo { public void foo(); }&lt;br /&gt;	public static class Impl implements PubFoo { public void foo(){} }&lt;br /&gt;&lt;br /&gt;	static final int COUNT = 10000000;&lt;br /&gt;	public static void main(String[] args) throws Exception {&lt;br /&gt;		Impl impl = new Impl();&lt;br /&gt;		int count;&lt;br /&gt;&lt;br /&gt;		startTiming("Bridge (including BCEL)");&lt;br /&gt;		IFoo ifoo = Bridge.expose(impl, IFoo.class);&lt;br /&gt;		stopTiming();&lt;br /&gt;		startTiming("Bridge (BCEL loaded)");&lt;br /&gt;		Bridge.expose(impl, PubFoo.class);&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		System.out.println(COUNT+" virtual invocations, warm");&lt;br /&gt;&lt;br /&gt;		startTiming("Direct");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			impl.foo();&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		Method m = impl.getClass().getMethod("foo",new Class[0]);&lt;br /&gt;		startTiming("Reflection");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			m.invoke(impl);&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		startTiming("Bridge");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			ifoo.foo();&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;		System.out.println("1 virtual invocation on "+COUNT+" objects");&lt;br /&gt;&lt;br /&gt;		startTiming("Direct");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			impl.foo();&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		startTiming("Reflection");&lt;br /&gt;		Method tmpM = null;&lt;br /&gt;		Class[] no_args = new Class[0];&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++) {&lt;br /&gt;			if(tmpM == null || tmpM.getDeclaringClass() != impl.getClass())&lt;br /&gt;				tmpM = impl.getClass().getMethod("foo",no_args);&lt;br /&gt;			tmpM.invoke(impl);&lt;br /&gt;		}&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		startTiming("Bridge");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++) {&lt;br /&gt;			IFoo temp = Bridge.expose(impl, IFoo.class);&lt;br /&gt;		}&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		&lt;br /&gt;		System.out.println(COUNT+" interface invocations, warm");&lt;br /&gt;		PubFoo pfoo = (PubFoo)impl;&lt;br /&gt;		Method mi = impl.getClass().getInterfaces()[0].getMethod("foo", new Class[]{});&lt;br /&gt;		IFoo iifoo = Bridge.expose(impl, PubFoo.class, IFoo.class);&lt;br /&gt;&lt;br /&gt;		startTiming("Direct");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			pfoo.foo();&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		startTiming("Reflection");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			mi.invoke(impl);&lt;br /&gt;		stopTiming();&lt;br /&gt;&lt;br /&gt;		startTiming("Bridge");&lt;br /&gt;		for(int i=0; i&lt;COUNT; i++)&lt;br /&gt;			iifoo.foo();&lt;br /&gt;		stopTiming();&lt;br /&gt;		&lt;br /&gt;	}&lt;br /&gt;	static long timer;&lt;br /&gt;	static void startTiming(String task) {&lt;br /&gt;		System.out.printf("  * %12s - ", task);&lt;br /&gt;		System.out.flush();&lt;br /&gt;		timer = System.currentTimeMillis();&lt;br /&gt;	}&lt;br /&gt;	static void stopTiming() {&lt;br /&gt;		long time = System.currentTimeMillis() - timer;&lt;br /&gt;		System.out.println(time+" ms");&lt;br /&gt;	}&lt;br /&gt;}&lt;/code&gt;</description>
      <pubDate>Wed, 21 Nov 2007 11:51:06 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/4806</guid>
      <author>tunah (Sam McCall)</author>
    </item>
    <item>
      <title>Exposing an interface at runtime using a proxy class</title>
      <link>http://snippets.dzone.com/posts/show/4804</link>
      <description>Force an object expose an interface at runtime, through a generated proxy class. It must implement all required methods.&lt;br /&gt;Requires BCEL.&lt;br /&gt;&lt;br /&gt;UPDATED: does verification at bridge generation time.&lt;br /&gt;expose(Object, Class) will search for the correct public target type to use.&lt;br /&gt;UPDATED: performance hacks.&lt;br /&gt;&lt;br /&gt;Example usage:&lt;br /&gt;&lt;code&gt;public class BridgeTest {&lt;br /&gt;  public interface CharList {&lt;br /&gt;    public int length();&lt;br /&gt;    public char charAt(int i);&lt;br /&gt;  }&lt;br /&gt;  void print(CharList l) {&lt;br /&gt;    for(int i=0; i&lt;l.length(); i++)&lt;br /&gt;      System.out.print(l.charAt(i));&lt;br /&gt;  }&lt;br /&gt;  public static void main(String args[]) {&lt;br /&gt;    CharList list = Bridge.expose("Hello world\n", CharList.class);&lt;br /&gt;    print(list);&lt;br /&gt;  }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Bridge.java:&lt;br /&gt;&lt;code&gt;/* Make an object expose an interface at runtime */&lt;br /&gt;&lt;br /&gt;import org.apache.bcel.generic.*;&lt;br /&gt;import org.apache.bcel.Constants;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.util.*;&lt;br /&gt;&lt;br /&gt;public abstract class Bridge&lt;C,I&gt; {&lt;br /&gt;	protected C __target; // the implementation of the interface&lt;br /&gt;	private final void __init(Object target) { this.__target = (C)target; }&lt;br /&gt;&lt;br /&gt;	// cache already-generated bridges&lt;br /&gt;	private static HashMap&lt;Class, HashMap&lt;Class, Class&gt;&gt; cache &lt;br /&gt;		= new HashMap&lt;Class, HashMap&lt;Class, Class&gt;&gt;();&lt;br /&gt;	// allow injection of classes from byte arrays&lt;br /&gt;	private static InjectingClassLoader loader = new InjectingClassLoader();&lt;br /&gt;&lt;br /&gt;	private static final void cacheSet(Class key1, Class key2, Class value) {&lt;br /&gt;		HashMap&lt;Class,Class&gt; intermediate = cache.get(key1);&lt;br /&gt;		if(intermediate == null)&lt;br /&gt;			cache.put(key1, intermediate = new HashMap&lt;Class,Class&gt;());&lt;br /&gt;		intermediate.put(key2, value);&lt;br /&gt;	}&lt;br /&gt;	private static final Class cacheGet(Class key1, Class key2) {&lt;br /&gt;		HashMap&lt;Class,Class&gt; intermediate = cache.get(key1);&lt;br /&gt;		if(intermediate == null)&lt;br /&gt;			return null;&lt;br /&gt;		return intermediate.get(key2);&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	// returns [ [ifaceMethods...] [fromMethods...] ]&lt;br /&gt;	private static Method[][] getMapping(Class from, Class iface) throws NoSuchMethodException,IllegalAccessException {&lt;br /&gt;		if(!iface.isInterface())&lt;br /&gt;			throw new IllegalArgumentException(iface.getName()+" is not an interface");&lt;br /&gt;		if(!java.lang.reflect.Modifier.isPublic(from.getModifiers()))&lt;br /&gt;			throw new IllegalAccessException(from.getName()+" is not public");&lt;br /&gt;		java.lang.reflect.Method[][] map = new java.lang.reflect.Method[2][];&lt;br /&gt;		map[0] = iface.getMethods();&lt;br /&gt;		map[1] = new java.lang.reflect.Method[map[0].length];&lt;br /&gt;&lt;br /&gt;		for(int i=0;i&lt;map[0].length;i++) {&lt;br /&gt;			try {&lt;br /&gt;				Method match = from.getMethod(map[0][i].getName(), map[0][i].getParameterTypes());&lt;br /&gt;				if(!map[0][i].getReturnType().isAssignableFrom(match.getReturnType()))&lt;br /&gt;					throw new NoSuchMethodException("Return type "+match.getReturnType().getName()+&lt;br /&gt;						" of "+toString(match)+" is not compatible with return type "+&lt;br /&gt;						map[0][i].getReturnType().getName()+" of "+toString(map[0][i]));&lt;br /&gt;				map[1][i] = match;&lt;br /&gt;			} catch (NoSuchMethodException e) {&lt;br /&gt;				throw new NoSuchMethodException("Couldn't find "+toString(map[0][i])+" in "+&lt;br /&gt;					from.getName());&lt;br /&gt;			}			&lt;br /&gt;		}&lt;br /&gt;		return map;&lt;br /&gt;	}&lt;br /&gt;	private static String toString(Method m) {&lt;br /&gt;		StringBuffer sb = new StringBuffer(m.getDeclaringClass().getName());&lt;br /&gt;		sb.append(".").append(m.getName()).append("(");&lt;br /&gt;		boolean first=true;&lt;br /&gt;		for(Class c : m.getParameterTypes()) {&lt;br /&gt;			if(!first)&lt;br /&gt;				sb.append(", ");&lt;br /&gt;			sb.append(c.getName());	&lt;br /&gt;			first=false;&lt;br /&gt;		}&lt;br /&gt;		sb.append(")");&lt;br /&gt;		return sb.toString();&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	private static &lt;C,I&gt; Class&lt;? extends Bridge&lt;C,I&gt;&gt; create(Class&lt;C&gt; from, Class&lt;I&gt; iface) {&lt;br /&gt;		try {&lt;br /&gt;			Method[][] map = getMapping(from, iface);&lt;br /&gt;&lt;br /&gt;			String bridgeName = "Bridge_"+from.getSimpleName()+"_"+iface.getSimpleName();&lt;br /&gt;			// public class Bridge_Thing_Mungible extends Bridge&lt;Thing,Mungible&gt; implements Mungible&lt;br /&gt;			ClassGen cg = new ClassGen(&lt;br /&gt;				bridgeName,&lt;br /&gt;				Bridge.class.getName(), // superclass name&lt;br /&gt;				"&lt;generated&gt;", // source file name&lt;br /&gt;				Constants.ACC_PUBLIC | Constants.ACC_FINAL | Constants.ACC_SUPER, // flags&lt;br /&gt;				new String [] { iface.getName() } // interfaces&lt;br /&gt;			);&lt;br /&gt;&lt;br /&gt;			ConstantPoolGen cpg = cg.getConstantPool();&lt;br /&gt;			InstructionFactory factory = new InstructionFactory(cg, cpg);&lt;br /&gt;&lt;br /&gt;			ReferenceType targetType = (ReferenceType)Type.getType(from);&lt;br /&gt;&lt;br /&gt;			for(int i=0; i&lt;map[0].length; i++) {&lt;br /&gt;				Method imeth = map[0][i];&lt;br /&gt;				Method fmeth = map[1][i];&lt;br /&gt;&lt;br /&gt;				Type 	ireturnType = Type.getType(imeth.getReturnType()),&lt;br /&gt;					freturnType = Type.getType(fmeth.getReturnType());&lt;br /&gt;				Class[]	iargs = imeth.getParameterTypes(), &lt;br /&gt;					fargs = fmeth.getParameterTypes();&lt;br /&gt;				Type[] 	iargsT = new Type[iargs.length],&lt;br /&gt;					fargsT = new Type[fargs.length];&lt;br /&gt;				String[] argNames = new String[iargs.length];&lt;br /&gt;				for(int j=0; j&lt;iargs.length; j++) {&lt;br /&gt;					iargsT[j] = Type.getType(iargs[j]);&lt;br /&gt;					fargsT[j] = Type.getType(fargs[j]);&lt;br /&gt;					argNames[j] = "arg"+i;&lt;br /&gt;				}&lt;br /&gt;&lt;br /&gt;				InstructionList il = new InstructionList();&lt;br /&gt;				// public int munge(Object arg0, int arg1) {&lt;br /&gt;				MethodGen mg = new MethodGen(&lt;br /&gt;					Constants.ACC_PUBLIC,&lt;br /&gt;					ireturnType,&lt;br /&gt;					iargsT,&lt;br /&gt;					argNames,&lt;br /&gt;					imeth.getName(),&lt;br /&gt;					bridgeName,&lt;br /&gt;					il, cpg);&lt;br /&gt;&lt;br /&gt;				// (Thing)this.__target&lt;br /&gt;				il.append(new ALOAD(0));&lt;br /&gt;				il.append(factory.createFieldAccess(&lt;br /&gt;					Bridge.class.getName(), &lt;br /&gt;					"__target", &lt;br /&gt;					Type.OBJECT, &lt;br /&gt;					Constants.GETFIELD));&lt;br /&gt;				il.append(factory.createCheckCast(targetType));&lt;br /&gt;				&lt;br /&gt;				// .munge(arg0, arg1);&lt;br /&gt;				int position = 1;&lt;br /&gt;				for(int j=0;j&lt;iargs.length;j++) {&lt;br /&gt;					il.append(factory.createLoad(iargsT[j], position));&lt;br /&gt;					position += iargsT[j].getSize();&lt;br /&gt;				}&lt;br /&gt;				il.append(factory.createInvoke(&lt;br /&gt;					from.getName(), &lt;br /&gt;					fmeth.getName(), &lt;br /&gt;					freturnType, &lt;br /&gt;					fargsT, &lt;br /&gt;					from.isInterface() ? Constants.INVOKEINTERFACE : Constants.INVOKEVIRTUAL));&lt;br /&gt;&lt;br /&gt;				// return (last result, if any)&lt;br /&gt;				il.append(factory.createReturn(ireturnType));&lt;br /&gt;&lt;br /&gt;				mg.setMaxStack();&lt;br /&gt;				cg.addMethod(mg.getMethod());&lt;br /&gt;				il.dispose(); // Allow instruction handles to be reused&lt;br /&gt;			}&lt;br /&gt;&lt;br /&gt;			// public Bridge_Thing_Mungible() { super(); }&lt;br /&gt;			cg.addEmptyConstructor(Constants.ACC_PUBLIC);&lt;br /&gt;&lt;br /&gt;			try { cg.getJavaClass().dump("proxy.class"); } catch(Exception e) { throw new RuntimeException(e); }&lt;br /&gt;&lt;br /&gt;			byte[] classData = cg.getJavaClass().getBytes();&lt;br /&gt;			Class c = loader.load(cg.getClassName(), classData);&lt;br /&gt;			return (Class&lt;Bridge&lt;C,I&gt;&gt;)c;&lt;br /&gt;		} catch (IllegalAccessException e) { &lt;br /&gt;			throw new BridgeFailure(from, iface, e); &lt;br /&gt;		} catch (NoSuchMethodException e) { &lt;br /&gt;			throw new BridgeFailure(from, iface, e); &lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;	private static &lt;C,I&gt; Class&lt;? extends Bridge&lt;C,I&gt;&gt; get(Class&lt;C&gt; from, Class&lt;I&gt; iface) {&lt;br /&gt;//		Pair&lt;Class,Class&gt; key = new Pair&lt;Class,Class&gt;(from, iface);&lt;br /&gt;		Class&lt;? extends Bridge&lt;C,I&gt;&gt; bridgeClass = (Class&lt;? extends Bridge&lt;C,I&gt;&gt;)cacheGet(from, iface);&lt;br /&gt;		if(bridgeClass == null) {&lt;br /&gt;			bridgeClass = create(from, iface);&lt;br /&gt;			cacheSet(from, iface, bridgeClass);&lt;br /&gt;		}&lt;br /&gt;		return bridgeClass;&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	// Expose interface iface by creating a proxy. &lt;br /&gt;	// the type of target must be from, a subclass of from, or a class implementing from.&lt;br /&gt;	// from must be public, and must expose all methods in iface.&lt;br /&gt;	public static &lt;I&gt; I expose(Object target, Class from, Class&lt;I&gt; iface) {&lt;br /&gt;		try {&lt;br /&gt;			Class&lt;? extends Bridge&lt;?,I&gt;&gt; c = Bridge.get(from, iface);&lt;br /&gt;			Bridge&lt;?,I&gt; proxy = c.newInstance();&lt;br /&gt;			proxy.__init(target);&lt;br /&gt;			return (I)proxy;&lt;br /&gt;		} catch (InstantiationException e) {&lt;br /&gt;			throw new RuntimeException(e);&lt;br /&gt;		} catch (IllegalAccessException e) {&lt;br /&gt;			throw new RuntimeException(e);&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	// Expose interface iface by creating a proxy. &lt;br /&gt;	// Tries expose(target, target.getClass(), iface) first.&lt;br /&gt;	// then works up the class hierarchy. If doesn't find a public superclass &lt;br /&gt;	// that exposes all methods, it tries interfaces.&lt;br /&gt;	// if you know in advance the class or interface that exposes the needed methods,&lt;br /&gt;	// use expose(target, Class.forName("ExposingClass"), iface).&lt;br /&gt;	public static &lt;I&gt; I expose(Object target, Class&lt;I&gt; iface) {&lt;br /&gt;		Class tClass = target.getClass();&lt;br /&gt;&lt;br /&gt;		Class from = tClass;&lt;br /&gt;		do {			&lt;br /&gt;			try {&lt;br /&gt;				I result = expose(target, from, iface);&lt;br /&gt;				if(tClass != from) // if tClass == tFrom then get() sets the cache&lt;br /&gt;					cacheSet(tClass, iface, result.getClass());&lt;br /&gt;				return result;&lt;br /&gt;			} catch (BridgeFailure e) {&lt;br /&gt;				Throwable cause = e.getCause();&lt;br /&gt;				if(cause instanceof NoSuchMethodException) {&lt;br /&gt;					// have traced superclass up until the interface isn't satisfied.&lt;br /&gt;					// try interfaces and then give up.&lt;br /&gt;					// in the case of a private implementation of a public interface, &lt;br /&gt;					// this allows you to subset the interface.&lt;br /&gt;					Class[] targetIfaces = target.getClass().getInterfaces();&lt;br /&gt;					for(Class targetIface : targetIfaces) &lt;br /&gt;						try {&lt;br /&gt;							I result = expose(target, targetIface, iface);&lt;br /&gt;							cacheSet(tClass, iface, result.getClass()); // perf hack&lt;br /&gt;							return result;&lt;br /&gt;							// ignore, reported exception is that for class hierarchy.&lt;br /&gt;						} catch (BridgeFailure ex) {} &lt;br /&gt;					throw new BridgeFailure(target, iface, e);&lt;br /&gt;				} else if(!(cause instanceof IllegalAccessException))&lt;br /&gt;					throw e;&lt;br /&gt;			}&lt;br /&gt;			from = from.getSuperclass();&lt;br /&gt;		} while(from != null);&lt;br /&gt;		throw new RuntimeException("Object "+target+" ("+target.getClass().getName()+") has no public superclass");&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;class BridgeFailure extends RuntimeException {&lt;br /&gt;	public BridgeFailure(Class from, Class iface, Exception cause) {&lt;br /&gt;		super("Could not map class "+from.getName()+" to interface "+iface.getName());&lt;br /&gt;		initCause(cause);&lt;br /&gt;	}&lt;br /&gt;	public BridgeFailure(Object target, Class iface, Exception cause) {&lt;br /&gt;		super("Could not map first public supertype of " + target +&lt;br /&gt;			" (" + target.getClass().getName() + ")," +&lt;br /&gt;			" or any implemented interface, to interface " + iface.getName());&lt;br /&gt;		initCause(cause);&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;// ClassLoader implementation to let you load classes from byte arrays&lt;br /&gt;class InjectingClassLoader extends ClassLoader { &lt;br /&gt;	public InjectingClassLoader() {&lt;br /&gt;		super(InjectingClassLoader.class.getClassLoader());&lt;br /&gt;	}&lt;br /&gt;	public Class load(String name, byte[] buffer) {  &lt;br /&gt;		return defineClass(name, buffer, 0, buffer.length);  &lt;br /&gt;	}  &lt;br /&gt;}&lt;/code&gt;</description>
      <pubDate>Wed, 21 Nov 2007 02:49:41 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/4804</guid>
      <author>tunah (Sam McCall)</author>
    </item>
  </channel>
</rss>
