Created
February 17, 2013 15:41
-
-
Save Xyene/4971929 to your computer and use it in GitHub Desktop.
Ultra-fast Java bytecode constant pool parser & DOM-style container.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.sf.jbl.introspection; | |
import net.sf.jbl.util.ByteStream; | |
public class CPool implements Opcode { | |
Constant[] items; | |
int threshold; | |
short index = 0; | |
ByteStream vec; | |
public CPool(int size) { | |
items = new Constant[size]; | |
threshold = (int) (size * 0.75D); | |
vec = ByteStream.writeStream(threshold); | |
} | |
CPool(ByteStream in) { | |
short len = in.readShort(); | |
items = new Constant[len]; | |
int start = in.position(); | |
for (short i = 1; i != len; i++) { | |
byte tag = in.readByte(); | |
Constant item = new Constant(i, tag); | |
switch (tag) { | |
case TAG_FIELD: | |
case TAG_METHOD: | |
case TAG_INTERFACE_METHOD: | |
item.set_(tag, in.readShort(), in.readShort()); | |
item.init = false; | |
break; | |
case TAG_INTEGER: | |
item.set(tag, in.readInt()); | |
break; | |
case TAG_FLOAT: | |
item.set(tag, in.readFloat()); | |
break; | |
case TAG_DESCRIPTOR: | |
item.set_(tag, in.readShort(), in.readShort()); | |
item.init = false; | |
break; | |
case TAG_LONG: | |
item.set(tag, in.readLong()); | |
++i; | |
break; | |
case TAG_DOUBLE: | |
item.set(tag, in.readDouble()); | |
++i; | |
break; | |
case TAG_UTF_STRING: | |
item.set(tag, in.read(in.readShort())); | |
item.init = false; | |
break; | |
case TAG_STRING: | |
case TAG_CLASS: | |
item.set(tag, in.readShort()); | |
item.init = false; | |
break; | |
} | |
item.next = items[i]; | |
items[i] = item; | |
} | |
threshold = (int) (0.75D * len); | |
index = len; | |
vec = in.forkWrite(start, in.position()); | |
} | |
public int newConst(Object cst) { | |
if (cst instanceof Integer) { | |
return newInt(((Integer) cst).intValue()); | |
} else if (cst instanceof Byte) { | |
return newInt(((Byte) cst).intValue()); | |
} else if (cst instanceof Character) { | |
return newInt(((Character) cst).charValue()); | |
} else if (cst instanceof Short) { | |
int val = ((Short) cst).intValue(); | |
return newInt(val); | |
} else if (cst instanceof Boolean) { | |
return newInt(((Boolean) cst).booleanValue() ? 1 : 0); | |
} else if (cst instanceof Float) { | |
return newFloat(((Float) cst).floatValue()); | |
} else if (cst instanceof Long) { | |
return newLong(((Long) cst).longValue()); | |
} else if (cst instanceof Double) { | |
return newDouble(((Double) cst).doubleValue()); | |
} else if (cst instanceof String) { | |
return newString((String) cst); | |
} | |
return -1; //TODO: the other types | |
} | |
//TODO: getdouble etc | |
public int newUTF(String value) { | |
Constant result = get(TAG_UTF_STRING, value); | |
if (result == null) { | |
vec.writeByte(TAG_UTF_STRING).writeUTF(value); | |
(result = new Constant(index++)).set_(TAG_UTF_STRING, value); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newString(String value) { | |
Constant result = get(TAG_STRING, value); | |
if (result == null) { | |
vec.writeByte(TAG_STRING).writeShort(newUTF(value)); | |
(result = new Constant(index++)).set(TAG_UTF_STRING, value); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newClass(String value) { | |
Constant result = get(TAG_CLASS, value); | |
if (result == null) { | |
vec.writeByte(TAG_CLASS).writeShort(newUTF(value)); | |
(result = new Constant(index++)).set_(TAG_CLASS, value); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newField(String owner, String name, String desc) { | |
Constant result = get(TAG_FIELD, owner, name, desc); | |
if (result == null) { | |
vec.writeByte(TAG_FIELD).writeShort(newClass(owner)).writeShort(newNameType(name, desc)); | |
(result = new Constant(index++)).set_(TAG_FIELD, owner, name, desc); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newMethod(String owner, String name, String desc) { | |
Constant result = get(TAG_METHOD, owner, name, desc); | |
if (result == null) { | |
vec.writeByte(TAG_METHOD).writeShort(newClass(owner)).writeShort(newNameType(name, desc)); | |
(result = new Constant(index++)).set_(TAG_METHOD, owner, name, desc); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newInt(int value) { | |
Constant result = get(TAG_INTEGER, value); | |
if (result == null) { | |
vec.writeByte(TAG_INTEGER).writeInt(value); | |
(result = new Constant(index++)).set(TAG_INTEGER, value); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newFloat(float value) { | |
Constant result = get(TAG_FLOAT, value); | |
if (result == null) { | |
vec.writeByte(TAG_FLOAT).writeInt((int) value); | |
(result = new Constant(index++)).set(TAG_FLOAT, value); | |
put(result); | |
} | |
return result.index; | |
} | |
public int newLong(long value) { | |
Constant result = get(TAG_LONG, value); | |
if (result == null) { | |
vec.writeByte(TAG_LONG).writeDouble(value); | |
(result = new Constant(index)).set(TAG_LONG, value); | |
index += 2; | |
put(result); | |
} | |
return result.index; | |
} | |
public int newDouble(double value) { | |
Constant result = get(TAG_DOUBLE, value); | |
if (result == null) { | |
vec.writeByte(TAG_DOUBLE).writeDouble(value); | |
(result = new Constant(index)).set(TAG_DOUBLE, value); | |
index += 2; | |
put(result); | |
} | |
return result.index; | |
} | |
public int newNameType(String name, String desc) { | |
Constant result = get(TAG_DESCRIPTOR, name, desc); | |
if (result == null) { | |
vec.writeByte(TAG_DESCRIPTOR).writeShort(newUTF(name)).writeShort(newUTF(desc)); | |
(result = new Constant(index++)).set_(TAG_DESCRIPTOR, name, desc); | |
put(result); | |
} | |
return result.index; | |
} | |
private Constant get(byte tag, Object... value) { | |
Constant c = items[1]; | |
while (c != null && (c.type != tag || !value.equals(c.complex))) { | |
c = c.next; | |
} | |
return c; | |
} | |
public int size() { | |
return items.length; | |
} | |
public Object get(int i) { | |
Constant c = items[i]; | |
switch (c.type) { | |
case TAG_DESCRIPTOR: | |
case TAG_FIELD: | |
case TAG_METHOD: | |
case TAG_INTERFACE_METHOD: | |
return getDescriptor(i); | |
case TAG_CLASS: | |
case TAG_STRING: | |
return getString(i); | |
case TAG_UTF_STRING: | |
return getUTF(i); | |
default: | |
return c.complex; | |
} | |
} | |
public String getUTF(int index) { | |
Constant con = items[index]; | |
if (con.init) | |
return (String) con.complex; | |
byte[] bytes = (byte[]) con.complex; | |
int size = bytes.length; | |
int pos = 0; | |
char[] buf = new char[size]; | |
int strLen = 0; | |
int c; | |
char cc; | |
while (pos < size) { | |
c = bytes[pos++] & 0xFF; | |
if (c < 0x80) { // 0xxxxxxx | |
buf[strLen++] = (char) c; | |
continue; | |
} else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx | |
cc = (char) (c & 0x1F); | |
} else { // 1110 xxxx 10xx xxxx 10xx xxxx | |
cc = (char) (((c & 0x0F) << 6) | (c & 0x3F)); | |
} | |
buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); | |
} | |
String dec = new String(buf, 0, strLen); | |
items[index].complex = dec; | |
items[index].init = true; | |
return dec; | |
} | |
public String getString(int index) { | |
Constant con = items[index]; | |
if (con.init) | |
return (String) con.complex; | |
items[index].init = true; | |
return (String) (items[index].complex = getUTF((Short) con.complex)); | |
} | |
public String[] getDescriptor(int index) { | |
Constant con = items[index]; | |
if (con.init) | |
return (String[]) con.complex; | |
Object[] comp = (Object[]) con.complex; | |
items[index].init = true; | |
return (String[]) (items[index].complex = new String[]{getUTF((Short) comp[0]), getUTF((Short) comp[1])}); | |
} | |
public double getDouble(int index) { | |
return (Double) items[index].complex; | |
} | |
public long longValue(int index) { | |
return (Long) items[index].complex; | |
} | |
public int getInteger(int index) { | |
return (Integer) items[index].complex; | |
} | |
private void put(Constant i) { | |
if (index > threshold) { | |
int ll = items.length; | |
int nl = (ll << 1) + 1; | |
Constant[] newItems = new Constant[nl]; | |
for (int l = ll - 1; l >= 0; --l) { | |
Constant j = items[l]; | |
while (j != null) { | |
int index = j.index; | |
Constant k = j.next; | |
j.next = newItems[index]; | |
newItems[index] = j; | |
j = k; | |
} | |
} | |
items = newItems; | |
threshold = (int) (nl * 0.75); | |
} | |
int index = i.index; | |
i.next = items[index]; | |
items[index] = i; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment