Skip to content

Instantly share code, notes, and snippets.

@Xyene
Created February 17, 2013 15:41
Show Gist options
  • Save Xyene/4971929 to your computer and use it in GitHub Desktop.
Save Xyene/4971929 to your computer and use it in GitHub Desktop.
Ultra-fast Java bytecode constant pool parser & DOM-style container.
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