Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Created August 1, 2013 06:44
Show Gist options
  • Save rednaxelafx/6128972 to your computer and use it in GitHub Desktop.
Save rednaxelafx/6128972 to your computer and use it in GitHub Desktop.
Dynamic proxy in Java loses generic type information. Demo with CLHSDB, run on JDK8b99/Mac OS X 10.7.5. This gist is to answer question from https://gist.github.com/kdlan/6128766
$ jps
78131 Jps
78118 Test
$ clhsdb
Password:
hsdb> verbose true
hsdb> attach 78118
Attaching to process 78118, please wait...
hsdb> jseval "t = jvm.threads[jvm.threads.length-1]"
Thread (address=0x00000007eaa852b8, name=main)
hsdb> jseval "f = t.frames[t.frames.length-1]"
Frame (method=Test.main(java.lang.String[]), bci=42, line=39)
hsdb> jseval "f.locals"
{proxyBean=Object 0x00000007eabc9d68, args=Object 0x00000007eabb7d08, rawBean=Object 0x00000007eabb9dd8}
hsdb> jseval "sa.objHeap.newOop(any2addr('0x00000007eabc9d68').addOffsetToAsOopHandle(0))"
sun.jvm.hotspot.oops.Instance@eabc9d68
hsdb> jseval "p = sa.objHeap.newOop(any2addr('0x00000007eabc9d68').addOffsetToAsOopHandle(0))"
sun.jvm.hotspot.oops.Instance@eabc9d68
hsdb> jseval "p.klass.name.asString()"
com/sun/proxy/$Proxy0
hsdb> jseval "pk = p.klass"
sun.jvm.hotspot.oops.InstanceKlass@0x00000007b9c60a50
hsdb> print 0x00000007b9c60a50
public final class com.sun.proxy.$Proxy0 @0x00000007b9c60a50
Super Class
public class java.lang.reflect.Proxy @0x00000007b9c4ad50
Interfaces
public abstract interface Test$TestService @0x00000007b9c60240
Fields
private static java.lang.reflect.Method m1; (offset = 104)
private static java.lang.reflect.Method m0; (offset = 108)
private static java.lang.reflect.Method m3; (offset = 112)
private static java.lang.reflect.Method m2; (offset = 116)
Methods
public void <init>(java.lang.reflect.InvocationHandler) @0x0000000104fc3b40;
static void <clinit>() @0x0000000104fc4100;
public final boolean equals(java.lang.Object) @0x0000000104fc3c30;
public final java.lang.String toString() @0x0000000104fc3ef0;
public final int hashCode() @0x0000000104fc3d20;
public final java.util.List list(java.util.List) @0x0000000104fc3e10;
Constant Pool
Constant Pool of [public final class com.sun.proxy.$Proxy0 @0x00000007b9c60a50] @0x0000000104fc36a0
hsdb> jseval "b = sa.objHeap.newOop(any2addr('0x00000007eabb9dd8').addOffsetToAsOopHandle(0))"
sun.jvm.hotspot.oops.Instance@eabb9dd8
hsdb> jseval "bk = b.klass"
sun.jvm.hotspot.oops.InstanceKlass@0x00000007b9c60440
hsdb> print 0x00000007b9c60440
public class Test$TestServiceImpl @0x00000007b9c60440
Super Class
public class java.lang.Object @0x00000007b9c00fc0
Interfaces
public abstract interface Test$TestService @0x00000007b9c60240
Methods
public void <init>() @0x0000000104fc2f20;
public java.util.List list(java.util.List) [signature (Ljava.util.List<Ljava.util.Map<Ljava.lang.String;Ljava.lang.Object;>;>;)Ljava.util.List<Ljava.util.Map<Ljava.lang.String;Ljava.lang.Object;>;>;] @0x0000000104fc3040;
Constant Pool
Constant Pool of [public class Test$TestServiceImpl @0x00000007b9c60440] @0x0000000104fc2d20
hsdb> print 0x0000000104fc3e10
public final java.util.List list(java.util.List) @0x0000000104fc3e10
Holder Class
public final class com.sun.proxy.$Proxy0 @0x00000007b9c60a50
Bytecode
bci bytecode
0 aload_0
1 getfield #16 [Field java.lang.reflect.InvocationHandler h] of public class java.lang.reflect.Proxy @0x00000007b9c4ad50
4 aload_0
5 getstatic #60 [Field java.lang.reflect.Method m3] of public final class com.sun.proxy.$Proxy0 @0x00000007b9c60a50
8 iconst_1
9 anewarray #22 [Class java.lang.Object]
12 dup
13 iconst_0
14 aload_1
15 aastore
16 invokeinterface #28 [Method java.lang.Object invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])]
21 checkcast #62 [Class java.util.List]
24 areturn
25 athrow
26 astore_2
27 new #42 [Class java.lang.reflect.UndeclaredThrowableException]
30 dup
31 aload_2
32 invokespecial #45 [Method void <init>(java.lang.Throwable)]
35 athrow
Exception Table
start bci end bci handler bci catch type
0 25 25 java.lang.Error
0 25 25 java.lang.RuntimeException
0 25 26 java.lang.Throwable
Constant Pool
Constant Pool of [public final class com.sun.proxy.$Proxy0 @0x00000007b9c60a50] @0x0000000104fc36a0
hsdb> print 0x0000000104fc3040
public java.util.List list(java.util.List) [signature (Ljava.util.List<Ljava.util.Map<Ljava.lang.String;Ljava.lang.Object;>;>;)Ljava.util.List<Ljava.util.Map<Ljava.lang.String;Ljava.lang.Object;>;>;] @0x0000000104fc3040
Holder Class
public class Test$TestServiceImpl @0x00000007b9c60440
Bytecode
line bci bytecode
16 0 aload_1
16 1 areturn
Constant Pool
Constant Pool of [public class Test$TestServiceImpl @0x00000007b9c60440] @0x0000000104fc2d20
hsdb>
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Test {
public interface TestService{
List<Map<String,Object>> list(List<Map<String,Object>> list);
}
public static class TestServiceImpl implements TestService {
public List<Map<String, Object>> list(List<Map<String, Object>> list) {
return list;
}
}
public static TestService proxy(TestService bean) {
return (TestService) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{TestService.class}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
}
static Type[] getGenericTypeParams(TestService bean) throws Exception{
Class<?> clazz = bean.getClass();
return clazz.getDeclaredMethod("list", List.class).getGenericParameterTypes();
}
public static void main(String[] args) throws Exception {
TestService rawBean = new TestServiceImpl();
TestService proxyBean = proxy(rawBean);
System.out.println(Arrays.toString(getGenericTypeParams(rawBean)));
System.out.println(Arrays.toString(getGenericTypeParams(proxyBean)));
System.in.read();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment