If foo.Bar.Baz is a nested class in foo.Bar, then the argument of @MyAnnotation(foo.bar.Baz.class) could not be obtained. The test code is javassist.JvstTest4#testAnnArg().tags/rel_3_19_0_ga
@@ -591,6 +591,13 @@ public class SignatureAttribute extends AttributeInfo { | |||
sbuf.append(ts[i]); | |||
} | |||
} | |||
/** | |||
* Returns the type name in the JVM internal style. | |||
* For example, if the type is a nested class {@code foo.Bar.Baz}, | |||
* then {@code foo.Bar$Baz} is returned. | |||
*/ | |||
public String jvmTypeName() { return toString(); } | |||
} | |||
/** | |||
@@ -746,6 +753,34 @@ public class SignatureAttribute extends AttributeInfo { | |||
return sbuf.toString(); | |||
} | |||
/** | |||
* Returns the type name in the JVM internal style. | |||
* For example, if the type is a nested class {@code foo.Bar.Baz}, | |||
* then {@code foo.Bar$Baz} is returned. | |||
*/ | |||
public String jvmTypeName() { | |||
StringBuffer sbuf = new StringBuffer(); | |||
ClassType parent = getDeclaringClass(); | |||
if (parent != null) | |||
sbuf.append(parent.jvmTypeName()).append('$'); | |||
sbuf.append(name); | |||
if (arguments != null) { | |||
sbuf.append('<'); | |||
int n = arguments.length; | |||
for (int i = 0; i < n; i++) { | |||
if (i > 0) | |||
sbuf.append(", "); | |||
sbuf.append(arguments[i].toString()); | |||
} | |||
sbuf.append('>'); | |||
} | |||
return sbuf.toString(); | |||
} | |||
void encode(StringBuffer sb) { | |||
sb.append('L'); | |||
encode2(sb); |
@@ -101,7 +101,7 @@ public class ClassMemberValue extends MemberValue { | |||
public String getValue() { | |||
String v = cp.getUtf8Info(valueIndex); | |||
try { | |||
return SignatureAttribute.toTypeSignature(v).toString(); | |||
return SignatureAttribute.toTypeSignature(v).jvmTypeName(); | |||
} catch (BadBytecode e) { | |||
throw new RuntimeException(e); | |||
} | |||
@@ -121,7 +121,7 @@ public class ClassMemberValue extends MemberValue { | |||
* Obtains the string representation of this object. | |||
*/ | |||
public String toString() { | |||
return getValue() + ".class"; | |||
return getValue().replace('$', '.') + ".class"; | |||
} | |||
/** |
@@ -2,19 +2,25 @@ import javassist.*; | |||
public class Test { | |||
public static void main(String[] args) throws Exception { | |||
ClassPool cp = ClassPool.getDefault(); | |||
CtClass newClass = cp.makeClass("test4.TestDeadcode"); | |||
addDeadCode(newClass, "public void evaluate5(){ boolean b = !false; b = false && b; b = true && true;" | |||
+ " b = true || b; b = b || false; }"); | |||
if (args.length > 1) { | |||
new Test().bar(3); | |||
return; | |||
} | |||
newClass.debugWriteFile(); | |||
Class<?> cClass = newClass.toClass(); | |||
Object o = cClass.newInstance(); | |||
java.lang.reflect.Method m = cClass.getMethod("evaluate5"); | |||
m.invoke(o); | |||
} | |||
private static void addDeadCode(CtClass cc, String meth) throws Exception { | |||
CtMethod m = CtNewMethod.make(meth, cc); | |||
cc.addMethod(m); | |||
ClassPool cp = ClassPool.getDefault(); | |||
CtClass str = cp.get("java.lang.String"); | |||
CtClass cc = cp.get("Test"); | |||
cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_4); | |||
CtMethod m = cc.getDeclaredMethod("bar"); | |||
m.addLocalVariable("aVar", str); | |||
m.insertAfter(" dismiss( aVar );" , true); | |||
cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_7); | |||
m.insertBefore("aVar = initVar();"); | |||
cc.writeFile(); | |||
} | |||
public void bar(int i) { foo(i); } | |||
public void foo(int i) { System.out.println(i); } | |||
public String initVar() { return "init"; } | |||
public void dismiss(String s) { System.out.println(s); } | |||
} |
@@ -1030,4 +1030,12 @@ public class JvstTest4 extends JvstTestRoot { | |||
CtMethod m = CtNewMethod.make(meth, cc); | |||
cc.addMethod(m); | |||
} | |||
public void testAnnArg() throws Exception { | |||
CtClass cc = sloader.get("test4.AnnoArg"); | |||
CtMethod m = cc.getDeclaredMethod("foo"); | |||
test4.AnnoArg.AnnoArgAt a = (test4.AnnoArg.AnnoArgAt)m.getAnnotations()[0]; | |||
assertEquals("test4.AnnoArg$B", a.value().getName()); | |||
System.out.println(a.value().getName()); | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package test4; | |||
public class AnnoArg { | |||
public static @interface AnnoArgAt { | |||
Class<? extends AnnoArg.A> value(); | |||
} | |||
public static class A { | |||
int baz() { return 1; } | |||
} | |||
public static class B extends A { | |||
int baz() { return 2; } | |||
} | |||
@AnnoArgAt(B.class) | |||
public int foo(int i) { return i; } | |||
} |