@Override public ClassfileBinaryParser newInstance() { return new ClassfileBinaryParser(); } }) {
/** * Get a string from the constant pool, and interpret it as a class name by replacing '/' with '.'. */ private String getConstantPoolClassName(final int CpIdx) { return getConstantPoolString(CpIdx, /* replaceSlashWithDot = */ true, /* stripLSemicolon = */ false); }
/** Get a string from the constant pool, optionally replacing '/' with '.'. */ private String getConstantPoolString(final int cpIdx, final boolean replaceSlashWithDot, final boolean stripLSemicolon) { final int constantPoolStringOffset = getConstantPoolStringOffset(cpIdx, /* subFieldIdx = */ 0); return constantPoolStringOffset == 0 ? null : readString(constantPoolStringOffset, replaceSlashWithDot, stripLSemicolon); }
/** * Get the first UTF8 byte of a string in the constant pool, or '\0' if the string is null or empty. */ private byte getConstantPoolStringFirstByte(final int cpIdx) { final int constantPoolStringOffset = getConstantPoolStringOffset(cpIdx, /* subFieldIdx = */ 0); if (constantPoolStringOffset == 0) { return '\0'; } final int utfLen = readUnsignedShort(constantPoolStringOffset); if (utfLen == 0) { return '\0'; } return buf[constantPoolStringOffset + 2]; }
if (readInt() != 0xCAFEBABE) { throw new IOException("Classfile " + relativePath + " does not have correct classfile magic number"); readUnsignedShort(); readUnsignedShort(); final int cpCount = readUnsignedShort(); tag[i] = readUnsignedByte(); offset[i] = curr; switch (tag[i]) { case 1: // Modified UTF8 final int strLen = readUnsignedShort(); skip(strLen); break; case 3: // int, short, char, byte, boolean are all represented by Constant_INTEGER case 4: // float skip(4); break; case 5: // long case 6: // double skip(8); indirectStringRefs[i] = readUnsignedShort(); case 10: // method ref case 11: // interface ref skip(4);
final int tag = (char) readUnsignedByte(); switch (tag) { case 'B': return Byte.valueOf((byte) readInt(offset[readUnsignedShort()])); case 'C': return Character.valueOf((char) readInt(offset[readUnsignedShort()])); case 'D': return Double.valueOf(Double.longBitsToDouble(readLong(offset[readUnsignedShort()]))); case 'F': return Float.valueOf(Float.intBitsToFloat(readInt(offset[readUnsignedShort()]))); case 'I': return Integer.valueOf(readInt(offset[readUnsignedShort()])); case 'J': return Long.valueOf(readLong(offset[readUnsignedShort()])); case 'S': return Short.valueOf((short) readInt(offset[readUnsignedShort()])); case 'Z': return Boolean.valueOf(readInt(offset[readUnsignedShort()]) != 0); case 's': return getConstantPoolString(readUnsignedShort()); case 'e': { final String className = getConstantPoolClassDescriptor(readUnsignedShort()); final String constName = getConstantPoolString(readUnsignedShort()); return new AnnotationEnumValue(className, constName); final String classRefTypeDescriptor = getConstantPoolString(readUnsignedShort()); return new AnnotationClassRef(classRefTypeDescriptor); case '@':
/** Read annotation entry from classfile. */ private AnnotationInfo readAnnotation() throws IOException, InterruptedException { // Lcom/xyz/Annotation; -> Lcom.xyz.Annotation; final String annotationClassName = getConstantPoolClassDescriptor(readUnsignedShort()); final int numElementValuePairs = readUnsignedShort(); List<AnnotationParamValue> paramVals = null; if (numElementValuePairs > 0) { paramVals = new ArrayList<>(numElementValuePairs); } for (int i = 0; i < numElementValuePairs; i++) { final String paramName = getConstantPoolString(readUnsignedShort()); // skip(2); // element_name_index final Object paramValue = readAnnotationElementValue(); paramVals.add(new AnnotationParamValue(paramName, paramValue)); } return new AnnotationInfo(annotationClassName, paramVals); }
case 8: // String return getConstantPoolString(cpIdx, /* subFieldIdx = */ 0); case 3: // int, short, char, byte, boolean are all represented by Constant_INTEGER final int intVal = readInt(offset[cpIdx]); switch (fieldTypeDescriptorFirstChar) { case 'I': return Float.valueOf(Float.intBitsToFloat(readInt(offset[cpIdx]))); case 5: // long return Long.valueOf(readLong(offset[cpIdx])); case 6: // double return Double.valueOf(Double.longBitsToDouble(readLong(offset[cpIdx]))); default:
/** * Compare a string in the constant pool with a given constant, without constructing the String object. */ private boolean constantPoolStringEquals(final int cpIdx, final String otherString) { final int strOffset = getConstantPoolStringOffset(cpIdx, /* subFieldIdx = */ 0); if (strOffset == 0) { return otherString == null; } final int strLen = readUnsignedShort(strOffset); final int otherLen = otherString.length(); if (strLen != otherLen) { return false; } final int strStart = strOffset + 2; for (int i = 0; i < strLen; i++) { if ((char) (buf[strStart + i] & 0xff) != otherString.charAt(i)) { return false; } } return true; }
/** * Get a string from the constant pool. * * @param cpIdx * the constant pool index * @param subFieldIdx * should be 0 for CONSTANT_Utf8, CONSTANT_Class and CONSTANT_String, and for * CONSTANT_NameAndType_info, fetches the name for value 0, or the type descriptor for value 1. */ private String getConstantPoolString(final int cpIdx, final int subFieldIdx) { final int constantPoolStringOffset = getConstantPoolStringOffset(cpIdx, subFieldIdx); return constantPoolStringOffset == 0 ? null : readString(constantPoolStringOffset, /* replaceSlashWithDot = */ false, /* stripLSemicolon = */ false); }
/** * Get a string from the constant pool representing an internal string descriptor for a class name * ("Lcom/xyz/MyClass;"), and interpret it as a class name by replacing '/' with '.', and removing the leading * "L" and the trailing ";". */ private String getConstantPoolClassDescriptor(final int CpIdx) { return getConstantPoolString(CpIdx, /* replaceSlashWithDot = */ true, /* stripLSemicolon = */ true); }
/** Get a string from the constant pool. */ private String getConstantPoolString(final int cpIdx) { return getConstantPoolString(cpIdx, /* subFieldIdx = */ 0); }