private void initConstantPool() throws ClsFormatException { if (myConstantPoolOffsets == null){ BytePointer ptr = new BytePointer(getData(), 0); ConstantPoolIterator iterator = new ConstantPoolIterator(ptr); myConstantPoolOffsets = new int[iterator.getEntryCount()]; myConstantPoolOffsets[0] = iterator.getCurrentOffset(); int index = 1; while (iterator.hasMoreEntries()) { int tag = ClsUtil.readU1(ptr); if (tag == ClsUtil.CONSTANT_Long || tag == ClsUtil.CONSTANT_Double) { myConstantPoolOffsets[index++] = ptr.offset + 8; // takes 2 entries! } iterator.next(); myConstantPoolOffsets[index++] = iterator.getCurrentOffset(); } } }
private ConstantValue readConstant(final BytePointer ptr) throws ClsFormatException { final int tag = ClsUtil.readU1(ptr); switch (tag) { case ClsUtil.CONSTANT_Integer : int value = ClsUtil.readU4(ptr); return new IntegerConstantValue(value); case ClsUtil.CONSTANT_Float: float floatValue = ClsUtil.readFloat(ptr); return new FloatConstantValue(floatValue); case ClsUtil.CONSTANT_Long : int high = ClsUtil.readU4(ptr); int low = ClsUtil.readU4(ptr); long v = ((long)high << 32) | (low & 0xFFFFFFFFL); return new LongConstantValue(v); case ClsUtil.CONSTANT_Double : double doubleValue = ClsUtil.readDouble(ptr); return new DoubleConstantValue(doubleValue); case ClsUtil.CONSTANT_String : int stringIndex = ClsUtil.readU2(ptr); ptr.offset = getOffsetInConstantPool(stringIndex); return new StringConstantValue(ClsUtil.readUtf8Info(ptr)); default : throw new ClsFormatException(); } }
public ConstantPoolIterator(BytePointer ptr) throws ClsFormatException { myPtr = ptr; myPtr.offset = 0; int magic = ClsUtil.readU4(myPtr); if (magic != ClsUtil.MAGIC){ throw new ClsFormatException(); } myPtr.offset += 2; // minor version myPtr.offset += 2; // major version myEntryCount = ClsUtil.readU2(myPtr); if (myEntryCount < 1){ throw new ClsFormatException(); } myCurrentEntryIndex = 1; // Entry at index 0 is included in the count but is not present in the constant pool myCurrentOffset = myPtr.offset; }
public String getQualifiedName() throws ClsFormatException { if (myQualifiedName == null) { BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 2); ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); int tag = ClsUtil.readU1(ptr); if (tag != ClsUtil.CONSTANT_Class){ throw new ClsFormatException(); } ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); myQualifiedName = ClsUtil.readUtf8Info(ptr, '/', '.'); // keep '$' in the names } return myQualifiedName; }
/** * @return fully qualified name of the class' superclass. In case there is no super return "" */ public String getSuperClass() throws ClsFormatException { if (mySuperClassName == null) { BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 4); int index = ClsUtil.readU2(ptr); if (index == 0) { if (CommonClassNames.JAVA_LANG_OBJECT.equals(getQualifiedName())) { mySuperClassName = ""; } else { throw new ClsFormatException(); } } else { ptr.offset = getOffsetInConstantPool(index); mySuperClassName = readClassInfo(ptr); // keep '$' in the name for anonymous classes if (isInterface()) { if (!CommonClassNames.JAVA_LANG_OBJECT.equals(mySuperClassName)) { throw new ClsFormatException(); } } /* else { if (!MakeUtil.isAnonymous(mySuperClassName)) { mySuperClassName = mySuperClassName.replace('$', '.'); } } */ } } return mySuperClassName; }
public String[] getSuperInterfaces() throws ClsFormatException { if (mySuperInterfaces == null) { BytePointer ptr = new BytePointer(getData(), getConstantPoolEnd() + 6); int count = ClsUtil.readU2(ptr); mySuperInterfaces = ArrayUtil.newStringArray(count); BytePointer auxPtr = new BytePointer(ptr.bytes, 0); for (int idx = 0; idx < mySuperInterfaces.length; idx++) { auxPtr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); mySuperInterfaces[idx] = readClassInfo(auxPtr); } } return mySuperInterfaces; }
private void parseConstantPool() throws ClsFormatException { if (myReferences != null) { return; } myReferences = new ArrayList<ReferenceInfo>(); initConstantPool(); final BytePointer ptr = new BytePointer(getData(), 0); ConstantPoolIterator iterator = new ConstantPoolIterator(ptr); while (iterator.hasMoreEntries()) { final int tag = ClsUtil.readU1(ptr); if (tag == ClsUtil.CONSTANT_Fieldref || tag == ClsUtil.CONSTANT_Methodref || tag == ClsUtil.CONSTANT_InterfaceMethodref) { //ptr.offset -= 1; // position to the beginning of the structure MemberReferenceInfo refInfo = readRefStructure(tag, ptr); if (refInfo != null) { myReferences.add(refInfo); } /* String name = mySymbolTable.getSymbol(refInfo.getMemberInfo().getName()); if (name.indexOf('$') < 0 && name.indexOf('<') < 0) { // skip refs to synthetic members myReferences.add(refInfo); } else if ("<init>".equals(name)) { // add instance initializers (constructors) myReferences.add(refInfo); } else { System.out.println("ReferenceInfo thrown out: " + mySymbolTable.getSymbol(refInfo.getClassName()) + "." + mySymbolTable.getSymbol(refInfo.getMemberInfo().getName())); ourWasteReferenceObjectsCounter += 1; } */ } else if (tag == ClsUtil.CONSTANT_Class) { ptr.offset -= 1; // position to the beginning of the structure String className = readClassInfo(ptr); myReferences.add(new ReferenceInfo(getSymbolId(className))); } iterator.next(); } //System.out.println("ourWasteReferenceObjectsCounter = " + ourWasteReferenceObjectsCounter); }
private MemberReferenceInfo readRefStructure(int tag, BytePointer ptr) throws ClsFormatException { /* if (tag != ClsUtil.CONSTANT_Fieldref && tag != ClsUtil.CONSTANT_Methodref && tag != ClsUtil.CONSTANT_InterfaceMethodref) { throw new ClsFormatException(); } */ int classInfoIndex = ClsUtil.readU2(ptr); int nameTypeInfoIndex = ClsUtil.readU2(ptr); ptr.offset = getOffsetInConstantPool(classInfoIndex); if (ClsUtil.CONSTANT_Class != ClsUtil.readU1(ptr)) { throw new ClsFormatException(); } ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); String className = ClsUtil.readUtf8Info(ptr, '/', '.'); // keep '$' in names ptr.offset = getOffsetInConstantPool(nameTypeInfoIndex); if (ClsUtil.CONSTANT_NameAndType != ClsUtil.readU1(ptr)) { throw new ClsFormatException(); } int memberNameIndex = ClsUtil.readU2(ptr); int descriptorIndex = ClsUtil.readU2(ptr); ptr.offset = getOffsetInConstantPool(memberNameIndex); String memberName = ClsUtil.readUtf8Info(ptr); if ((memberName.indexOf('$') >= 0 || memberName.indexOf('<') >= 0) && !CONSTRUCTOR_NAME.equals(memberName)) { // skip refs to synthetic members return null; } ptr.offset = getOffsetInConstantPool(descriptorIndex); String descriptor = ClsUtil.readUtf8Info(ptr); MemberInfo info = ClsUtil.CONSTANT_Fieldref == tag? new FieldInfo(getSymbolId(memberName), getSymbolId(descriptor)) : new MethodInfo(getSymbolId(memberName), getSymbolId(descriptor), CONSTRUCTOR_NAME.equals(memberName)); return new MemberReferenceInfo(getSymbolId(className), info); }
private String readClassInfo(BytePointer ptr) throws ClsFormatException{ final int tag = ClsUtil.readU1(ptr); if (tag != ClsUtil.CONSTANT_Class){ throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.record.tag.expected.another", tag, ClsUtil.CONSTANT_Class)); } int index = ClsUtil.readU2(ptr); return ClsUtil.readUtf8Info(new BytePointer(ptr.bytes, getOffsetInConstantPool(index)), '/', '.'); }
@SuppressWarnings({"HardCodedStringLiteral"}) private ClsAttributeTable readAttributes(BytePointer ptr) throws ClsFormatException { int count = ClsUtil.readU2(ptr); // attributeCount final ClsAttributeTable attributes = new ClsAttributeTable(); while (count-- > 0) { final String attrName = readAttributeName(ptr); if ("Exceptions".equals(attrName)) { attributes.exceptions = readExceptions(ptr); } else if ("Signature".equals(attrName)) { attributes.genericSignature = readSignatureAttribute(ptr); } else if ("SourceFile".equals(attrName)) { attributes.sourceFile = readSourceFileAttribute(ptr); } else if ("ConstantValue".equals(attrName)){ attributes.constantValue = readFieldConstantValue(ptr); } else if ("RuntimeVisibleAnnotations".equals(attrName)) { attributes.runtimeVisibleAnnotations = readAnnotations(ptr); } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { attributes.runtimeInvisibleAnnotations = readAnnotations(ptr); } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) { attributes.runtimeVisibleParameterAnnotations = readParameterAnnotations(ptr); } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) { attributes.runtimeInvisibleParameterAnnotations = readParameterAnnotations(ptr); } else if ("AnnotationDefault".equals(attrName)) { attributes.annotationDefault = readAnnotationMemberValue(new BytePointer(ptr.bytes, ptr.offset + 6)); } gotoNextAttribute(ptr); } return attributes; }
/** Signature_attribute { u2 attribute_name_index; (must be equal to "Signature") u4 attribute_length; (must be equal to 2) u2 signature_index; } */ private String readSignatureAttribute(BytePointer p) throws ClsFormatException { final BytePointer ptr = new BytePointer(p.bytes, p.offset + 2); // position to the length if (ClsUtil.readU4(ptr) != 2) { return null; } ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); return ClsUtil.readUtf8Info(ptr); }
private String[] readExceptions(BytePointer p) throws ClsFormatException{ final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6); // position to the count of exceptions int count = ClsUtil.readU2(ptr); final ArrayList<String> array = new ArrayList<String>(count); while (count-- > 0) { int idx = ClsUtil.readU2(ptr); if (idx != 0) { final String exceptionClass = readClassInfo(new BytePointer(ptr.bytes, getOffsetInConstantPool(idx))); array.add(exceptionClass); } } return ArrayUtil.toStringArray(array); }
private String readSourceFileAttribute(BytePointer p) throws ClsFormatException { BytePointer ptr = new BytePointer(p.bytes, p.offset + 2); // position to the length if (ClsUtil.readU4(ptr) != 2) { return null; } ptr.offset = getOffsetInConstantPool(ClsUtil.readU2(ptr)); String path = ClsUtil.readUtf8Info(ptr); // jdk version 1.3.0 puts full path to the source, but later versions store only short name final int slashIndex = path.lastIndexOf('/'); if (slashIndex >= 0) { path = path.substring(slashIndex + 1, path.length()); } return path; }
private ConstantValue readFieldConstantValue(BytePointer p) throws ClsFormatException{ final BytePointer ptr = new BytePointer(p.bytes, p.offset + 2); if (ClsUtil.readU4(ptr) != 2) { throw new ClsFormatException(); // attribute length must be 2 } int valueIndex = ClsUtil.readU2(ptr); ptr.offset = getOffsetInConstantPool(valueIndex); return readConstant(ptr); }
private AnnotationConstantValue[][] readParameterAnnotations(BytePointer p) throws ClsFormatException { final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6); // position to the number of parameters final int numberOfParams = ClsUtil.readU1(ptr); if (numberOfParams == 0) { return null; } final AnnotationConstantValue[][] annotations = new AnnotationConstantValue[numberOfParams][]; for (int parameterIndex = 0; parameterIndex < numberOfParams; parameterIndex++) { annotations[parameterIndex] = readAnnotationsArray(ptr); } return annotations; }
private AnnotationConstantValue[] readAnnotationsArray(BytePointer ptr) throws ClsFormatException { final int numberOfAnnotations = ClsUtil.readU2(ptr); if (numberOfAnnotations == 0) { return AnnotationConstantValue.EMPTY_ARRAY; } AnnotationConstantValue[] annotations = new AnnotationConstantValue[numberOfAnnotations]; for (int attributeIndex = 0; attributeIndex < numberOfAnnotations; attributeIndex++) { annotations[attributeIndex] = readAnnotation(ptr); } return annotations; }
private AnnotationConstantValue readAnnotation(BytePointer ptr) throws ClsFormatException { final int classInfoIndex = ClsUtil.readU2(ptr); final String qName = readAnnotationClassName(new BytePointer(ptr.bytes, getOffsetInConstantPool(classInfoIndex))); final List<AnnotationNameValuePair> memberValues = new ArrayList<AnnotationNameValuePair>(); final int numberOfPairs = ClsUtil.readU2(ptr); for (int idx = 0; idx < numberOfPairs; idx++) { final int memberNameIndex = ClsUtil.readU2(ptr); final String memberName = ClsUtil.readUtf8Info(ptr.bytes, getOffsetInConstantPool(memberNameIndex)); final ConstantValue memberValue = readAnnotationMemberValue(ptr); memberValues.add(new AnnotationNameValuePair(getSymbolId(memberName), memberValue)); } return new AnnotationConstantValue(getSymbolId(qName), memberValues.toArray(new AnnotationNameValuePair[memberValues.size()])); }
private String readAnnotationClassName(BytePointer ptr) throws ClsFormatException { // TODO: need this method because because of incomplete class format spec at the moment of writing // it is not clear what structure is expected: CONSTANT_Utf8 or CONSTANT_Class final int tag = ClsUtil.readU1(ptr); if (tag == ClsUtil.CONSTANT_Utf8) { return ClsUtil.getTypeText(ptr.bytes, ptr.offset + 2); //skip length } if (tag == ClsUtil.CONSTANT_Class){ ptr.offset -= 1; // rollback return readClassInfo(ptr); } //noinspection HardCodedStringLiteral throw new ClsFormatException(CompilerBundle.message("class.parsing.error.wrong.record.tag.expected.another", tag, "CONSTANT_Utf8(" + ClsUtil.CONSTANT_Utf8 + ") / CONSTANT_Class(" + ClsUtil.CONSTANT_Class + ")")); }
private String readAttributeName(BytePointer p) throws ClsFormatException { final BytePointer ptr = new BytePointer(p.bytes, p.offset); final int nameIndex = ClsUtil.readU2(ptr); ptr.offset = getOffsetInConstantPool(nameIndex); return ClsUtil.readUtf8Info(ptr); }
private static void gotoNextAttribute(BytePointer ptr) throws ClsFormatException { ptr.offset += 2; // skip name index final int length = ClsUtil.readU4(ptr); // important! Do not inline since ptr.offset is also changed inside ClsUtil.readU4() method ptr.offset += length; }
private AnnotationConstantValue[] readAnnotations(BytePointer p) throws ClsFormatException { final BytePointer ptr = new BytePointer(p.bytes, p.offset + 6); return readAnnotationsArray(ptr); }