📄 classreader.java
字号:
}
break;
case ClassWriter.TYPE_INSN:
cv.visitTypeInsn(opcode, readClass(v + 1, c));
v += 3;
break;
case ClassWriter.IINC_INSN:
cv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
v += 3;
break;
// case MANA_INSN:
default:
cv.visitMultiANewArrayInsn(readClass(v + 1, c), b[v + 3] & 0xFF);
v += 4;
break;
}
}
l = labels[codeEnd - codeStart];
if (l != null) {
cv.visitLabel(l);
}
// visits the try catch entries
j = readUnsignedShort(v); v += 2;
for ( ; j > 0; --j) {
Label start = labels[readUnsignedShort(v)];
Label end = labels[readUnsignedShort(v + 2)];
Label handler = labels[readUnsignedShort(v + 4)];
int type = readUnsignedShort(v + 6);
if (type == 0) {
cv.visitTryCatchBlock(start, end, handler, null);
} else {
cv.visitTryCatchBlock(start, end, handler, readUTF8(items[type], c));
}
v += 8;
}
// visits the local variable table
j = readUnsignedShort(v); v += 2;
if (!skipDebug) {
for ( ; j > 0; --j) {
String attrName = readUTF8(v, c);
if (attrName.equals("LocalVariableTable")) {
k = readUnsignedShort(v + 6);
w = v + 8;
for ( ; k > 0; --k) {
label = readUnsignedShort(w);
Label start = labels[label];
label += readUnsignedShort(w + 2);
Label end = labels[label];
cv.visitLocalVariable(
readUTF8(w + 4, c),
readUTF8(w + 6, c),
start,
end,
readUnsignedShort(w + 8));
w += 10;
}
}
v += 6 + readInt(v + 2);
}
}
// visits the other attributes
while (cattrs != null) {
attr = cattrs.next;
cattrs.next = null;
cv.visitAttribute(cattrs);
cattrs = attr;
}
// visits the max stack and max locals values
cv.visitMaxs(maxStack, maxLocals);
}
}
// visits the class attributes
Attribute last = null;
attr = clattrs;
while (attr != null) {
Attribute next = attr.next;
attr.next = last;
last = attr;
attr = next;
}
while (last != null) {
attr = last.next;
last.next = null;
classVisitor.visitAttribute(last);
last = attr;
}
// visits the end of the class
classVisitor.visitEnd();
}
// --------------------------------------------------------------------------
// Utility methods: low level parsing
// --------------------------------------------------------------------------
/**
* Returns the start index of the constant pool item in {@link #b b}, plus
* one. <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param item the index a constant pool item.
* @return the start index of the constant pool item in {@link #b b}, plus
* one.
*/
public int getItem (final int item) {
return items[item];
}
/**
* Reads a byte value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
*/
public int readByte (final int index) {
return b[index] & 0xFF;
}
/**
* Reads an unsigned short value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
*/
public int readUnsignedShort (final int index) {
byte[] b = this.b;
return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
}
/**
* Reads a signed short value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
*/
public short readShort (final int index) {
byte[] b = this.b;
return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
}
/**
* Reads a signed int value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
*/
public int readInt (final int index) {
byte[] b = this.b;
return ((b[index] & 0xFF) << 24) |
((b[index + 1] & 0xFF) << 16) |
((b[index + 2] & 0xFF) << 8) |
(b[index + 3] & 0xFF);
}
/**
* Reads a signed long value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
*/
public long readLong (final int index) {
long l1 = readInt(index);
long l0 = readInt(index + 4) & 0xFFFFFFFFL;
return (l1 << 32) | l0;
}
/**
* Reads an UTF8 string constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index the start index of an unsigned short value in {@link #b b},
* whose value is the index of an UTF8 constant pool item.
* @param buf buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified UTF8 item.
*/
public String readUTF8 (int index, final char[] buf) {
// consults cache
int item = readUnsignedShort(index);
String s = strings[item];
if (s != null) {
return s;
}
// computes the start index of the CONSTANT_Utf8 item in b
index = items[item];
// reads the length of the string (in bytes, not characters)
int utfLen = readUnsignedShort(index);
index += 2;
// parses the string bytes
int endIndex = index + utfLen;
byte[] b = this.b;
int strLen = 0;
int c, d, e;
while (index < endIndex) {
c = b[index++] & 0xFF;
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
buf[strLen++] = (char)c;
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
d = b[index++];
buf[strLen++] = (char)(((c & 0x1F) << 6) | (d & 0x3F));
break;
default:
// 1110 xxxx 10xx xxxx 10xx xxxx
d = b[index++];
e = b[index++];
buf[strLen++] =
(char)(((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F));
break;
}
}
s = new String(buf, 0, strLen);
strings[item] = s;
return s;
}
/**
* Reads a class constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index the start index of an unsigned short value in {@link #b b},
* whose value is the index of a class constant pool item.
* @param buf buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified class item.
*/
public String readClass (final int index, final char[] buf) {
// computes the start index of the CONSTANT_Class item in b
// and reads the CONSTANT_Utf8 item designated by
// the first two bytes of this CONSTANT_Class item
return readUTF8(items[readUnsignedShort(index)], buf);
}
/**
* Reads a numeric or string constant pool item in {@link #b b}. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param item the index of a constant pool item.
* @param buf buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized.
* @return the {@link java.lang.Integer Integer}, {@link java.lang.Float
* Float}, {@link java.lang.Long Long}, {@link java.lang.Double Double},
* {@link String String} or {@link Type Type} corresponding to the given
* constant pool item.
*/
public Object readConst (final int item, final char[] buf) {
int index = items[item];
switch (b[index - 1]) {
case ClassWriter.INT:
return new Integer(readInt(index));
case ClassWriter.FLOAT:
return new Float(Float.intBitsToFloat(readInt(index)));
case ClassWriter.LONG:
return new Long(readLong(index));
case ClassWriter.DOUBLE:
return new Double(Double.longBitsToDouble(readLong(index)));
case ClassWriter.CLASS:
String s = readUTF8(index, buf);
return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";");
//case ClassWriter.STR:
default:
return readUTF8(index, buf);
}
}
/**
* Reads an attribute in {@link #b b}.
*
* @param attrs prototypes of the attributes that must be parsed during the
* visit of the class. Any attribute whose type is not equal to the type
* of one the prototypes is ignored (i.e. an empty {@link Attribute}
* instance is returned).
* @param type the type of the attribute.
* @param off index of the first byte of the attribute's content in {@link #b
* b}. The 6 attribute header bytes, containing the type and the length
* of the attribute, are not taken into account here (they have already
* been read).
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link #readUTF8 readUTF8}, {@link
* #readClass(int,char[]) readClass} or {@link #readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in
* {@link #b b}, or -1 if the attribute to be read is not a code
* attribute. The 6 attribute header bytes, containing the type and the
* length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return the attribute that has been read, or <tt>null</tt> to skip this
* attribute.
*/
protected Attribute readAttribute (
final Attribute[] attrs,
final String type,
final int off,
final int len,
final char[] buf,
final int codeOff,
final Label[] labels)
{
for (int i = 0; i < attrs.length; ++i) {
if (attrs[i].type.equals(type)) {
return attrs[i].read(this, off, len, buf, codeOff, labels);
}
}
return new Attribute(type);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -