aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2011-11-04 14:01:56 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2011-11-04 14:01:56 +0000
commit716fb49d201cf5d8628c7217edb6c0f4f255e218 (patch)
tree5394a02654e94393fe58c9eb05d7f72f7115e3e1
parentbfc16920e4eb12db5df1e6175e77e3b3c81e37b2 (diff)
downloadjavassist-716fb49d201cf5d8628c7217edb6c0f4f255e218.tar.gz
javassist-716fb49d201cf5d8628c7217edb6c0f4f255e218.zip
fixed JASSIST-146
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@595 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
-rw-r--r--src/main/javassist/bytecode/ConstPool.java438
-rw-r--r--src/test/javassist/JvstTest2.java2
-rw-r--r--src/test/javassist/JvstTest4.java3
-rw-r--r--src/test/javassist/bytecode/BytecodeTest.java197
-rw-r--r--src/test/test4/Rename.java8
5 files changed, 445 insertions, 203 deletions
diff --git a/src/main/javassist/bytecode/ConstPool.java b/src/main/javassist/bytecode/ConstPool.java
index a04ba128..0a01f9a2 100644
--- a/src/main/javassist/bytecode/ConstPool.java
+++ b/src/main/javassist/bytecode/ConstPool.java
@@ -34,27 +34,8 @@ import javassist.CtClass;
public final class ConstPool {
LongVector items;
int numOfItems;
- HashMap classes;
- HashMap strings;
- ConstInfo[] constInfoCache;
- int[] constInfoIndexCache;
int thisClassInfo;
-
- private static final int CACHE_SIZE = 32;
-
- /**
- * A hash function for CACHE_SIZE
- */
- private static int hashFunc(int a, int b) {
- int h = -2128831035;
- final int prime = 16777619;
- h = (h ^ (a & 0xff)) * prime;
- h = (h ^ (b & 0xff)) * prime;
-
- // changing the hash key size from 32bit to 5bit
- h = (h >> 5) ^ (h & 0x1f);
- return h & 0x1f; // 0..31
- }
+ HashMap itemsCache;
/**
* <code>CONSTANT_Class</code>
@@ -125,12 +106,9 @@ public final class ConstPool {
*/
public ConstPool(String thisclass) {
items = new LongVector();
+ itemsCache = null;
numOfItems = 0;
- addItem(null); // index 0 is reserved by the JVM.
- classes = new HashMap();
- strings = new HashMap();
- constInfoCache = new ConstInfo[CACHE_SIZE];
- constInfoIndexCache = new int[CACHE_SIZE];
+ addItem0(null); // index 0 is reserved by the JVM.
thisClassInfo = addClassInfo(thisclass);
}
@@ -140,10 +118,7 @@ public final class ConstPool {
* @param in byte stream.
*/
public ConstPool(DataInputStream in) throws IOException {
- classes = new HashMap();
- strings = new HashMap();
- constInfoCache = new ConstInfo[CACHE_SIZE];
- constInfoIndexCache = new int[CACHE_SIZE];
+ itemsCache = null;
thisClassInfo = 0;
/* read() initializes items and numOfItems, and do addItem(null).
*/
@@ -151,10 +126,7 @@ public final class ConstPool {
}
void prune() {
- classes = new HashMap();
- strings = new HashMap();
- constInfoCache = new ConstInfo[CACHE_SIZE];
- constInfoIndexCache = new int[CACHE_SIZE];
+ itemsCache = null;
}
/**
@@ -686,11 +658,25 @@ public final class ConstPool {
return null; // false
}
- private int addItem(ConstInfo info) {
+ private int addItem0(ConstInfo info) {
items.addElement(info);
return numOfItems++;
}
+ private int addItem(ConstInfo info) {
+ if (itemsCache == null)
+ itemsCache = makeItemsCache(items);
+
+ ConstInfo found = (ConstInfo)itemsCache.get(info);
+ if (found != null)
+ return found.index;
+ else {
+ items.addElement(info);
+ itemsCache.put(info, info);
+ return numOfItems++;
+ }
+ }
+
/**
* Copies the n-th item in this ConstPool object into the destination
* ConstPool object.
@@ -711,7 +697,7 @@ public final class ConstPool {
}
int addConstInfoPadding() {
- return addItem(new ConstInfoPadding());
+ return addItem0(new ConstInfoPadding(numOfItems));
}
/**
@@ -748,15 +734,8 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addClassInfo(String qname) {
- ClassInfo info = (ClassInfo)classes.get(qname);
- if (info != null)
- return info.index;
- else {
- int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
- info = new ClassInfo(utf8, numOfItems);
- classes.put(qname, info);
- return addItem(info);
- }
+ int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
+ return addItem(new ClassInfo(utf8, numOfItems));
}
/**
@@ -780,17 +759,7 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addNameAndTypeInfo(int name, int type) {
- int h = hashFunc(name, type);
- ConstInfo ci = constInfoCache[h];
- if (ci != null && ci instanceof NameAndTypeInfo && ci.hashCheck(name, type))
- return constInfoIndexCache[h];
- else {
- NameAndTypeInfo item = new NameAndTypeInfo(name, type);
- constInfoCache[h] = item;
- int i = addItem(item);
- constInfoIndexCache[h] = i;
- return i;
- }
+ return addItem(new NameAndTypeInfo(name, type, numOfItems));
}
/**
@@ -819,17 +788,7 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
- int h = hashFunc(classInfo, nameAndTypeInfo);
- ConstInfo ci = constInfoCache[h];
- if (ci != null && ci instanceof FieldrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
- return constInfoIndexCache[h];
- else {
- FieldrefInfo item = new FieldrefInfo(classInfo, nameAndTypeInfo);
- constInfoCache[h] = item;
- int i = addItem(item);
- constInfoIndexCache[h] = i;
- return i;
- }
+ return addItem(new FieldrefInfo(classInfo, nameAndTypeInfo, numOfItems));
}
/**
@@ -858,17 +817,7 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
- int h = hashFunc(classInfo, nameAndTypeInfo);
- ConstInfo ci = constInfoCache[h];
- if (ci != null && ci instanceof MethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
- return constInfoIndexCache[h];
- else {
- MethodrefInfo item = new MethodrefInfo(classInfo, nameAndTypeInfo);
- constInfoCache[h] = item;
- int i = addItem(item);
- constInfoIndexCache[h] = i;
- return i;
- }
+ return addItem(new MethodrefInfo(classInfo, nameAndTypeInfo, numOfItems));
}
/**
@@ -901,17 +850,8 @@ public final class ConstPool {
*/
public int addInterfaceMethodrefInfo(int classInfo,
int nameAndTypeInfo) {
- int h = hashFunc(classInfo, nameAndTypeInfo);
- ConstInfo ci = constInfoCache[h];
- if (ci != null && ci instanceof InterfaceMethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
- return constInfoIndexCache[h];
- else {
- InterfaceMethodrefInfo item =new InterfaceMethodrefInfo(classInfo, nameAndTypeInfo);
- constInfoCache[h] = item;
- int i = addItem(item);
- constInfoIndexCache[h] = i;
- return i;
- }
+ return addItem(new InterfaceMethodrefInfo(classInfo, nameAndTypeInfo,
+ numOfItems));
}
/**
@@ -924,7 +864,8 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addStringInfo(String str) {
- return addItem(new StringInfo(addUtf8Info(str)));
+ int utf = addUtf8Info(str);
+ return addItem(new StringInfo(utf, numOfItems));
}
/**
@@ -934,7 +875,7 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addIntegerInfo(int i) {
- return addItem(new IntegerInfo(i));
+ return addItem(new IntegerInfo(i, numOfItems));
}
/**
@@ -944,7 +885,7 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addFloatInfo(float f) {
- return addItem(new FloatInfo(f));
+ return addItem(new FloatInfo(f, numOfItems));
}
/**
@@ -954,8 +895,10 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addLongInfo(long l) {
- int i = addItem(new LongInfo(l));
- addItem(new ConstInfoPadding());
+ int i = addItem(new LongInfo(l, numOfItems));
+ if (i == numOfItems - 1) // if not existing
+ addConstInfoPadding();
+
return i;
}
@@ -966,8 +909,10 @@ public final class ConstPool {
* @return the index of the added entry.
*/
public int addDoubleInfo(double d) {
- int i = addItem(new DoubleInfo(d));
- addItem(new ConstInfoPadding());
+ int i = addItem(new DoubleInfo(d, numOfItems));
+ if (i == numOfItems - 1) // if not existing
+ addConstInfoPadding();
+
return i;
}
@@ -975,31 +920,18 @@ public final class ConstPool {
* Adds a new <code>CONSTANT_Utf8_info</code>
* structure.
*
- * <p>If the given utf8 string has been already recorded in the
- * table, then this method does not add a new entry to avoid adding
- * a duplicated entry.
- * Instead, it returns the index of the entry already recorded.
- *
* @return the index of the added entry.
*/
public int addUtf8Info(String utf8) {
- Utf8Info info = (Utf8Info)strings.get(utf8);
- if (info != null)
- return info.index;
- else {
- info = new Utf8Info(utf8, numOfItems);
- strings.put(utf8, info);
- return addItem(info);
- }
+ return addItem(new Utf8Info(utf8, numOfItems));
}
/**
* Get all the class names.
*
- * @return a set of class names
+ * @return a set of class names (<code>String</code> objects).
*/
- public Set getClassNames()
- {
+ public Set getClassNames() {
HashSet result = new HashSet();
LongVector v = items;
int size = numOfItems;
@@ -1020,11 +952,9 @@ public final class ConstPool {
public void renameClass(String oldName, String newName) {
LongVector v = items;
int size = numOfItems;
- classes = new HashMap(classes.size() * 2);
for (int i = 1; i < size; ++i) {
ConstInfo ci = v.elementAt(i);
- ci.renameClass(this, oldName, newName);
- ci.makeHashtable(this);
+ ci.renameClass(this, oldName, newName, itemsCache);
}
}
@@ -1037,11 +967,9 @@ public final class ConstPool {
public void renameClass(Map classnames) {
LongVector v = items;
int size = numOfItems;
- classes = new HashMap(classes.size() * 2);
for (int i = 1; i < size; ++i) {
ConstInfo ci = v.elementAt(i);
- ci.renameClass(this, classnames);
- ci.makeHashtable(this);
+ ci.renameClass(this, classnames, itemsCache);
}
}
@@ -1050,24 +978,29 @@ public final class ConstPool {
items = new LongVector(n);
numOfItems = 0;
- addItem(null); // index 0 is reserved by the JVM.
+ addItem0(null); // index 0 is reserved by the JVM.
while (--n > 0) { // index 0 is reserved by JVM
int tag = readOne(in);
if ((tag == LongInfo.tag) || (tag == DoubleInfo.tag)) {
- addItem(new ConstInfoPadding());
+ addConstInfoPadding();
--n;
}
}
+ }
+ private static HashMap makeItemsCache(LongVector items) {
+ HashMap cache = new HashMap();
int i = 1;
while (true) {
ConstInfo info = items.elementAt(i++);
if (info == null)
break;
else
- info.makeHashtable(this);
+ cache.put(info, info);
}
+
+ return cache;
}
private int readOne(DataInputStream in) throws IOException {
@@ -1076,44 +1009,43 @@ public final class ConstPool {
switch (tag) {
case Utf8Info.tag : // 1
info = new Utf8Info(in, numOfItems);
- strings.put(((Utf8Info)info).string, info);
break;
case IntegerInfo.tag : // 3
- info = new IntegerInfo(in);
+ info = new IntegerInfo(in, numOfItems);
break;
case FloatInfo.tag : // 4
- info = new FloatInfo(in);
+ info = new FloatInfo(in, numOfItems);
break;
case LongInfo.tag : // 5
- info = new LongInfo(in);
+ info = new LongInfo(in, numOfItems);
break;
case DoubleInfo.tag : // 6
- info = new DoubleInfo(in);
+ info = new DoubleInfo(in, numOfItems);
break;
case ClassInfo.tag : // 7
info = new ClassInfo(in, numOfItems);
// classes.put(<classname>, info);
break;
case StringInfo.tag : // 8
- info = new StringInfo(in);
+ info = new StringInfo(in, numOfItems);
break;
case FieldrefInfo.tag : // 9
- info = new FieldrefInfo(in);
+ info = new FieldrefInfo(in, numOfItems);
break;
case MethodrefInfo.tag : // 10
- info = new MethodrefInfo(in);
+ info = new MethodrefInfo(in, numOfItems);
break;
case InterfaceMethodrefInfo.tag : // 11
- info = new InterfaceMethodrefInfo(in);
+ info = new InterfaceMethodrefInfo(in, numOfItems);
break;
case NameAndTypeInfo.tag : // 12
- info = new NameAndTypeInfo(in);
+ info = new NameAndTypeInfo(in, numOfItems);
break;
default :
- throw new IOException("invalid constant type: " + tag);
+ throw new IOException("invalid constant type: " + tag + " at " + numOfItems);
}
- addItem(info);
+ addItem0(info);
return tag;
}
@@ -1149,21 +1081,21 @@ public final class ConstPool {
}
abstract class ConstInfo {
+ int index;
+
+ public ConstInfo(int i) { index = i; }
+
public abstract int getTag();
public String getClassName(ConstPool cp) { return null; }
- public void renameClass(ConstPool cp, String oldName, String newName) {}
- public void renameClass(ConstPool cp, Map classnames) {}
+ public void renameClass(ConstPool cp, String oldName, String newName, HashMap cache) {}
+ public void renameClass(ConstPool cp, Map classnames, HashMap cache) {}
public abstract int copy(ConstPool src, ConstPool dest, Map classnames);
// ** classnames is a mapping between JVM names.
public abstract void write(DataOutputStream out) throws IOException;
public abstract void print(PrintWriter out);
- void makeHashtable(ConstPool cp) {} // called after read() finishes in ConstPool.
-
- boolean hashCheck(int a, int b) { return false; }
-
public String toString() {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter(bout);
@@ -1175,6 +1107,8 @@ abstract class ConstInfo {
/* padding following DoubleInfo or LongInfo.
*/
class ConstInfoPadding extends ConstInfo {
+ public ConstInfoPadding(int i) { super(i); }
+
public int getTag() { return 0; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1191,46 +1125,72 @@ class ConstInfoPadding extends ConstInfo {
class ClassInfo extends ConstInfo {
static final int tag = 7;
int name;
- int index;
- public ClassInfo(int className, int i) {
+ public ClassInfo(int className, int index) {
+ super(index);
name = className;
- index = i;
}
- public ClassInfo(DataInputStream in, int i) throws IOException {
+ public ClassInfo(DataInputStream in, int index) throws IOException {
+ super(index);
name = in.readUnsignedShort();
- index = i;
+ }
+
+ public int hashCode() { return name; }
+
+ public boolean equals(Object obj) {
+ return obj instanceof ClassInfo && ((ClassInfo)obj).name == name;
}
public int getTag() { return tag; }
public String getClassName(ConstPool cp) {
return cp.getUtf8Info(name);
- };
+ }
- public void renameClass(ConstPool cp, String oldName, String newName) {
+ public void renameClass(ConstPool cp, String oldName, String newName, HashMap cache) {
String nameStr = cp.getUtf8Info(name);
+ String newNameStr = null;
if (nameStr.equals(oldName))
- name = cp.addUtf8Info(newName);
+ newNameStr = newName;
else if (nameStr.charAt(0) == '[') {
- String nameStr2 = Descriptor.rename(nameStr, oldName, newName);
- if (nameStr != nameStr2)
- name = cp.addUtf8Info(nameStr2);
+ String s = Descriptor.rename(nameStr, oldName, newName);
+ if (nameStr != s)
+ newNameStr = s;
}
+
+ if (newNameStr != null)
+ if (cache == null)
+ name = cp.addUtf8Info(newNameStr);
+ else {
+ cache.remove(this);
+ name = cp.addUtf8Info(newNameStr);
+ cache.put(this, this);
+ }
}
- public void renameClass(ConstPool cp, Map map) {
+ public void renameClass(ConstPool cp, Map map, HashMap cache) {
String oldName = cp.getUtf8Info(name);
+ String newName = null;
if (oldName.charAt(0) == '[') {
- String newName = Descriptor.rename(oldName, map);
- if (oldName != newName)
- name = cp.addUtf8Info(newName);
+ String s = Descriptor.rename(oldName, map);
+ if (oldName != s)
+ newName = s;
}
else {
- String newName = (String)map.get(oldName);
- if (newName != null && !newName.equals(oldName))
+ String s = (String)map.get(oldName);
+ if (s != null && !s.equals(oldName))
+ newName = s;
+ }
+
+ if (newName != null) {
+ if (cache == null)
+ name = cp.addUtf8Info(newName);
+ else {
+ cache.remove(this);
name = cp.addUtf8Info(newName);
+ cache.put(this, this);
+ }
}
}
@@ -1254,11 +1214,6 @@ class ClassInfo extends ConstInfo {
out.print("Class #");
out.println(name);
}
-
- void makeHashtable(ConstPool cp) {
- String name = Descriptor.toJavaName(getClassName(cp));
- cp.classes.put(name, this);
- }
}
class NameAndTypeInfo extends ConstInfo {
@@ -1266,32 +1221,55 @@ class NameAndTypeInfo extends ConstInfo {
int memberName;
int typeDescriptor;
- public NameAndTypeInfo(int name, int type) {
+ public NameAndTypeInfo(int name, int type, int index) {
+ super(index);
memberName = name;
typeDescriptor = type;
}
- public NameAndTypeInfo(DataInputStream in) throws IOException {
+ public NameAndTypeInfo(DataInputStream in, int index) throws IOException {
+ super(index);
memberName = in.readUnsignedShort();
typeDescriptor = in.readUnsignedShort();
}
- boolean hashCheck(int a, int b) { return a == memberName && b == typeDescriptor; }
+ public int hashCode() { return (memberName << 16) ^ typeDescriptor; }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof NameAndTypeInfo) {
+ NameAndTypeInfo nti = (NameAndTypeInfo)obj;
+ return nti.memberName == memberName && nti.typeDescriptor == typeDescriptor;
+ }
+ else
+ return false;
+ }
public int getTag() { return tag; }
- public void renameClass(ConstPool cp, String oldName, String newName) {
+ public void renameClass(ConstPool cp, String oldName, String newName, HashMap cache) {
String type = cp.getUtf8Info(typeDescriptor);
String type2 = Descriptor.rename(type, oldName, newName);
if (type != type2)
- typeDescriptor = cp.addUtf8Info(type2);
+ if (cache == null)
+ typeDescriptor = cp.addUtf8Info(type2);
+ else {
+ cache.remove(this);
+ typeDescriptor = cp.addUtf8Info(type2);
+ cache.put(this, this);
+ }
}
- public void renameClass(ConstPool cp, Map map) {
+ public void renameClass(ConstPool cp, Map map, HashMap cache) {
String type = cp.getUtf8Info(typeDescriptor);
String type2 = Descriptor.rename(type, map);
if (type != type2)
- typeDescriptor = cp.addUtf8Info(type2);
+ if (cache == null)
+ typeDescriptor = cp.addUtf8Info(type2);
+ else {
+ cache.remove(this);
+ typeDescriptor = cp.addUtf8Info(type2);
+ cache.put(this, this);
+ }
}
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1320,24 +1298,36 @@ abstract class MemberrefInfo extends ConstInfo {
int classIndex;
int nameAndTypeIndex;
- public MemberrefInfo(int cindex, int ntindex) {
+ public MemberrefInfo(int cindex, int ntindex, int thisIndex) {
+ super(thisIndex);
classIndex = cindex;
nameAndTypeIndex = ntindex;
}
- public MemberrefInfo(DataInputStream in) throws IOException {
+ public MemberrefInfo(DataInputStream in, int thisIndex) throws IOException {
+ super(thisIndex);
classIndex = in.readUnsignedShort();
nameAndTypeIndex = in.readUnsignedShort();
}
+ public int hashCode() { return (classIndex << 16) ^ nameAndTypeIndex; }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof MemberrefInfo) {
+ MemberrefInfo mri = (MemberrefInfo)obj;
+ return mri.classIndex == classIndex && mri.nameAndTypeIndex == nameAndTypeIndex
+ && mri.getClass() == this.getClass();
+ }
+ else
+ return false;
+ }
+
public int copy(ConstPool src, ConstPool dest, Map map) {
int classIndex2 = src.getItem(classIndex).copy(src, dest, map);
int ntIndex2 = src.getItem(nameAndTypeIndex).copy(src, dest, map);
return copy2(dest, classIndex2, ntIndex2);
}
- boolean hashCheck(int a, int b) { return a == classIndex && b == nameAndTypeIndex; }
-
abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
public void write(DataOutputStream out) throws IOException {
@@ -1359,12 +1349,12 @@ abstract class MemberrefInfo extends ConstInfo {
class FieldrefInfo extends MemberrefInfo {
static final int tag = 9;
- public FieldrefInfo(int cindex, int ntindex) {
- super(cindex, ntindex);
+ public FieldrefInfo(int cindex, int ntindex, int thisIndex) {
+ super(cindex, ntindex, thisIndex);
}
- public FieldrefInfo(DataInputStream in) throws IOException {
- super(in);
+ public FieldrefInfo(DataInputStream in, int thisIndex) throws IOException {
+ super(in, thisIndex);
}
public int getTag() { return tag; }
@@ -1379,12 +1369,12 @@ class FieldrefInfo extends MemberrefInfo {
class MethodrefInfo extends MemberrefInfo {
static final int tag = 10;
- public MethodrefInfo(int cindex, int ntindex) {
- super(cindex, ntindex);
+ public MethodrefInfo(int cindex, int ntindex, int thisIndex) {
+ super(cindex, ntindex, thisIndex);
}
- public MethodrefInfo(DataInputStream in) throws IOException {
- super(in);
+ public MethodrefInfo(DataInputStream in, int thisIndex) throws IOException {
+ super(in, thisIndex);
}
public int getTag() { return tag; }
@@ -1399,12 +1389,12 @@ class MethodrefInfo extends MemberrefInfo {
class InterfaceMethodrefInfo extends MemberrefInfo {
static final int tag = 11;
- public InterfaceMethodrefInfo(int cindex, int ntindex) {
- super(cindex, ntindex);
+ public InterfaceMethodrefInfo(int cindex, int ntindex, int thisIndex) {
+ super(cindex, ntindex, thisIndex);
}
- public InterfaceMethodrefInfo(DataInputStream in) throws IOException {
- super(in);
+ public InterfaceMethodrefInfo(DataInputStream in, int thisIndex) throws IOException {
+ super(in, thisIndex);
}
public int getTag() { return tag; }
@@ -1420,14 +1410,22 @@ class StringInfo extends ConstInfo {
static final int tag = 8;
int string;
- public StringInfo(int str) {
+ public StringInfo(int str, int index) {
+ super(index);
string = str;
}
- public StringInfo(DataInputStream in) throws IOException {
+ public StringInfo(DataInputStream in, int index) throws IOException {
+ super(index);
string = in.readUnsignedShort();
}
+ public int hashCode() { return string; }
+
+ public boolean equals(Object obj) {
+ return obj instanceof StringInfo && ((StringInfo)obj).string == string;
+ }
+
public int getTag() { return tag; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1449,14 +1447,22 @@ class IntegerInfo extends ConstInfo {
static final int tag = 3;
int value;
- public IntegerInfo(int i) {
- value = i;
+ public IntegerInfo(int v, int index) {
+ super(index);
+ value = v;
}
- public IntegerInfo(DataInputStream in) throws IOException {
+ public IntegerInfo(DataInputStream in, int index) throws IOException {
+ super(index);
value = in.readInt();
}
+ public int hashCode() { return value; }
+
+ public boolean equals(Object obj) {
+ return obj instanceof IntegerInfo && ((IntegerInfo)obj).value == value;
+ }
+
public int getTag() { return tag; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1478,14 +1484,22 @@ class FloatInfo extends ConstInfo {
static final int tag = 4;
float value;
- public FloatInfo(float f) {
+ public FloatInfo(float f, int index) {
+ super(index);
value = f;
}
- public FloatInfo(DataInputStream in) throws IOException {
+ public FloatInfo(DataInputStream in, int index) throws IOException {
+ super(index);
value = in.readFloat();
}
+ public int hashCode() { return Float.floatToIntBits(value); }
+
+ public boolean equals(Object obj) {
+ return obj instanceof FloatInfo && ((FloatInfo)obj).value == value;
+ }
+
public int getTag() { return tag; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1507,14 +1521,22 @@ class LongInfo extends ConstInfo {
static final int tag = 5;
long value;
- public LongInfo(long l) {
+ public LongInfo(long l, int index) {
+ super(index);
value = l;
}
- public LongInfo(DataInputStream in) throws IOException {
+ public LongInfo(DataInputStream in, int index) throws IOException {
+ super(index);
value = in.readLong();
}
+ public int hashCode() { return (int)(value ^ (value >>> 32)); }
+
+ public boolean equals(Object obj) {
+ return obj instanceof LongInfo && ((LongInfo)obj).value == value;
+ }
+
public int getTag() { return tag; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1536,14 +1558,25 @@ class DoubleInfo extends ConstInfo {
static final int tag = 6;
double value;
- public DoubleInfo(double d) {
+ public DoubleInfo(double d, int index) {
+ super(index);
value = d;
}
- public DoubleInfo(DataInputStream in) throws IOException {
+ public DoubleInfo(DataInputStream in, int index) throws IOException {
+ super(index);
value = in.readDouble();
}
+ public int hashCode() {
+ long v = Double.doubleToLongBits(value);
+ return (int)(v ^ (v >>> 32));
+ }
+
+ public boolean equals(Object obj) {
+ return obj instanceof DoubleInfo && ((DoubleInfo)obj).value == value;
+ }
+
public int getTag() { return tag; }
public int copy(ConstPool src, ConstPool dest, Map map) {
@@ -1564,16 +1597,23 @@ class DoubleInfo extends ConstInfo {
class Utf8Info extends ConstInfo {
static final int tag = 1;
String string;
- int index;
- public Utf8Info(String utf8, int i) {
+ public Utf8Info(String utf8, int index) {
+ super(index);
string = utf8;
- index = i;
}
- public Utf8Info(DataInputStream in, int i) throws IOException {
+ public Utf8Info(DataInputStream in, int index) throws IOException {
+ super(index);
string = in.readUTF();
- index = i;
+ }
+
+ public int hashCode() {
+ return string.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ return obj instanceof Utf8Info && ((Utf8Info)obj).string.equals(string);
}
public int getTag() { return tag; }
diff --git a/src/test/javassist/JvstTest2.java b/src/test/javassist/JvstTest2.java
index 7a9d398a..71704e08 100644
--- a/src/test/javassist/JvstTest2.java
+++ b/src/test/javassist/JvstTest2.java
@@ -3,6 +3,8 @@ package javassist;
import java.io.*;
import java.net.URL;
import java.lang.reflect.Method;
+
+import javassist.bytecode.ClassFile;
import javassist.expr.*;
public class JvstTest2 extends JvstTestRoot {
diff --git a/src/test/javassist/JvstTest4.java b/src/test/javassist/JvstTest4.java
index 67c229fa..93177f6e 100644
--- a/src/test/javassist/JvstTest4.java
+++ b/src/test/javassist/JvstTest4.java
@@ -122,7 +122,8 @@ public class JvstTest4 extends JvstTestRoot {
cc2.rebuildClassFile();
cc2.writeFile();
Object obj = make(cc.getName());
- assertEquals(4, invoke(obj, "run"));
+ assertEquals("test4.Rename2", obj.getClass().getName());
+ assertEquals(14, invoke(obj, "run"));
}
public void testRename2() throws Exception {
diff --git a/src/test/javassist/bytecode/BytecodeTest.java b/src/test/javassist/bytecode/BytecodeTest.java
index 27fa0b5a..4b88852b 100644
--- a/src/test/javassist/bytecode/BytecodeTest.java
+++ b/src/test/javassist/bytecode/BytecodeTest.java
@@ -66,7 +66,7 @@ public class BytecodeTest extends TestCase {
assertEquals(LongVector.ASIZE * LongVector.VSIZE, vec.capacity());
int size = LongVector.ASIZE * LongVector.VSIZE * 3;
for (int i = 0; i < size; i++) {
- vec.addElement(new IntegerInfo(i));
+ vec.addElement(new IntegerInfo(i, i));
assertEquals(i, ((IntegerInfo)vec.elementAt(i)).value);
assertEquals(i + 1, vec.size());
}
@@ -75,7 +75,7 @@ public class BytecodeTest extends TestCase {
vec = new LongVector(size - 5);
assertEquals(size, vec.capacity());
for (int i = 0; i < size; i++) {
- vec.addElement(new IntegerInfo(i));
+ vec.addElement(new IntegerInfo(i, i));
assertEquals(i, ((IntegerInfo)vec.elementAt(i)).value);
assertEquals(i + 1, vec.size());
}
@@ -558,6 +558,199 @@ public class BytecodeTest extends TestCase {
assertEquals(bs2[i], bos2[i]);
}
+ public void testConstInfos() throws Exception {
+ int n = 1;
+ Utf8Info ui1 = new Utf8Info("test", n++);
+ Utf8Info ui2 = new Utf8Info("te" + "st", n++);
+ Utf8Info ui3 = new Utf8Info("test2", n++);
+ assertTrue(ui1.hashCode() == ui2.hashCode());
+ assertTrue(ui1.equals(ui1));
+ assertTrue(ui1.equals(ui2));
+ assertFalse(ui1.equals(ui3));
+ assertFalse(ui1.equals(null));
+
+ ClassInfo ci1 = new ClassInfo(ui1.index, n++);
+ ClassInfo ci2 = new ClassInfo(ui1.index, n++);
+ ClassInfo ci3 = new ClassInfo(ui2.index, n++);
+ ClassInfo ci4 = new ClassInfo(ui3.index, n++);
+ assertTrue(ci1.hashCode() == ci2.hashCode());
+ assertTrue(ci1.equals(ci1));
+ assertTrue(ci1.equals(ci2));
+ assertFalse(ci1.equals(ci3));
+ assertFalse(ci1.equals(ci4));
+ assertFalse(ci1.equals(ui1));
+ assertFalse(ci1.equals(null));
+
+ NameAndTypeInfo ni1 = new NameAndTypeInfo(ui1.index, ui3.index, n++);
+ NameAndTypeInfo ni2 = new NameAndTypeInfo(ui1.index, ui3.index, n++);
+ NameAndTypeInfo ni3 = new NameAndTypeInfo(ui1.index, ui1.index, n++);
+ NameAndTypeInfo ni4 = new NameAndTypeInfo(ui3.index, ui3.index, n++);
+ assertTrue(ni1.hashCode() == ni2.hashCode());
+ assertTrue(ni1.equals(ni1));
+ assertTrue(ni1.equals(ni2));
+ assertFalse(ni1.equals(ni3));
+ assertFalse(ni1.equals(ni4));
+ assertFalse(ni1.equals(ci1));
+ assertFalse(ni1.equals(null));
+
+ MethodrefInfo mi1 = new MethodrefInfo(ui1.index, ui3.index, n++);
+ MethodrefInfo mi2 = new MethodrefInfo(ui1.index, ui3.index, n++);
+ MethodrefInfo mi3 = new MethodrefInfo(ui1.index, ui1.index, n++);
+ MethodrefInfo mi4 = new MethodrefInfo(ui2.index, ui3.index, n++);
+ assertTrue(mi1.hashCode() == mi2.hashCode());
+ assertTrue(mi1.equals(mi1));
+ assertTrue(mi1.equals(mi2));
+ assertFalse(mi1.equals(mi3));
+ assertFalse(mi1.equals(mi4));
+ assertFalse(mi1.equals(ci1));
+ assertFalse(mi1.equals(null));
+
+ FieldrefInfo field1 = new FieldrefInfo(ui1.index, ui3.index, n++);
+ FieldrefInfo field2 = new FieldrefInfo(ui1.index, ui1.index, n++);
+ FieldrefInfo field3 = new FieldrefInfo(ui1.index, ui1.index, n++);
+ InterfaceMethodrefInfo intf1 = new InterfaceMethodrefInfo(ui1.index, ui3.index, n++);
+ InterfaceMethodrefInfo intf2 = new InterfaceMethodrefInfo(ui1.index, ui3.index, n++);
+ assertFalse(mi1.equals(field1));
+ assertFalse(field1.equals(mi1));
+ assertTrue(field2.equals(field3));
+ assertFalse(mi1.equals(field2));
+ assertFalse(mi1.equals(intf1));
+ assertFalse(intf1.equals(mi1));
+ assertTrue(intf1.equals(intf2));
+
+ StringInfo si1 = new StringInfo(ui1.index, n++);
+ StringInfo si2 = new StringInfo(ui1.index, n++);
+ StringInfo si3 = new StringInfo(ui2.index, n++);
+ assertTrue(si1.hashCode() == si2.hashCode());
+ assertTrue(si1.equals(si1));
+ assertTrue(si1.equals(si2));
+ assertFalse(si1.equals(si3));
+ assertFalse(si1.equals(ci1));
+ assertFalse(si1.equals(null));
+
+ IntegerInfo ii1 = new IntegerInfo(12345, n++);
+ IntegerInfo ii2 = new IntegerInfo(12345, n++);
+ IntegerInfo ii3 = new IntegerInfo(-12345, n++);
+ assertTrue(ii1.hashCode() == ii2.hashCode());
+ assertTrue(ii1.equals(ii1));
+ assertTrue(ii1.equals(ii2));
+ assertFalse(ii1.equals(ii3));
+ assertFalse(ii1.equals(ci1));
+ assertFalse(ii1.equals(null));
+
+ FloatInfo fi1 = new FloatInfo(12345.0F, n++);
+ FloatInfo fi2 = new FloatInfo(12345.0F, n++);
+ FloatInfo fi3 = new FloatInfo(-12345.0F, n++);
+ assertTrue(fi1.hashCode() == fi2.hashCode());
+ assertTrue(fi1.equals(fi1));
+ assertTrue(fi1.equals(fi2));
+ assertFalse(fi1.equals(fi3));
+ assertFalse(fi1.equals(ci1));
+ assertFalse(fi1.equals(null));
+
+ LongInfo li1 = new LongInfo(12345L, n++);
+ LongInfo li2 = new LongInfo(12345L, n++);
+ LongInfo li3 = new LongInfo(-12345L, n++);
+ assertTrue(li1.hashCode() == li2.hashCode());
+ assertTrue(li1.equals(li1));
+ assertTrue(li1.equals(li2));
+ assertFalse(li1.equals(li3));
+ assertFalse(li1.equals(ci1));
+ assertFalse(li1.equals(null));
+
+ DoubleInfo di1 = new DoubleInfo(12345.0, n++);
+ DoubleInfo di2 = new DoubleInfo(12345.0, n++);
+ DoubleInfo di3 = new DoubleInfo(-12345.0, n++);
+ assertTrue(di1.hashCode() == di2.hashCode());
+ assertTrue(di1.equals(di1));
+ assertTrue(di1.equals(di2));
+ assertFalse(di1.equals(di3));
+ assertFalse(di1.equals(ci1));
+ assertFalse(di1.equals(null));
+ }
+
+ public void testConstInfoAdd() {
+ ConstPool cp = new ConstPool("test.Tester");
+ assertEquals("test.Tester", cp.getClassName());
+ int n0 = cp.addClassInfo("test.Foo");
+ assertEquals(n0, cp.addClassInfo("test.Foo"));
+ int n1 = cp.addUtf8Info("test.Bar");
+ assertEquals(n1, cp.addUtf8Info("test.Bar"));
+ int n2 = cp.addUtf8Info("()V");
+ assertEquals(n2, cp.addUtf8Info("()V"));
+ assertTrue(n1 != n2);
+ int n3 = cp.addNameAndTypeInfo(n1, n2);
+ assertEquals(n3, cp.addNameAndTypeInfo(n1, n2));
+ assertEquals(n3, cp.addNameAndTypeInfo("test.Bar", "()V"));
+ int n4 = cp.addNameAndTypeInfo("test.Baz", "()V");
+ assertTrue(n3 != n4);
+ assertTrue(n3 != cp.addNameAndTypeInfo(cp.addUtf8Info("test.Baz"), n2));
+ int n5 = cp.addFieldrefInfo(n0, n3);
+ assertEquals(n5, cp.addFieldrefInfo(n0, n3));
+ assertTrue(n5 != cp.addFieldrefInfo(n0, n4));
+ assertTrue(cp.addMethodrefInfo(n0, n3) == cp.addMethodrefInfo(n0, n3));
+ assertTrue(cp.addMethodrefInfo(n0, "test", "()B") == cp.addMethodrefInfo(n0, "test", "()B"));
+ assertTrue(cp.addMethodrefInfo(n0, "test", "()B") != cp.addMethodrefInfo(n0, "test", "()I"));
+ assertTrue(n5 != cp.addInterfaceMethodrefInfo(n0, n3));
+ assertTrue(cp.addInterfaceMethodrefInfo(n0, "test", "()B")
+ == cp.addInterfaceMethodrefInfo(n0, "test", "()B"));
+ assertTrue(cp.addInterfaceMethodrefInfo(n0, "test", "()B")
+ != cp.addInterfaceMethodrefInfo(n0, "test", "()I"));
+ int n6 = cp.addStringInfo("foobar");
+ assertEquals(n6, cp.addStringInfo("foobar"));
+ assertTrue(n6 != cp.addStringInfo("foobar2"));
+ int n7 = cp.addIntegerInfo(123);
+ assertEquals(n7, cp.addIntegerInfo(123));
+ assertTrue(n7 != cp.addIntegerInfo(-123));
+ int n8 = cp.addFloatInfo(123);
+ assertEquals(n8, cp.addFloatInfo(123.0F));
+ assertTrue(n8 != cp.addFloatInfo(-123.0F));
+ int n9 = cp.addLongInfo(1234L);
+ assertEquals(n9, cp.addLongInfo(1234L));
+ assertTrue(n9 != cp.addLongInfo(-1234L));
+ int n10 = cp.addDoubleInfo(1234.0);
+ assertEquals(n10, cp.addDoubleInfo(1234.0));
+ assertTrue(n10 != cp.addDoubleInfo(-1234.0));
+
+ cp.prune();
+ assertEquals(n1, cp.addUtf8Info("test.Bar"));
+ assertEquals(n0, cp.addClassInfo("test.Foo"));
+ assertEquals(n10, cp.addDoubleInfo(1234.0));
+ }
+
+ public void testRenameInConstPool() {
+ ConstPool cp = new ConstPool("test.Tester");
+ int n1 = cp.addClassInfo("test.Foo");
+ int n2 = cp.addClassInfo("test.Bar");
+ int n3 = cp.addClassInfo("test.Baz");
+ int n4 = cp.addNameAndTypeInfo("foo", "(Ltest/Foo;)V");
+ int n5 = cp.addNameAndTypeInfo("bar", "(Ltest/Bar;)V");
+ int n6 = cp.addNameAndTypeInfo("baz", "(Ltest/Baz;)V");
+ int n7 = cp.addClassInfo("[Ltest/Foo;");
+ int n8 = cp.addClassInfo("[Ltest/Bar;");
+
+ cp.renameClass("test/Foo", "test/Foo2");
+ assertEquals("test.Foo2", cp.getClassInfo(n1));
+ assertEquals("(Ltest/Foo2;)V", cp.getUtf8Info(cp.getNameAndTypeDescriptor(n4)));
+ assertTrue(cp.addClassInfo("test.Foo2") == n1);
+ assertTrue(cp.addClassInfo("test.Foo") != n1);
+ assertTrue(cp.addNameAndTypeInfo("foo", "(Ltest/Foo2;)V") == n4);
+ assertTrue(cp.addNameAndTypeInfo("foo", "(Ltest/Foo;)V") != n4);
+ assertEquals("[Ltest.Foo2;", cp.getClassInfo(n7));
+
+ ClassMap map = new ClassMap();
+ map.put("test.Bar", "test.Bar2");
+ map.put("test.Baz", "test.Baz2");
+ cp.renameClass(map);
+ assertEquals("test.Bar2", cp.getClassInfo(n2));
+ assertEquals("(Ltest/Bar2;)V", cp.getUtf8Info(cp.getNameAndTypeDescriptor(n5)));
+ assertTrue(cp.addClassInfo("test.Bar2") == n2);
+ assertTrue(cp.addClassInfo("test.Bar") != n2);
+ assertTrue(cp.addNameAndTypeInfo("bar", "(Ltest/Bar2;)V") == n5);
+ assertTrue(cp.addNameAndTypeInfo("bar", "(Ltest/Bar;)V") != n5);
+ assertEquals("[Ltest.Bar2;", cp.getClassInfo(n8));
+ }
+
public static void main(String[] args) {
// junit.textui.TestRunner.run(suite());
junit.awtui.TestRunner.main(new String[] {
diff --git a/src/test/test4/Rename.java b/src/test/test4/Rename.java
index 1ded1f69..b2ff794e 100644
--- a/src/test/test4/Rename.java
+++ b/src/test/test4/Rename.java
@@ -4,6 +4,10 @@ interface IRename {
Rename foo(Rename r);
}
+class RenameB {
+ int foo() { return 10; }
+}
+
public class Rename implements IRename {
int value = 3;
Rename next = null;
@@ -19,6 +23,8 @@ public class Rename implements IRename {
public int run() {
next = new Rename();
next.value = 4;
- return foo(this).value;
+ RenameB rb = new RenameB();
+ return foo(this).value + rb.foo();
}
}
+