diff options
author | chibash <chiba@javassist.org> | 2016-07-30 23:06:05 +0900 |
---|---|---|
committer | chibash <chiba@javassist.org> | 2016-07-30 23:06:05 +0900 |
commit | 2321430bd34e0e576435e2f16b3736f5ce7e2053 (patch) | |
tree | c01fd6094bbc2381fb3905efc343560deab0fd57 | |
parent | 79785b83f263d90135dbcc5744deb44b27ae3665 (diff) | |
parent | f795fcb1717fdde3e0c510b218b04abb55081202 (diff) | |
download | javassist-2321430bd34e0e576435e2f16b3736f5ce7e2053.tar.gz javassist-2321430bd34e0e576435e2f16b3736f5ce7e2053.zip |
Merge branch 'master' of github.com:jboss-javassist/javassist into test/java9-jigsaw
-rw-r--r-- | Readme.html | 4 | ||||
-rw-r--r-- | build.xml | 8 | ||||
-rw-r--r-- | javassist.jar | bin | 721634 -> 0 bytes | |||
-rw-r--r-- | src/main/javassist/bytecode/stackmap/TypeData.java | 329 | ||||
-rw-r--r-- | src/main/javassist/bytecode/stackmap/TypeTag.java | 10 | ||||
-rw-r--r-- | src/main/javassist/tools/Callback.java | 10 | ||||
-rw-r--r-- | src/main/javassist/util/proxy/ProxyFactory.java | 19 | ||||
-rw-r--r-- | src/test/Test.java | 67 | ||||
-rw-r--r-- | src/test/javassist/JvstTest.java | 2 | ||||
-rw-r--r-- | src/test/javassist/JvstTest2.java | 8 | ||||
-rw-r--r-- | src/test/javassist/JvstTest5.java | 15 | ||||
-rw-r--r-- | src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java | 6 | ||||
-rw-r--r-- | src/test/test/javassist/proxy/ProxySimpleTest.java | 59 | ||||
-rw-r--r-- | src/test/test5/StackmapWithArray83.java | 38 | ||||
-rw-r--r-- | src/test/testproxy/ProxyFactoryPerformanceTest.java | 2 | ||||
-rw-r--r-- | src/test/testproxy/ProxyTester.java | 46 |
16 files changed, 472 insertions, 151 deletions
diff --git a/Readme.html b/Readme.html index 7290c099..c80abd21 100644 --- a/Readme.html +++ b/Readme.html @@ -284,6 +284,10 @@ see javassist.Dump. <p>-version 3.21 <ul> <li>JIRA JASSIST-244, 245, 248, 250, 255, 256, 259, 262. +<li><code>javassist.tools.Callback</code> was modified to be Java 1.4 compatible. +The parameter type of <code>Callback#result()</code> was changed. +<li>The algorithm for generating a stack-map table was modified to fix github issue #83. +<li>A bug of ProxyFactory related to default methods was fixed. It is github issue #45. </ul> </p> @@ -6,7 +6,7 @@ <project name="javassist" default="jar" basedir="."> - <property name="dist-version" value="javassist-3.20.0-GA"/> + <property name="dist-version" value="javassist-3.21.0-GA"/> <property environment="env"/> <property name="target.jar" value="javassist.jar"/> @@ -64,6 +64,7 @@ debug="on" deprecation="on" optimize="off" + includeantruntime="true" includes="**"> <classpath refid="classpath"/> </javac> @@ -77,6 +78,7 @@ source="1.6" target="1.6" optimize="off" + includeantruntime="true" includes="**"> <classpath refid="classpath"/> </javac> @@ -88,6 +90,7 @@ debug="on" deprecation="on" optimize="off" + includeantruntime="false" includes="**"> <classpath refid="test.compile.classpath"/> <compilerarg value="-parameters" /> @@ -205,8 +208,9 @@ Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.</i>]]></bottom> </target> <target name="clean"> - <delete dir="build"/> <delete dir="html"/> + <delete dir="${test.run.dir}" /> + <delete dir="${build.dir}"/> <delete file="${target.jar}"/> <delete file="${dist-version}.zip"/> </target> diff --git a/javassist.jar b/javassist.jar Binary files differdeleted file mode 100644 index bcc617c6..00000000 --- a/javassist.jar +++ /dev/null diff --git a/src/main/javassist/bytecode/stackmap/TypeData.java b/src/main/javassist/bytecode/stackmap/TypeData.java index b83c9f69..206fd52a 100644 --- a/src/main/javassist/bytecode/stackmap/TypeData.java +++ b/src/main/javassist/bytecode/stackmap/TypeData.java @@ -78,7 +78,17 @@ public abstract class TypeData { public abstract String getName(); public abstract void setType(String s, ClassPool cp) throws BadBytecode; - // depth-first search + /** + * @param dim array dimension. It may be negative. + */ + public abstract TypeData getArrayType(int dim) throws NotFoundException; + + /** + * Depth-first search by Tarjan's algorithm + * + * @param order a node stack in the order in which nodes are visited. + * @param index the index used by the algorithm. + */ public int dfs(ArrayList order, int index, ClassPool cp) throws NotFoundException { @@ -89,32 +99,42 @@ public abstract class TypeData { * Returns this if it is a TypeVar or a TypeVar that this * type depends on. Otherwise, this method returns null. * It is used by dfs(). + * + * @param dim dimension */ - protected TypeVar toTypeVar() { return null; } + protected TypeVar toTypeVar(int dim) { return null; } // see UninitTypeVar and UninitData public void constructorCalled(int offset) {} + public String toString() { + return super.toString() + "(" + toString2(new HashSet()) + ")"; + } + + abstract String toString2(HashSet set); + /** * Primitive types. */ protected static class BasicType extends TypeData { private String name; private int typeTag; + private char decodedName; - public BasicType(String type, int tag) { + public BasicType(String type, int tag, char decoded) { name = type; typeTag = tag; + decodedName = decoded; } public int getTypeTag() { return typeTag; } public int getTypeData(ConstPool cp) { return 0; } public TypeData join() { - if (this == TypeTag.TOP) - return this; - else - return super.join(); + if (this == TypeTag.TOP) + return this; + else + return super.join(); } public BasicType isBasicType() { return this; } @@ -130,11 +150,33 @@ public abstract class TypeData { return name; } + public char getDecodedName() { return decodedName; } + public void setType(String s, ClassPool cp) throws BadBytecode { throw new BadBytecode("conflict: " + name + " and " + s); } - public String toString() { return name; } + /** + * @param dim array dimension. It may be negative. + */ + public TypeData getArrayType(int dim) throws NotFoundException { + if (this == TypeTag.TOP) + return this; + else if (dim < 0) + throw new NotFoundException("no element type: " + name); + else if (dim == 0) + return this; + else { + char[] name = new char[dim + 1]; + for (int i = 0; i < dim; i++) + name[i] = '['; + + name[dim] = decodedName; + return new ClassName(new String(name)); + } + } + + String toString2(HashSet set) { return name; } } // a type variable @@ -206,9 +248,9 @@ public abstract class TypeData { } public void merge(TypeData t) { - lowers.add(t); - if (t instanceof TypeVar) - ((TypeVar)t).usedBy.add(this); + lowers.add(t); + if (t instanceof TypeVar) + ((TypeVar)t).usedBy.add(this); } public int getTypeTag() { @@ -235,46 +277,68 @@ public abstract class TypeData { uppers.add(typeName); } - protected TypeVar toTypeVar() { return this; } - private int visited = 0; private int smallest = 0; private boolean inList = false; + private int dimension = 0; + + protected TypeVar toTypeVar(int dim) { + dimension = dim; + return this; + } + + /* When fixTypes() is called, getName() will return the correct + * (i.e. fixed) type name. + */ + public TypeData getArrayType(int dim) throws NotFoundException { + if (dim == 0) + return this; + else { + BasicType bt = isBasicType(); + if (bt == null) + if (isNullType()) + return new NullType(); + else + return new ClassName(getName()).getArrayType(dim); + else + return bt.getArrayType(dim); + } + } // depth-first serach public int dfs(ArrayList preOrder, int index, ClassPool cp) throws NotFoundException { - if (visited > 0) - return index; // MapMaker.make() may call an already visited node. - - visited = smallest = ++index; - preOrder.add(this); - inList = true; - int n = lowers.size(); - for (int i = 0; i < n; i++) { - TypeVar child = ((TypeData)lowers.get(i)).toTypeVar(); - if (child != null) - if (child.visited == 0) { - index = child.dfs(preOrder, index, cp); - if (child.smallest < smallest) - smallest = child.smallest; - } - else if (child.inList) - if (child.visited < smallest) - smallest = child.visited; - } - - if (visited == smallest) { + if (visited > 0) + return index; // MapMaker.make() may call an already visited node. + + visited = smallest = ++index; + preOrder.add(this); + inList = true; + int n = lowers.size(); + for (int i = 0; i < n; i++) { + TypeVar child = ((TypeData)lowers.get(i)).toTypeVar(dimension); + if (child != null) + if (child.visited == 0) { + index = child.dfs(preOrder, index, cp); + if (child.smallest < smallest) + smallest = child.smallest; + } + else if (child.inList) + if (child.visited < smallest) + smallest = child.visited; + } + + if (visited == smallest) { ArrayList scc = new ArrayList(); // strongly connected component - TypeVar cv; - do { - cv = (TypeVar)preOrder.remove(preOrder.size() - 1); - cv.inList = false; - scc.add(cv); - } while (cv != this); - fixTypes(scc, cp); - } + TypeVar cv; + do { + cv = (TypeVar)preOrder.remove(preOrder.size() - 1); + cv.inList = false; + scc.add(cv); + } while (cv != this); + fixTypes(scc, cp); + } - return index; + return index; } private void fixTypes(ArrayList scc, ClassPool cp) throws NotFoundException { @@ -283,10 +347,12 @@ public abstract class TypeData { TypeData kind = null; int size = scc.size(); for (int i = 0; i < size; i++) { - ArrayList tds = ((TypeVar)scc.get(i)).lowers; + TypeVar tvar = (TypeVar)scc.get(i); + ArrayList tds = tvar.lowers; int size2 = tds.size(); for (int j = 0; j < size2; j++) { - TypeData d = (TypeData)tds.get(j); + TypeData td = (TypeData)tds.get(j); + TypeData d = td.getArrayType(tvar.dimension); BasicType bt = d.isBasicType(); if (kind == null) { if (bt == null) { @@ -305,12 +371,11 @@ public abstract class TypeData { } } else { - if ((bt == null && isBasicType) - || (bt != null && kind != bt)) { + if ((bt == null && isBasicType) || (bt != null && kind != bt)) { isBasicType = true; kind = TypeTag.TOP; break; - } + } } if (bt == null && !d.isNullType()) @@ -319,19 +384,26 @@ public abstract class TypeData { } if (isBasicType) { - is2WordType = kind.is2WordType(); - for (int i = 0; i < size; i++) { - TypeVar cv = (TypeVar)scc.get(i); - cv.lowers.clear(); - cv.lowers.add(kind); - cv.is2WordType = kind.is2WordType(); - } + is2WordType = kind.is2WordType(); // necessary? + fixTypes1(scc, kind); } else { String typeName = fixTypes2(scc, lowersSet, cp); - for (int i = 0; i < size; i++) { - TypeVar cv = (TypeVar)scc.get(i); - cv.fixedType = typeName; + fixTypes1(scc, new ClassName(typeName)); + } + } + + private void fixTypes1(ArrayList scc, TypeData kind) throws NotFoundException { + int size = scc.size(); + for (int i = 0; i < size; i++) { + TypeVar cv = (TypeVar)scc.get(i); + TypeData kind2 = kind.getArrayType(-cv.dimension); + if (kind2.isBasicType() == null) + cv.fixedType = kind2.getName(); + else { + cv.lowers.clear(); + cv.lowers.add(kind2); + cv.is2WordType = kind2.is2WordType(); } } } @@ -343,17 +415,17 @@ public abstract class TypeData { else if (lowersSet.size() == 1) return (String)it.next(); else { - CtClass cc = cp.get((String)it.next()); - while (it.hasNext()) - cc = commonSuperClassEx(cc, cp.get((String)it.next())); + CtClass cc = cp.get((String)it.next()); + while (it.hasNext()) + cc = commonSuperClassEx(cc, cp.get((String)it.next())); - if (cc.getSuperclass() == null || isObjectArray(cc)) - cc = fixByUppers(scc, cp, new HashSet(), cc); + if (cc.getSuperclass() == null || isObjectArray(cc)) + cc = fixByUppers(scc, cp, new HashSet(), cc); - if (cc.isArray()) - return Descriptor.toJvmName(cc); - else - return cc.getName(); + if (cc.isArray()) + return Descriptor.toJvmName(cc); + else + return cc.getName(); } } @@ -387,6 +459,18 @@ public abstract class TypeData { return type; } + + String toString2(HashSet hash) { + hash.add(this); + if (lowers.size() > 0) { + TypeData e = (TypeData)lowers.get(0); + if (e != null && !hash.contains(e)) { + return e.toString2(hash); + } + } + + return "?"; + } } /** @@ -522,14 +606,14 @@ public abstract class TypeData { } public void merge(TypeData t) { - try { - if (!t.isNullType()) - element.merge(ArrayElement.make(t)); - } - catch (BadBytecode e) { - // never happens - throw new RuntimeException("fatal: " + e); - } + try { + if (!t.isNullType()) + element.merge(ArrayElement.make(t)); + } + catch (BadBytecode e) { + // never happens + throw new RuntimeException("fatal: " + e); + } } public String getName() { @@ -555,10 +639,18 @@ public abstract class TypeData { element.setType(ArrayElement.typeName(s), cp); } - protected TypeVar toTypeVar() { return element.toTypeVar(); } + protected TypeVar toTypeVar(int dim) { return element.toTypeVar(dim + 1); } + + public TypeData getArrayType(int dim) throws NotFoundException { + return element.getArrayType(dim + 1); + } public int dfs(ArrayList order, int index, ClassPool cp) throws NotFoundException { - return element.dfs(order, index, cp); + return element.dfs(order, index, cp); + } + + String toString2(HashSet set) { + return "[" + element.toString2(set); } } @@ -585,14 +677,14 @@ public abstract class TypeData { } public void merge(TypeData t) { - try { - if (!t.isNullType()) - array.merge(ArrayType.make(t)); - } - catch (BadBytecode e) { - // never happens - throw new RuntimeException("fatal: " + e); - } + try { + if (!t.isNullType()) + array.merge(ArrayType.make(t)); + } + catch (BadBytecode e) { + // never happens + throw new RuntimeException("fatal: " + e); + } } public String getName() { @@ -625,10 +717,18 @@ public abstract class TypeData { array.setType(ArrayType.typeName(s), cp); } - protected TypeVar toTypeVar() { return array.toTypeVar(); } + protected TypeVar toTypeVar(int dim) { return array.toTypeVar(dim - 1); } + + public TypeData getArrayType(int dim) throws NotFoundException { + return array.getArrayType(dim - 1); + } public int dfs(ArrayList order, int index, ClassPool cp) throws NotFoundException { - return array.dfs(order, index, cp); + return array.dfs(order, index, cp); + } + + String toString2(HashSet set) { + return "*" + array.toString2(set); } } @@ -644,7 +744,7 @@ public abstract class TypeData { public boolean eq(TypeData d) { return type.eq(d); } public String getName() { return type.getName(); } - protected TypeVar toTypeVar() { return null; } + protected TypeVar toTypeVar(int dim) { return null; } public TypeData join() { return type.join(); } public void setType(String s, ClassPool cp) throws BadBytecode { @@ -666,6 +766,12 @@ public abstract class TypeData { else // if type == TypeTag.TOP throw new RuntimeException("not available"); } + + public TypeData getArrayType(int dim) throws NotFoundException { + return type.getArrayType(dim); + } + + String toString2(HashSet set) { return ""; } } /** @@ -695,6 +801,45 @@ public abstract class TypeData { public boolean eq(TypeData d) { return name.equals(d.getName()); } public void setType(String typeName, ClassPool cp) throws BadBytecode {} + + public TypeData getArrayType(int dim) throws NotFoundException { + if (dim == 0) + return this; + else if (dim > 0) { + char[] dimType = new char[dim]; + for (int i = 0; i < dim; i++) + dimType[i] = '['; + + String elementType = getName(); + if (elementType.charAt(0) != '[') + elementType = "L" + elementType.replace('.', '/') + ";"; + + return new ClassName(new String(dimType) + elementType); + } + else { + for (int i = 0; i < -dim; i++) + if (name.charAt(i) != '[') + throw new NotFoundException("no " + dim + " dimensional array type: " + getName()); + + char type = name.charAt(-dim); + if (type == '[') + return new ClassName(name.substring(-dim)); + else if (type == 'L') + return new ClassName(name.substring(-dim + 1, name.length() - 1).replace('/', '.')); + else if (type == TypeTag.DOUBLE.decodedName) + return TypeTag.DOUBLE; + else if (type == TypeTag.FLOAT.decodedName) + return TypeTag.FLOAT; + else if (type == TypeTag.LONG.decodedName) + return TypeTag.LONG; + else + return TypeTag.INTEGER; + } + } + + String toString2(HashSet set) { + return name; + } } /** @@ -713,6 +858,8 @@ public abstract class TypeData { public boolean isNullType() { return true; } public int getTypeData(ConstPool cp) { return 0; } + + public TypeData getArrayType(int dim) { return this; } } /** @@ -756,14 +903,14 @@ public abstract class TypeData { return false; } - public String toString() { return "uninit:" + getName() + "@" + offset; } - public int offset() { return offset; } public void constructorCalled(int offset) { if (offset == this.offset) initialized = true; } + + String toString2(HashSet set) { return getName() + "," + offset; } } public static class UninitThis extends UninitData { @@ -781,6 +928,6 @@ public abstract class TypeData { return 0; } - public String toString() { return "uninit:this"; } + String toString2(HashSet set) { return "uninit:this"; } } } diff --git a/src/main/javassist/bytecode/stackmap/TypeTag.java b/src/main/javassist/bytecode/stackmap/TypeTag.java index 2a90d147..6fcdb243 100644 --- a/src/main/javassist/bytecode/stackmap/TypeTag.java +++ b/src/main/javassist/bytecode/stackmap/TypeTag.java @@ -20,11 +20,11 @@ import javassist.bytecode.StackMapTable; public interface TypeTag { String TOP_TYPE = "*top*"; - TypeData TOP = new TypeData.BasicType(TOP_TYPE, StackMapTable.TOP); - TypeData INTEGER = new TypeData.BasicType("int", StackMapTable.INTEGER); - TypeData FLOAT = new TypeData.BasicType("float", StackMapTable.FLOAT); - TypeData DOUBLE = new TypeData.BasicType("double", StackMapTable.DOUBLE); - TypeData LONG = new TypeData.BasicType("long", StackMapTable.LONG); + TypeData.BasicType TOP = new TypeData.BasicType(TOP_TYPE, StackMapTable.TOP, ' '); + TypeData.BasicType INTEGER = new TypeData.BasicType("int", StackMapTable.INTEGER, 'I'); + TypeData.BasicType FLOAT = new TypeData.BasicType("float", StackMapTable.FLOAT, 'F'); + TypeData.BasicType DOUBLE = new TypeData.BasicType("double", StackMapTable.DOUBLE, 'D'); + TypeData.BasicType LONG = new TypeData.BasicType("long", StackMapTable.LONG, 'J'); // and NULL, THIS, OBJECT, UNINIT } diff --git a/src/main/javassist/tools/Callback.java b/src/main/javassist/tools/Callback.java index 56c87414..c3095ccb 100644 --- a/src/main/javassist/tools/Callback.java +++ b/src/main/javassist/tools/Callback.java @@ -28,7 +28,7 @@ import java.util.UUID; * <p>Example of how to create and insert a callback:</p> * <pre> * ctMethod.insertAfter(new Callback("Thread.currentThread()") { - * public void result(Object... objects) { + * public void result(Object[] objects) { * Thread thread = (Thread) objects[0]; * // do something with thread... * } @@ -37,7 +37,7 @@ import java.util.UUID; * <p>Contains utility methods for inserts callbacks in <code>CtBehaviour</code>, example:</p> * <pre> * insertAfter(ctBehaviour, new Callback("Thread.currentThread(), dummyString") { - * public void result(Object... objects) { + * public void result(Object[] objects) { * Thread thread = (Thread) objects[0]; * // do something with thread... * } @@ -45,10 +45,11 @@ import java.util.UUID; * </pre> * * @author Marten Hedborg + * @author Shigeru Chiba */ public abstract class Callback { - public static HashMap<String, Callback> callbacks = new HashMap<String, Callback>(); + public static HashMap callbacks = new HashMap(); private final String sourceCode; @@ -70,9 +71,8 @@ public abstract class Callback { * * @param objects Objects that the bytecode in callback returns */ - public abstract void result(Object... objects); + public abstract void result(Object[] objects); - @Override public String toString(){ return sourceCode(); } diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java index 26c5c6c9..a85e8de0 100644 --- a/src/main/javassist/util/proxy/ProxyFactory.java +++ b/src/main/javassist/util/proxy/ProxyFactory.java @@ -1230,7 +1230,7 @@ public class ProxyFactory { return minfo; } - private static MethodInfo makeDelegator(Method meth, String desc, + private MethodInfo makeDelegator(Method meth, String desc, ConstPool cp, Class declClass, String delegatorName) { MethodInfo delegator = new MethodInfo(cp, delegatorName, desc); delegator.setAccessFlags(Modifier.FINAL | Modifier.PUBLIC @@ -1243,7 +1243,8 @@ public class ProxyFactory { Bytecode code = new Bytecode(cp, 0, 0); code.addAload(0); int s = addLoadParameters(code, meth.getParameterTypes(), 1); - code.addInvokespecial(declClass.isInterface(), cp.addClassInfo(declClass.getName()), + Class targetClass = invokespecialTarget(declClass); + code.addInvokespecial(targetClass.isInterface(), cp.addClassInfo(targetClass.getName()), meth.getName(), desc); addReturn(code, meth.getReturnType()); code.setMaxLocals(++s); @@ -1251,6 +1252,20 @@ public class ProxyFactory { return delegator; } + /* Suppose that the receiver type is S, the invoked method + * is declared in T, and U is the immediate super class of S + * (or its interface). If S <: U <: T (S <: T reads "S extends T"), + * the target type of invokespecial has to be not T but U. + */ + private Class invokespecialTarget(Class declClass) { + if (declClass.isInterface()) + for (Class i: interfaces) + if (declClass.isAssignableFrom(i)) + return i; + + return superClass; + } + /** * @param delegatorName null if the original method is abstract. */ diff --git a/src/test/Test.java b/src/test/Test.java index 2e6f5c3d..c21d930f 100644 --- a/src/test/Test.java +++ b/src/test/Test.java @@ -1,31 +1,54 @@ +import java.util.ArrayList; +import java.util.List; import javassist.*; -import javassist.bytecode.*; -import javassist.bytecode.annotation.*; -@interface Entity {} +class InvalidStackMapFrame { -@interface Table { String[] textValues() default {}; } + public void bytecodeVerifyError1() { + String[] newLine = new String[10]; + for (int i = 0; i < 5; i++) { + String a = newLine[1]; + newLine[4] = a; + } + } + + public void bytecodeVerifyError() { + // javassist bug : invalid stack map frame + List<Integer> test = new ArrayList<Integer>(); + String[] newLine = new String[10]; + for (Integer idx : test) { + // invalid stackMapFrame + // FRAME FULL [bug_regression_jdk7/javassist/InvalidStackMapFrame java/util/ArrayList java/lang/Object java/util/Iterator T T T I] [] + // java/lang/Object is wrong -> [Ljava/lang/String; is correct + String address = newLine[1]; + int tabPos = -1; + if (tabPos != -1) { + address = address.substring(tabPos + 1); + } + newLine[4] = address; + } + + } +} public class Test { + private static final String INVALID_STACK_MAP_FRAME = "InvalidStackMapFrame"; + public static void main(String[] args) throws Exception { + + // CustomURLClassLoader classLoader = new CustomURLClassLoader(new URL[]{}, Thread.currentThread().getContextClassLoader()); + ClassPool classPool = ClassPool.getDefault(); - ClassFile cf = classPool.makeClass("TestSub").getClassFile(); - ConstPool constPool = cf.getConstPool(); - Annotation[] annotations = new Annotation[2]; - AnnotationsAttribute attrib = - new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); - Annotation annotation = new Annotation(constPool, classPool.get("Entity")); - annotations[0] = annotation; - // Add @Table(name="",schema="") to class - annotation = new Annotation(constPool, classPool.get("Table")); - annotation.addMemberValue("name", new StringMemberValue("name", constPool)); - annotation.addMemberValue("schema", new StringMemberValue("schema", constPool)); -// ArrayMemberValue blankMemberValueArray = new ArrayMemberValue(new AnnotationMemberValue(constPool), constPool); -// blankMemberValueArray.setValue(new MemberValue[0]); -// annotation.addMemberValue("textValues", blankMemberValueArray); - annotations[1] = annotation; - attrib.setAnnotations(annotations); - cf.addAttribute(attrib); - System.out.println("done"); + // classPool.appendClassPath(new LoaderClassPath(classLoader)); + + final CtClass ctClass = classPool.get(INVALID_STACK_MAP_FRAME); + final CtMethod method = ctClass.getDeclaredMethod("bytecodeVerifyError"); + method.addLocalVariable("test_localVariable", CtClass.intType); + method.insertBefore("{ test_localVariable = 1; }"); + ctClass.debugWriteFile(); + Class<?> cc = ctClass.toClass(); + System.out.println(cc.getName()); + InvalidStackMapFrame obj = (InvalidStackMapFrame)cc.newInstance(); + obj.bytecodeVerifyError(); } } diff --git a/src/test/javassist/JvstTest.java b/src/test/javassist/JvstTest.java index 791b0820..9a671de6 100644 --- a/src/test/javassist/JvstTest.java +++ b/src/test/javassist/JvstTest.java @@ -842,7 +842,7 @@ public class JvstTest extends JvstTestRoot { // cloader.loadClass(cc.getName()); java.io.File genDir = new java.io.File("."); java.net.URLClassLoader ucl = new java.net.URLClassLoader( - new java.net.URL[] { genDir.toURL() }, null); + new java.net.URL[] { genDir.toURI().toURL() }, null); Class intf = ucl.loadClass("test1.MkInterface"); } diff --git a/src/test/javassist/JvstTest2.java b/src/test/javassist/JvstTest2.java index 411c1e97..4ff84784 100644 --- a/src/test/javassist/JvstTest2.java +++ b/src/test/javassist/JvstTest2.java @@ -516,15 +516,15 @@ public class JvstTest2 extends JvstTestRoot { CtClass out = sloader.get("test2.Anon"); CtClass inner = sloader.get("test2.Anon$1"); if (System.getProperty("java.vm.version").startsWith("1.4")) - assertTrue(inner.getEnclosingMethod() == null); + assertTrue(inner.getEnclosingBehavior() == null); else { - assertEquals("make", inner.getEnclosingMethod().getName()); + assertEquals("make", inner.getEnclosingBehavior().getName()); assertEquals(out, inner.getDeclaringClass()); assertEquals(out, - inner.getEnclosingMethod().getDeclaringClass()); + inner.getEnclosingBehavior().getDeclaringClass()); } - assertNull(out.getEnclosingMethod()); + assertNull(out.getEnclosingBehavior()); assertNull(out.getEnclosingBehavior()); CtClass inner2 = sloader.get("test2.Anon$Anon2$1"); diff --git a/src/test/javassist/JvstTest5.java b/src/test/javassist/JvstTest5.java index 1af027fd..792fed6e 100644 --- a/src/test/javassist/JvstTest5.java +++ b/src/test/javassist/JvstTest5.java @@ -220,4 +220,19 @@ public class JvstTest5 extends JvstTestRoot { Class clazzz = badClass.toClass(); Object obj = clazzz.newInstance(); // <-- falls here } + + public void test83StackmapWithArrayType() throws Exception { + final CtClass ctClass = sloader.get("test5.StackmapWithArray83"); + final CtMethod method = ctClass.getDeclaredMethod("bytecodeVerifyError"); + method.addLocalVariable("test_localVariable", CtClass.intType); + method.insertBefore("{ test_localVariable = 1; }"); + + final CtMethod method2 = ctClass.getDeclaredMethod("bytecodeVerifyError2"); + method2.addLocalVariable("test_localVariable", CtClass.intType); + method2.insertBefore("{ test_localVariable = 1; }"); + + ctClass.writeFile(); + Object obj = make(ctClass.getName()); + assertEquals(1, invoke(obj, "run")); + } } diff --git a/src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java b/src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java index 5b72d82e..0b255064 100644 --- a/src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java +++ b/src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java @@ -3,6 +3,7 @@ package test.javassist.proxy; import javassist.*; import javassist.util.proxy.MethodFilter; import javassist.util.proxy.MethodHandler; +import javassist.util.proxy.Proxy; import javassist.util.proxy.ProxyFactory; import javassist.util.proxy.ProxyObject; import junit.framework.TestCase; @@ -71,22 +72,23 @@ public class ProxyFactoryCompatibilityTest extends TestCase factory.setSuperclass(TestClass.class); factory.setInterfaces(new Class[] { TestInterface.class}); factory.setFilter(filter); - factory.setHandler(handler); // create the same class twice and check that it is reused Class proxyClass3 = factory.createClass(); System.out.println("created third class " + proxyClass3.getName()); TestClass proxy3 = (TestClass)proxyClass3.newInstance(); + ((Proxy)proxy3).setHandler(handler); proxy3.testMethod(); assertTrue(proxy3.isTestCalled()); Class proxyClass4 = factory.createClass(); System.out.println("created fourth class " + proxyClass4.getName()); TestClass proxy4 = (TestClass)proxyClass4.newInstance(); + ((Proxy)proxy4).setHandler(handler); proxy4.testMethod(); assertTrue(proxy4.isTestCalled()); - assertTrue(proxyClass3 != proxyClass4); + assertTrue(proxyClass3 == proxyClass4); } /** diff --git a/src/test/test/javassist/proxy/ProxySimpleTest.java b/src/test/test/javassist/proxy/ProxySimpleTest.java index f37e7b8c..289895cc 100644 --- a/src/test/test/javassist/proxy/ProxySimpleTest.java +++ b/src/test/test/javassist/proxy/ProxySimpleTest.java @@ -140,4 +140,63 @@ public class ProxySimpleTest extends TestCase { public String extended() { return "ext"; } public String base2() { return super.base2() + "ext2"; } } + + String valueDefaultMethods = ""; + + public void testDefaultMethods() throws Exception { + valueDefaultMethods = ""; + ProxyFactory f = new ProxyFactory(); + f.writeDirectory = "./proxy"; + f.setSuperclass(Default3.class); + Class c = f.createClass(); + MethodHandler mi = new MethodHandler() { + public Object invoke(Object self, Method m, Method proceed, + Object[] args) throws Throwable { + valueDefaultMethods += "1"; + return proceed.invoke(self, args); // execute the original method. + } + }; + Default3 foo = (Default3)c.newInstance(); + ((Proxy)foo).setHandler(mi); + foo.foo(); + foo.bar(); + assertEquals("11", valueDefaultMethods); + } + + public void testDefaultMethods2() throws Exception { + valueDefaultMethods = ""; + ProxyFactory f = new ProxyFactory(); + f.writeDirectory = "./proxy"; + f.setInterfaces(new Class[] { Default2.class }); + Class c = f.createClass(); + MethodHandler mi = new MethodHandler() { + public Object invoke(Object self, Method m, Method proceed, + Object[] args) throws Throwable { + valueDefaultMethods += "1"; + return proceed.invoke(self, args); // execute the original method. + } + }; + Default2 foo = (Default2)c.newInstance(); + ((Proxy)foo).setHandler(mi); + foo.foo(); + foo.bar(); + assertEquals("11", valueDefaultMethods); + } + + public static interface Default1 { + default int foo() { return 0; } + default int baz() { return 2; } + } + + public static interface Default2 extends Default1 { + default int bar() { return 1; } + } + + public static class Default3 implements Default2 { + public int foo() { return Default2.super.foo(); } + } + + public static class Default4 extends Default3 { + public int baz() { return super.baz(); } + } } diff --git a/src/test/test5/StackmapWithArray83.java b/src/test/test5/StackmapWithArray83.java new file mode 100644 index 00000000..c8333d81 --- /dev/null +++ b/src/test/test5/StackmapWithArray83.java @@ -0,0 +1,38 @@ +package test5; + +import java.util.ArrayList; +import java.util.List; + +public class StackmapWithArray83 { + public int run() { + bytecodeVerifyError(); + bytecodeVerifyError2(); + return 1; + } + + public void bytecodeVerifyError() { + List<Integer> test = new ArrayList<Integer>(); + String[] newLine = new String[10]; + for (Integer idx : test) { + String address = newLine[1]; + int tabPos = -1; + if (tabPos != -1) { + address = address.substring(tabPos + 1); + } + newLine[4] = address; + } + } + + public void bytecodeVerifyError2() { + List<Integer> test = new ArrayList<Integer>(); + int[] newLine = new int[10]; + for (Integer idx : test) { + int address = newLine[1]; + int tabPos = -1; + if (tabPos != -1) { + address = address + tabPos; + } + newLine[4] = address; + } + } +} diff --git a/src/test/testproxy/ProxyFactoryPerformanceTest.java b/src/test/testproxy/ProxyFactoryPerformanceTest.java index 5ce0adb6..d2081ae2 100644 --- a/src/test/testproxy/ProxyFactoryPerformanceTest.java +++ b/src/test/testproxy/ProxyFactoryPerformanceTest.java @@ -104,7 +104,7 @@ class ProxyMaker extends Thread implements MethodHandler { factory.setSuperclass(SampleBean.class);
factory.setInterfaces(SampleBean.class.getInterfaces());
factory.setFilter(FINALIZE_FILTER);
- factory.setHandler(this);
+ // factory.setHandler(this);
Class proxyClass = factory.createClass();
//System.out.println("proxy name: " + proxyClass.getName());
diff --git a/src/test/testproxy/ProxyTester.java b/src/test/testproxy/ProxyTester.java index e06848f8..77bdfa05 100644 --- a/src/test/testproxy/ProxyTester.java +++ b/src/test/testproxy/ProxyTester.java @@ -8,6 +8,7 @@ import javassist.util.proxy.ProxyFactory; import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyObject;
+import javassist.util.proxy.Proxy;
import junit.framework.Assert;
import junit.framework.TestCase;
import java.io.*;
@@ -44,7 +45,7 @@ public class ProxyTester extends TestCase { return proceed.invoke(self, args);
else
if (m.getReturnType() == int.class)
- return new Integer(3);
+ return Integer.valueOf(3);
else
return "OK";
}
@@ -60,11 +61,12 @@ public class ProxyTester extends TestCase { ProxyFactory f = new ProxyFactory();
f.setSuperclass(Target.class);
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
f.writeDirectory = ".";
Class c = f.createClass();
Target obj = (Target)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor);
obj.m();
assertEquals(true, obj.m(true));
assertEquals((byte)1, obj.m1((byte)1));
@@ -87,10 +89,11 @@ public class ProxyTester extends TestCase { ProxyFactory f = new ProxyFactory();
f.setSuperclass(Target1.class);
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
Class c = f.createClass();
Target1 obj = (Target1)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor);
assertEquals(null, obj.m(null));
assertEquals(1, interceptor.counter);
}
@@ -98,10 +101,11 @@ public class ProxyTester extends TestCase { public void testObject() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
Class c = f.createClass();
Object obj = (Object)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor);
System.out.println(obj.toString());
assertEquals(2, interceptor.counter);
}
@@ -110,10 +114,11 @@ public class ProxyTester extends TestCase { ProxyFactory f = new ProxyFactory();
f.writeDirectory = ".";
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
Class c = f.createClass();
Object obj = (Object)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor);
System.out.println("setter1: " + obj.toString());
((ProxyObject)obj).setHandler(new MethodHandler() {
public Object invoke(Object self, Method m, Method proceed,
@@ -128,7 +133,7 @@ public class ProxyTester extends TestCase { public void testString() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
f.setSuperclass(String.class);
try {
@@ -143,7 +148,7 @@ public class ProxyTester extends TestCase { public void testConstructor() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
f.setSuperclass(Target2.class);
Class c = f.createClass();
@@ -156,7 +161,8 @@ public class ProxyTester extends TestCase { assertEquals(0, m1.getExceptionTypes().length);
assertEquals("java.io.IOException", m2.getExceptionTypes()[0].getName());
- Target2 t2 = (Target2)con1.newInstance(new Object[] { new Integer(1) });
+ Target2 t2 = (Target2)con1.newInstance(new Object[] { Integer.valueOf(1) });
+ ((Proxy)t2).setHandler(interceptor);
System.out.println(t2.toString());
assertEquals(2, interceptor.counter);
@@ -169,11 +175,12 @@ public class ProxyTester extends TestCase { public void testInterface() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor2 interceptor2 = new Interceptor2();
- f.setHandler(interceptor2);
+ // f.setHandler(interceptor2);
f.setFilter(finalizeRemover);
f.setInterfaces(new Class[] { Target3.class });
Class c = f.createClass();
Target3 obj = (Target3)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor2);
assertEquals("OK", obj.m());
System.out.println(obj.toString());
assertEquals(3, interceptor2.counter);
@@ -182,17 +189,19 @@ public class ProxyTester extends TestCase { public void test2Interfaces() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor2 interceptor2 = new Interceptor2();
- f.setHandler(interceptor2);
+ // f.setHandler(interceptor2);
f.setFilter(finalizeRemover);
f.setInterfaces(new Class[] { Target3.class, Target4.class });
Class c = f.createClass();
Target3 obj = (Target3)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor2);
assertEquals("OK", obj.m());
System.out.println(obj.toString());
assertEquals(3, interceptor2.counter);
interceptor2.counter = 0;
Target4 obj4 = (Target4)c.newInstance();
+ ((Proxy)obj4).setHandler(interceptor2);
assertEquals(3, obj4.bar4());
assertEquals(3, obj4.foo4());
assertEquals(2, interceptor2.counter);
@@ -201,7 +210,7 @@ public class ProxyTester extends TestCase { public void testFilter() throws Exception {
ProxyFactory f = new ProxyFactory();
Interceptor2 interceptor2 = new Interceptor2();
- f.setHandler(interceptor2);
+ // f.setHandler(interceptor2);
f.setFilter(finalizeRemover);
f.setInterfaces(new Class[] { Target3.class });
f.setFilter(new MethodFilter() {
@@ -211,6 +220,7 @@ public class ProxyTester extends TestCase { });
Class c = f.createClass();
Target3 obj = (Target3)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor2);
assertEquals("OK", obj.m());
System.out.println(obj.toString());
assertEquals(1, interceptor2.counter);
@@ -243,10 +253,11 @@ public class ProxyTester extends TestCase { ProxyFactory f = new ProxyFactory();
f.setSuperclass(Target5.class);
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
Class c = f.createClass();
- Target5 obj = (Target5)f.create(new Class[] { int.class }, new Object[] { new Integer(3) });
+ Target5 obj = (Target5)f.create(new Class[] { int.class }, new Object[] { Integer.valueOf(3) });
+ ((Proxy)obj).setHandler(interceptor);
assertEquals(3, obj.get());
}
@@ -256,10 +267,11 @@ public class ProxyTester extends TestCase { f.writeDirectory = ".";
f.setSuperclass(BridgeMethod.class);
Interceptor1 interceptor = new Interceptor1();
- f.setHandler(interceptor);
+ // f.setHandler(interceptor);
f.setFilter(finalizeRemover);
Class c = f.createClass();
BridgeMethod obj = (BridgeMethod)c.newInstance();
+ ((Proxy)obj).setHandler(interceptor);
Integer value = obj.m1();
assertEquals(7, value.intValue());
BridgeMethodInf inf = (BridgeMethodInf)obj;
@@ -310,7 +322,8 @@ public class ProxyTester extends TestCase { ProxyFactory.classLoaderProvider = cp;
}
- public void testCache() throws Exception {
+ @SuppressWarnings("deprecation")
+ public void testCache() throws Exception {
boolean prev = ProxyFactory.useCache;
ProxyFactory.useCache = true;
ProxyFactory f = new ProxyFactory();
@@ -321,8 +334,9 @@ public class ProxyTester extends TestCase { assertEquals(c, f2.createClass());
ProxyFactory f3 = new ProxyFactory();
f3.setSuperclass(Cache1.class);
- f3.setHandler(new Interceptor1());
+ f3.setHandler(new Interceptor1()); // deprecated
assertFalse(c == f3.createClass());
+ ProxyFactory.useCache = true;
ProxyFactory f4 = new ProxyFactory();
f4.setSuperclass(Cache1.class);
f4.setInterfaces(new Class[] { Cache2.class });
|