summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchibash <chiba@javassist.org>2016-07-30 23:06:05 +0900
committerchibash <chiba@javassist.org>2016-07-30 23:06:05 +0900
commit2321430bd34e0e576435e2f16b3736f5ce7e2053 (patch)
treec01fd6094bbc2381fb3905efc343560deab0fd57
parent79785b83f263d90135dbcc5744deb44b27ae3665 (diff)
parentf795fcb1717fdde3e0c510b218b04abb55081202 (diff)
downloadjavassist-2321430bd34e0e576435e2f16b3736f5ce7e2053.tar.gz
javassist-2321430bd34e0e576435e2f16b3736f5ce7e2053.zip
Merge branch 'master' of github.com:jboss-javassist/javassist into test/java9-jigsaw
-rw-r--r--Readme.html4
-rw-r--r--build.xml8
-rw-r--r--javassist.jarbin721634 -> 0 bytes
-rw-r--r--src/main/javassist/bytecode/stackmap/TypeData.java329
-rw-r--r--src/main/javassist/bytecode/stackmap/TypeTag.java10
-rw-r--r--src/main/javassist/tools/Callback.java10
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java19
-rw-r--r--src/test/Test.java67
-rw-r--r--src/test/javassist/JvstTest.java2
-rw-r--r--src/test/javassist/JvstTest2.java8
-rw-r--r--src/test/javassist/JvstTest5.java15
-rw-r--r--src/test/test/javassist/proxy/ProxyFactoryCompatibilityTest.java6
-rw-r--r--src/test/test/javassist/proxy/ProxySimpleTest.java59
-rw-r--r--src/test/test5/StackmapWithArray83.java38
-rw-r--r--src/test/testproxy/ProxyFactoryPerformanceTest.java2
-rw-r--r--src/test/testproxy/ProxyTester.java46
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>
diff --git a/build.xml b/build.xml
index b22829e0..2cbfeb8d 100644
--- a/build.xml
+++ b/build.xml
@@ -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
deleted file mode 100644
index bcc617c6..00000000
--- a/javassist.jar
+++ /dev/null
Binary files differ
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 });