Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2011 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation Stephan Herrmann - Contribution for bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method /
  
  package org.eclipse.jdt.internal.compiler.classfmt;
  
  import java.io.File;
  import java.util.Arrays;
  
  
  public class ClassFileReader extends ClassFileStruct implements IBinaryType {
  
  	private int accessFlags;
  	private char[] classFileName;
  	private char[] className;
  	private int classNameIndex;
  	private int constantPoolCount;
  	private AnnotationInfo[] annotations;
  	private FieldInfo[] fields;
  	private int fieldsCount;
  
  	// initialized in case the .class file is a nested type
  	private InnerClassInfo innerInfo;
  	private int innerInfoIndex;
  	private InnerClassInfo[] innerInfos;
  	private char[][] interfaceNames;
  	private int interfacesCount;
  	private MethodInfo[] methods;
  	private int methodsCount;
  	private char[] signature;
  	private char[] sourceName;
  	private char[] sourceFileName;
  	private char[] superclassName;
  	private long tagBits;
  	private long version;
  	private char[] enclosingTypeName;
  	private char[][][] missingTypeNames;
  	private int enclosingNameAndTypeIndex;
  	private char[] enclosingMethod;
  
  private static String printTypeModifiers(int modifiers) {
  	java.io.PrintWriter print = new java.io.PrintWriter(out);
  
  	if ((modifiers & .) != 0) print.print("public "); //$NON-NLS-1$
  	if ((modifiers & .) != 0) print.print("private "); //$NON-NLS-1$
  	if ((modifiers & .) != 0) print.print("final "); //$NON-NLS-1$
  	if ((modifiers & .) != 0) print.print("super "); //$NON-NLS-1$
  	if ((modifiers & .) != 0) print.print("interface "); //$NON-NLS-1$
  	if ((modifiers & .) != 0) print.print("abstract "); //$NON-NLS-1$
  	print.flush();
  	return out.toString();
  }
  
  public static ClassFileReader read(File filethrows ClassFormatExceptionIOException {
  	return read(filefalse);
  }
  
  public static ClassFileReader read(File fileboolean fullyInitializethrows ClassFormatExceptionIOException {
  	byte classFileBytes[] = Util.getFileByteContent(file);
  	ClassFileReader classFileReader = new ClassFileReader(classFileBytesfile.getAbsolutePath().toCharArray());
  	if (fullyInitialize) {
  		classFileReader.initialize();
  	}
  	return classFileReader;
  }
  
  public static ClassFileReader read(InputStream streamString fileNamethrows ClassFormatExceptionIOException {
  	return read(streamfileNamefalse);
  }
  
  public static ClassFileReader read(InputStream streamString fileNameboolean fullyInitializethrows ClassFormatExceptionIOException {
  	byte classFileBytes[] = Util.getInputStreamAsByteArray(stream, -1);
  	ClassFileReader classFileReader = new ClassFileReader(classFileBytesfileName.toCharArray());
  	if (fullyInitialize) {
  		classFileReader.initialize();
  	}
  	return classFileReader;
  }
  
  public static ClassFileReader read(
  	java.util.zip.ZipFile zip,
  	String filename)
 		return read(zipfilenamefalse);
 }
 
 public static ClassFileReader read(
 	String filename,
 	boolean fullyInitialize)
 	java.util.zip.ZipEntry ze = zip.getEntry(filename);
 	if (ze == null)
 		return null;
 	byte classFileBytes[] = Util.getZipEntryByteContent(zezip);
 	ClassFileReader classFileReader = new ClassFileReader(classFileBytesfilename.toCharArray());
 	if (fullyInitialize) {
 		classFileReader.initialize();
 	}
 	return classFileReader;
 }
 
 public static ClassFileReader read(String fileNamethrows ClassFormatExceptionjava.io.IOException {
 	return read(fileNamefalse);
 }
 
 public static ClassFileReader read(String fileNameboolean fullyInitializethrows ClassFormatExceptionjava.io.IOException {
 	return read(new File(fileName), fullyInitialize);
 }

Parameters:
classFileBytes Actual bytes of a .class file
fileName Actual name of the file that contains the bytes, can be null
Throws:
ClassFormatException
 
 public ClassFileReader(byte classFileBytes[], char[] fileNamethrows ClassFormatException {
 	this(classFileBytesfileNamefalse);
 }

Parameters:
classFileBytes byte[] Actual bytes of a .class file
fileName char[] Actual name of the file that contains the bytes, can be null
fullyInitialize boolean Flag to fully initialize the new object
Throws:
ClassFormatException
 
 public ClassFileReader(byte[] classFileByteschar[] fileNameboolean fullyInitializethrows ClassFormatException {
 	// This method looks ugly but is actually quite simple, the constantPool is constructed
 	// in 3 passes.  All non-primitive constant pool members that usually refer to other members
 	// by index are tweaked to have their value in inst vars, this minor cost at read-time makes
 	// all subsequent uses of the constant pool element faster.
 	super(classFileBytesnull, 0);
 	this. = fileName;
 	int readOffset = 10;
 	try {
 		this. = ((long)u2At(6) << 16) + u2At(4); // major<<16 + minor
 		this. = u2At(8);
 		// Pass #1 - Fill in all primitive constants
 		this. = new int[this.];
 		for (int i = 1; i < this.i++) {
 			int tag = u1At(readOffset);
 			switch (tag) {
 					this.[i] = readOffset;
 					readOffset += u2At(readOffset + 1);
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					i++;
 					break;
 					this.[i] = readOffset;
 					i++;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 					this.[i] = readOffset;
 					break;
 			}
 		}
 		// Read and validate access flags
 		this. = u2At(readOffset);
 		readOffset += 2;
 
 		// Read the classname, use exception handlers to catch bad format
 		this. = u2At(readOffset);
 		readOffset += 2;
 
 		// Read the superclass name, can be null for java.lang.Object
 		int superclassNameIndex = u2At(readOffset);
 		readOffset += 2;
 		// if superclassNameIndex is equals to 0 there is no need to set a value for the
 		// field this.superclassName. null is fine.
 		if (superclassNameIndex != 0) {
 			this. = getConstantClassNameAt(superclassNameIndex);
 		}
 
 		// Read the interfaces, use exception handlers to catch bad format
 		this. = u2At(readOffset);
 		readOffset += 2;
 		if (this. != 0) {
 			this. = new char[this.][];
 			for (int i = 0; i < this.i++) {
 				this.[i] = getConstantClassNameAt(u2At(readOffset));
 				readOffset += 2;
 			}
 		}
 		// Read the fields, use exception handlers to catch bad format
 		this. = u2At(readOffset);
 		readOffset += 2;
 		if (this. != 0) {
 			FieldInfo field;
 			this. = new FieldInfo[this.];
 			for (int i = 0; i < this.i++) {
 				field = FieldInfo.createField(this.this.readOffset);
 				this.[i] = field;
 				readOffset += field.sizeInBytes();
 			}
 		}
 		// Read the methods
 		this. = u2At(readOffset);
 		readOffset += 2;
 		if (this. != 0) {
 			this. = new MethodInfo[this.];
 			boolean isAnnotationType = (this. & .) != 0;
 			for (int i = 0; i < this.i++) {
 				this.[i] = isAnnotationType
 					? AnnotationMethodInfo.createAnnotationMethod(this.this.readOffset)
 					: MethodInfo.createMethod(this.this.readOffset);
 				readOffset += this.[i].sizeInBytes();
 			}
 		}
 
 		// Read the attributes
 		int attributesCount = u2At(readOffset);
 		readOffset += 2;
 
 		for (int i = 0; i < attributesCounti++) {
 			int utf8Offset = this.[u2At(readOffset)];
 			char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 			if (attributeName.length == 0) {
 				readOffset += (6 + u4At(readOffset + 2));
 				continue;
 			}
 			switch(attributeName[0] ) {
 				case 'E' :
 					if (CharOperation.equals(attributeName.)) {
 						utf8Offset =
 							this.[u2At(this.[u2At(readOffset + 6)] + 1)];
  						this. = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 						this. = u2At(readOffset + 8);
 					}
 					break;
 				case 'D' :
 					if (CharOperation.equals(attributeName.)) {
 					}
 					break;
 				case 'I' :
 					if (CharOperation.equals(attributeName.)) {
 						int innerOffset = readOffset + 6;
 						int number_of_classes = u2At(innerOffset);
 						if (number_of_classes != 0) {
 							innerOffset+= 2;
 							this. = new InnerClassInfo[number_of_classes];
 							for (int j = 0; j < number_of_classesj++) {
 								this.[j] =
 									new InnerClassInfo(this.this.innerOffset);
 								if (this. == this.[j].) {
 									this. = this.[j];
 									this. = j;
 								}
 								innerOffset += 8;
 							}
 							if (this. != null) {
 								char[] enclosingType = this..getEnclosingTypeName();
 								if (enclosingType != null) {
 									this. = enclosingType;
 								}
 							}
 						}
 					} else if (CharOperation.equals(attributeName.)) {
 					}
 					break;
 				case 'S' :
 					if (attributeName.length > 2) {
 						switch(attributeName[1]) {
 							case 'o' :
 								if (CharOperation.equals(attributeName.)) {
 									utf8Offset = this.[u2At(readOffset + 6)];
 									this. = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 								}
 								break;
 							case 'y' :
 								if (CharOperation.equals(attributeName.)) {
 								}
 								break;
 							case 'i' :
 								if (CharOperation.equals(attributeName.)) {
 									utf8Offset = this.[u2At(readOffset + 6)];
 									this. = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 								}
 						}
 					}
 					break;
 				case 'R' :
 					if (CharOperation.equals(attributeName.)) {
 						decodeAnnotations(readOffsettrue);
 					} else if (CharOperation.equals(attributeName.)) {
 						decodeAnnotations(readOffsetfalse);
 					}
 					break;
 				case 'M' :
 					if (CharOperation.equals(attributeName.)) {
 						// decode the missing types
 						int missingTypeOffset = readOffset + 6;
 						int numberOfMissingTypes = u2At(missingTypeOffset);
 						if (numberOfMissingTypes != 0) {
 							this. = new char[numberOfMissingTypes][][];
 							missingTypeOffset += 2;
 							for (int j = 0; j < numberOfMissingTypesj++) {
 								utf8Offset = this.[u2At(this.[u2At(missingTypeOffset)] + 1)];
 								char[] missingTypeConstantPoolName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 								this.[j] = CharOperation.splitOn('/'missingTypeConstantPoolName);
 								missingTypeOffset += 2;
 							}
 						}
 					}
 			}
 			readOffset += (6 + u4At(readOffset + 2));
 		}
 		if (fullyInitialize) {
 		}
 	} catch(ClassFormatException e) {
 		throw e;
 	} catch (Exception e) {
 		throw new ClassFormatException(
 			readOffset);
 	}
 }

Answer the receiver's access flags. The value of the access_flags item is a mask of modifiers used with class and interface declarations.

Returns:
int
 
 public int accessFlags() {
 	return this.;
 }
 
 private void decodeAnnotations(int offsetboolean runtimeVisible) {
 	int numberOfAnnotations = u2At(offset + 6);
 	if (numberOfAnnotations > 0) {
 		int readOffset = offset + 8;
 		AnnotationInfo[] newInfos = null;
 		int newInfoCount = 0;
 		for (int i = 0; i < numberOfAnnotationsi++) {
 			// With the last parameter being 'false', the data structure will not be flushed out
 			AnnotationInfo newInfo = new AnnotationInfo(this.this.readOffsetruntimeVisiblefalse);
 			readOffset += newInfo.readOffset;
 			long standardTagBits = newInfo.standardAnnotationTagBits;
 			if (standardTagBits != 0) {
 				this. |= standardTagBits;
 			} else {
 				if (newInfos == null)
 					newInfos = new AnnotationInfo[numberOfAnnotations - i];
 				newInfos[newInfoCount++] = newInfo;
 			}
 		}
 		if (newInfos == null)
 			return// nothing to record in this.annotations
 
 		if (this. == null) {
 			if (newInfoCount != newInfos.length)
 				System.arraycopy(newInfos, 0, newInfos = new AnnotationInfo[newInfoCount], 0, newInfoCount);
 			this. = newInfos;
 		} else {
 			int length = this..length;
 			AnnotationInfo[] temp = new AnnotationInfo[length + newInfoCount];
 			System.arraycopy(this., 0, temp, 0, length);
 			System.arraycopy(newInfos, 0, templengthnewInfoCount);
 			this. = temp;
 		}
 	}
 }

Returns:
the annotations or null if there is none.
 
 	return this.;
 }

Answer the char array that corresponds to the class name of the constant class. constantPoolIndex is the index in the constant pool that is a constant class entry.

Parameters:
constantPoolIndex int
Returns:
char[]
 
 private char[] getConstantClassNameAt(int constantPoolIndex) {
 	int utf8Offset = this.[u2At(this.[constantPoolIndex] + 1)];
 	return utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
 }

Answer the int array that corresponds to all the offsets of each entry in the constant pool

Returns:
int[]
 
 public int[] getConstantPoolOffsets() {
 	return this.;
 }
 
 public char[] getEnclosingMethod() {
 	if (this. <= 0) {
 		return null;
 	}
 	if (this. == null) {
 		// read the name
 		StringBuffer buffer = new StringBuffer();
 		
 		int nameAndTypeOffset = this.[this.];
 		int utf8Offset = this.[u2At(nameAndTypeOffset + 1)];
 		buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)));
 
 		utf8Offset = this.[u2At(nameAndTypeOffset + 3)];
 		buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)));
 
 		this. = String.valueOf(buffer).toCharArray();
 	}
 	return this.;
 }
 
 /*
  * Answer the resolved compoundName of the enclosing type
  * or null if the receiver is a top level type.
  */
 public char[] getEnclosingTypeName() {
 	return this.;
 }

Answer the receiver's this.fields or null if the array is empty.

Returns:
org.eclipse.jdt.internal.compiler.api.IBinaryField[]
 
 public IBinaryField[] getFields() {
 	return this.;
 }

 
 public char[] getFileName() {
 	return this.;
 }
 
 public char[] getGenericSignature() {
 	return this.;
 }

Answer the source name if the receiver is a inner type. Return null if it is an anonymous class or if the receiver is a top-level class. e.g. public class A { public class B { } public void foo() { class C {} } public Runnable bar() { return new Runnable() { public void run() {} }; } } It returns {'B'} for the member A$B It returns null for A It returns {'C'} for the local class A$1$C It returns null for the anonymous A$1

Returns:
char[]
 
 public char[] getInnerSourceName() {
 	if (this. != null)
 		return this..getSourceName();
 	return null;
 }

Answer the resolved names of the receiver's interfaces in the class file format as specified in section 4.2 of the Java 2 VM spec or null if the array is empty. For example, java.lang.String is java/lang/String.

Returns:
char[][]
 
 public char[][] getInterfaceNames() {
 	return this.;
 }

Answer the receiver's nested types or null if the array is empty. This nested type info is extracted from the inner class attributes. Ask the name environment to find a member type using its compound name

Returns:
org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[]
 
 	// we might have some member types of the current type
 	if (this. == nullreturn null;
 
 	int length = this..length;
 	int startingIndex = this. != null ? this. + 1 : 0;
 	if (length != startingIndex) {
 		IBinaryNestedType[] memberTypes =
 			new IBinaryNestedType[length - this.];
 		int memberTypeIndex = 0;
 		for (int i = startingIndexi < lengthi++) {
 			InnerClassInfo currentInnerInfo = this.[i];
 			int outerClassNameIdx = currentInnerInfo.outerClassNameIndex;
 			int innerNameIndex = currentInnerInfo.innerNameIndex;
 			/*
 			 * Checking that outerClassNameIDx is different from 0 should be enough to determine if an inner class
 			 * attribute entry is a member class, but due to the bug:
 			 * http://dev.eclipse.org/bugs/show_bug.cgi?id=14592
 			 * we needed to add an extra check. So we check that innerNameIndex is different from 0 as well.
 			 *
 			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49879
 			 * From JavaMail 1.2, the class javax.mail.Folder contains an anonymous class in the
 			 * terminateQueue() method for which the inner attribute is boggus.
 			 * outerClassNameIdx is not 0, innerNameIndex is not 0, but the sourceName length is 0.
 			 * So I added this extra check to filter out this anonymous class from the
 			 * member types.
 			 */
 			if (outerClassNameIdx != 0
 				&& innerNameIndex != 0
 				&& outerClassNameIdx == this.
 				&& currentInnerInfo.getSourceName().length != 0) {
 				memberTypes[memberTypeIndex++] = currentInnerInfo;
 			}
 		}
 		if (memberTypeIndex == 0) return null;
 		if (memberTypeIndex != memberTypes.length) {
 			// we need to resize the memberTypes array. Some local or anonymous classes
 			// are present in the current class.
 			System.arraycopy(
 				memberTypes,
 				0,
 				(memberTypes = new IBinaryNestedType[memberTypeIndex]),
 				0,
 				memberTypeIndex);
 		}
 		return memberTypes;
 	}
 	return null;
 }

Answer the receiver's this.methods or null if the array is empty.

Returns:
org.eclipse.jdt.internal.compiler.api.env.IBinaryMethod[]
 
 public IBinaryMethod[] getMethods() {
 	return this.;
 }
 
 /*
 public static void main(String[] args) throws ClassFormatException, IOException {
 	if (args == null || args.length != 1) {
 		System.err.println("ClassFileReader <filename>"); //$NON-NLS-1$
 		System.exit(1);
 	}
 	File file = new File(args[0]);
 	ClassFileReader reader = read(file, true);
 	if (reader.annotations != null) {
 		System.err.println();
 		for (int i = 0; i < reader.annotations.length; i++)
 			System.err.println(reader.annotations[i]);
 	}
 	System.err.print("class "); //$NON-NLS-1$
 	System.err.print(reader.getName());
 	char[] superclass = reader.getSuperclassName();
 	if (superclass != null) {
 		System.err.print(" extends "); //$NON-NLS-1$
 		System.err.print(superclass);
 	}
 	System.err.println();
 	char[][] interfaces = reader.getInterfaceNames();
 	if (interfaces != null && interfaces.length > 0) {
 		System.err.print(" implements "); //$NON-NLS-1$
 		for (int i = 0; i < interfaces.length; i++) {
 			if (i != 0) System.err.print(", "); //$NON-NLS-1$
 			System.err.println(interfaces[i]);
 		}
 	}
 	System.err.println();
 	System.err.println('{');
 	if (reader.fields != null) {
 		for (int i = 0; i < reader.fields.length; i++) {
 			System.err.println(reader.fields[i]);
 			System.err.println();
 		}
 	}
 	if (reader.methods != null) {
 		for (int i = 0; i < reader.methods.length; i++) {
 			System.err.println(reader.methods[i]);
 			System.err.println();
 		}
 	}
 	System.err.println();
 	System.err.println('}');
 }
 */
 public char[][][] getMissingTypeNames() {
 	return this.;
 }

Answer an int whose bits are set according the access constants defined by the VM spec. Set the AccDeprecated and AccSynthetic bits if necessary

Returns:
int
 
 public int getModifiers() {
 	int modifiers;
 	if (this. != null) {
 		modifiers = this..getModifiers()
 	} else {
 		modifiers = this.;
 	}
 	return modifiers;
 }

Answer the resolved name of the type in the class file format as specified in section 4.2 of the Java 2 VM spec. For example, java.lang.String is java/lang/String.

Returns:
char[]
 
 public char[] getName() {
 	return this.;
 }
 
 public char[] getSourceName() {
 	if (this. != null)
 		return this.;
 
 	char[] name = getInnerSourceName(); // member or local scenario
 	if (name == null) {
 		name = getName(); // extract from full name
 		int start;
 		if (isAnonymous()) {
 			start = CharOperation.indexOf('$'name, CharOperation.lastIndexOf('/'name) + 1) + 1;
 		} else {
 			start = CharOperation.lastIndexOf('/'name) + 1;
 		}
 		if (start > 0) {
 			char[] newName = new char[name.length - start];
 			System.arraycopy(namestartnewName, 0, newName.length);
 			name = newName;
 		}
 	}
 	return this. = name;
 }

Answer the resolved name of the receiver's superclass in the class file format as specified in section 4.2 of the Java 2 VM spec or null if it does not have one. For example, java.lang.String is java/lang/String.

Returns:
char[]
 
 public char[] getSuperclassName() {
 	return this.;
 }
 
 public long getTagBits() {
 	return this.;
 }

Answer the major/minor version defined in this class file according to the VM spec. as a long: (major<<16)+minor

Returns:
the major/minor version found
 
 public long getVersion() {
 	return this.;
 }
 
 private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfosFieldInfo[] otherFieldInfos) {
 	int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length;
 	int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length;
 	int index1 = 0;
 	int index2 = 0;
 
 	end : while (index1 < length1 && index2 < length2) {
 		while (currentFieldInfos[index1].isSynthetic()) {
 			if (++index1 >= length1break end;
 		}
 		while (otherFieldInfos[index2].isSynthetic()) {
 			if (++index2 >= length2break end;
 		}
 		if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++]))
 			return true;
 	}
 
 	while (index1 < length1) {
 		if (!currentFieldInfos[index1++].isSynthetic()) return true;
 	}
 	while (index2 < length2) {
 		if (!otherFieldInfos[index2++].isSynthetic()) return true;
 	}
 	return false;
 }
 
 private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfosMethodInfo[] otherMethodInfos) {
 	int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length;
 	int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length;
 	int index1 = 0;
 	int index2 = 0;
 
 	end : while (index1 < length1 && index2 < length2) {
 		while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) {
 			if (++index1 >= length1break end;
 		}
 		while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) {
 			if (++index2 >= length2break end;
 		}
 		if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++]))
 			return true;
 	}
 
 	while (index1 < length1) {
 		if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true;
 	}
 	while (index2 < length2) {
 		if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true;
 	}
 	return false;
 }

Check if the receiver has structural changes compare to the byte array in argument. Structural changes are: - modifiers changes for the class, the this.fields or the this.methods - signature changes for this.fields or this.methods. - changes in the number of this.fields or this.methods - changes for field constants - changes for thrown exceptions - change for the super class or any super interfaces. - changes for member types name or modifiers If any of these changes occurs, the method returns true. false otherwise. The synthetic fields are included and the members are not required to be sorted.

Parameters:
newBytes the bytes of the .class file we want to compare the receiver to
Returns:
boolean Returns true is there is a structural change between the two .class files, false otherwise
 
 public boolean hasStructuralChanges(byte[] newBytes) {
 	return hasStructuralChanges(newBytestruetrue);
 }

Check if the receiver has structural changes compare to the byte array in argument. Structural changes are: - modifiers changes for the class, the this.fields or the this.methods - signature changes for this.fields or this.methods. - changes in the number of this.fields or this.methods - changes for field constants - changes for thrown exceptions - change for the super class or any super interfaces. - changes for member types name or modifiers If any of these changes occurs, the method returns true. false otherwise.

Parameters:
newBytes the bytes of the .class file we want to compare the receiver to
orderRequired a boolean indicating whether the members should be sorted or not
excludesSynthetic a boolean indicating whether the synthetic members should be used in the comparison
Returns:
boolean Returns true is there is a structural change between the two .class files, false otherwise
 
 public boolean hasStructuralChanges(byte[] newBytesboolean orderRequiredboolean excludesSynthetic) {
 	try {
 		ClassFileReader newClassFile =
 			new ClassFileReader(newBytesthis.);
 		// type level comparison
 		// modifiers
 		if (getModifiers() != newClassFile.getModifiers())
 			return true;
 
 		// only consider a portion of the tagbits which indicate a structural change for dependents
 		// e.g. @Override change has no influence outside
 		long OnlyStructuralTagBits = . // different @Target status ?
 			| . // different @Deprecated status ?
 			| . // different @Retention status ?
 			| .// different hierarchy status ?
 
 		// meta-annotations
 		if ((getTagBits() & OnlyStructuralTagBits) != (newClassFile.getTagBits() & OnlyStructuralTagBits))
 			return true;
 		// annotations
 			return true;
 
 		// generic signature
 		if (!CharOperation.equals(getGenericSignature(), newClassFile.getGenericSignature()))
 			return true;
 		// superclass
 		if (!CharOperation.equals(getSuperclassName(), newClassFile.getSuperclassName()))
 			return true;
 		// interfaces
 		char[][] newInterfacesNames = newClassFile.getInterfaceNames();
 		if (this. != newInterfacesNames) { // TypeConstants.NoSuperInterfaces
 			int newInterfacesLength = newInterfacesNames == null ? 0 : newInterfacesNames.length;
 			if (newInterfacesLength != this.)
 				return true;
 			for (int i = 0, max = this.i < maxi++)
 				if (!CharOperation.equals(this.[i], newInterfacesNames[i]))
 					return true;
 		}
 
 		// member types
 		IBinaryNestedType[] currentMemberTypes = getMemberTypes();
 		IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes();
 		if (currentMemberTypes != otherMemberTypes) { // TypeConstants.NoMemberTypes
 			int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length;
 			int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length;
 			if (currentMemberTypeLength != otherMemberTypeLength)
 				return true;
 			for (int i = 0; i < currentMemberTypeLengthi++)
 				if (!CharOperation.equals(currentMemberTypes[i].getName(), otherMemberTypes[i].getName())
 					|| currentMemberTypes[i].getModifiers() != otherMemberTypes[i].getModifiers())
 						return true;
 		}
 
 		// fields
 		FieldInfo[] otherFieldInfos = (FieldInfo[]) newClassFile.getFields();
 		int otherFieldInfosLength = otherFieldInfos == null ? 0 : otherFieldInfos.length;
 		boolean compareFields = true;
 		if (this. == otherFieldInfosLength) {
 			int i = 0;
 			for (; i < this.i++)
 				if (hasStructuralFieldChanges(this.[i], otherFieldInfos[i])) break;
 			if ((compareFields = i != this.) && !orderRequired && !excludesSynthetic)
 				return true;
 		}
 		if (compareFields) {
 			if (this. != otherFieldInfosLength && !excludesSynthetic)
 				return true;
 			if (orderRequired) {
 				if (this. != 0)
 					Arrays.sort(this.);
 				if (otherFieldInfosLength != 0)
 					Arrays.sort(otherFieldInfos);
 			}
 			if (excludesSynthetic) {
 				if (hasNonSyntheticFieldChanges(this.otherFieldInfos))
 					return true;
 			} else {
 				for (int i = 0; i < this.i++)
 					if (hasStructuralFieldChanges(this.[i], otherFieldInfos[i]))
 						return true;
 			}
 		}
 
 		// methods
 		MethodInfo[] otherMethodInfos = (MethodInfo[]) newClassFile.getMethods();
 		int otherMethodInfosLength = otherMethodInfos == null ? 0 : otherMethodInfos.length;
 		boolean compareMethods = true;
 		if (this. == otherMethodInfosLength) {
 			int i = 0;
 			for (; i < this.i++)
 				if (hasStructuralMethodChanges(this.[i], otherMethodInfos[i])) break;
 			if ((compareMethods = i != this.) && !orderRequired && !excludesSynthetic)
 				return true;
 		}
 		if (compareMethods) {
 			if (this. != otherMethodInfosLength && !excludesSynthetic)
 				return true;
 			if (orderRequired) {
 				if (this. != 0)
 					Arrays.sort(this.);
 				if (otherMethodInfosLength != 0)
 					Arrays.sort(otherMethodInfos);
 			}
 			if (excludesSynthetic) {
 				if (hasNonSyntheticMethodChanges(this.otherMethodInfos))
 					return true;
 			} else {
 				for (int i = 0; i < this.i++)
 					if (hasStructuralMethodChanges(this.[i], otherMethodInfos[i]))
 						return true;
 			}
 		}
 
 		// missing types
 		char[][][] missingTypes = getMissingTypeNames();
 		char[][][] newMissingTypes = newClassFile.getMissingTypeNames();
 		if (missingTypes != null) {
 			if (newMissingTypes == null) {
 				return true;
 			}
 			int length = missingTypes.length;
 			if (length != newMissingTypes.length) {
 				return true;
 			}
 			for (int i = 0; i < lengthi++) {
 				if (!CharOperation.equals(missingTypes[i], newMissingTypes[i])) {
 					return true;
 				}
 			}
 		} else if (newMissingTypes != null) {
 			return true;
 		}
 		return false;
 	} catch (ClassFormatException e) {
 		return true;
 	}
 }
 
 private boolean hasStructuralAnnotationChanges(IBinaryAnnotation[] currentAnnotationsIBinaryAnnotation[] otherAnnotations) {
 	if (currentAnnotations == otherAnnotations)
 		return false;
 
 	int currentAnnotationsLength = currentAnnotations == null ? 0 : currentAnnotations.length;
 	int otherAnnotationsLength = otherAnnotations == null ? 0 : otherAnnotations.length;
 	if (currentAnnotationsLength != otherAnnotationsLength)
 		return true;
 	for (int i = 0; i < currentAnnotationsLengthi++) {
 		if (!CharOperation.equals(currentAnnotations[i].getTypeName(), otherAnnotations[i].getTypeName()))
 			return true;
 		IBinaryElementValuePair[] currentPairs = currentAnnotations[i].getElementValuePairs();
 		IBinaryElementValuePair[] otherPairs = otherAnnotations[i].getElementValuePairs();
 		int currentPairsLength = currentPairs == null ? 0 : currentPairs.length;
 		int otherPairsLength = otherPairs == null ? 0 : otherPairs.length;
 		if (currentPairsLength != otherPairsLength)
 			return true;
 		for (int j = 0; j < currentPairsLengthj++) {
 			if (!CharOperation.equals(currentPairs[j].getName(), otherPairs[j].getName()))
 				return true;
 			final Object value = currentPairs[j].getValue();
 			final Object value2 = otherPairs[j].getValue();
 			if (value instanceof Object[]) {
 				Object[] currentValues = (Object[]) value;
 				if (value2 instanceof Object[]) {
 					Object[] currentValues2 = (Object[]) value2;
 					final int length = currentValues.length;
 					if (length != currentValues2.length) {
 						return true;
					for (int n = 0; n < lengthn++) {
						if (!currentValues[n].equals(currentValues2[n])) {
							return true;
					return false;
				return true;
else if (!value.equals(value2)) {
				return true;
	return false;
private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfoFieldInfo otherFieldInfo) {
	// generic signature
	if (!CharOperation.equals(currentFieldInfo.getGenericSignature(), otherFieldInfo.getGenericSignature()))
		return true;
	if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers())
		return true;
	if ((currentFieldInfo.getTagBits() & .) != (otherFieldInfo.getTagBits() & .))
		return true;
	if (hasStructuralAnnotationChanges(currentFieldInfo.getAnnotations(), otherFieldInfo.getAnnotations()))
		return true;
	if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName()))
		return true;
	if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName()))
		return true;
	if (currentFieldInfo.hasConstant() != otherFieldInfo.hasConstant())
		return true;
	if (currentFieldInfo.hasConstant()) {
		Constant currentConstant = currentFieldInfo.getConstant();
		Constant otherConstant = otherFieldInfo.getConstant();
		if (currentConstant.typeID() != otherConstant.typeID())
			return true;
		if (!currentConstant.getClass().equals(otherConstant.getClass()))
			return true;
		switch (currentConstant.typeID()) {
			case . :
				return currentConstant.intValue() != otherConstant.intValue();
				return currentConstant.byteValue() != otherConstant.byteValue();
				return currentConstant.shortValue() != otherConstant.shortValue();
				return currentConstant.charValue() != otherConstant.charValue();
				return currentConstant.longValue() != otherConstant.longValue();
				return currentConstant.floatValue() != otherConstant.floatValue();
				return currentConstant.doubleValue() != otherConstant.doubleValue();
				return currentConstant.booleanValue() != otherConstant.booleanValue();
				return !currentConstant.stringValue().equals(otherConstant.stringValue());
	return false;
private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfoMethodInfo otherMethodInfo) {
	// generic signature
	if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature()))
		return true;
	if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers())
		return true;
	if ((currentMethodInfo.getTagBits() & .) != (otherMethodInfo.getTagBits() & .))
		return true;
	if (hasStructuralAnnotationChanges(currentMethodInfo.getAnnotations(), otherMethodInfo.getAnnotations()))
		return true;
	// parameter annotations:
	int currentAnnotatedParamsCount = currentMethodInfo.getAnnotatedParametersCount();
	int otherAnnotatedParamsCount = otherMethodInfo.getAnnotatedParametersCount();
	if (currentAnnotatedParamsCount != otherAnnotatedParamsCount)
		return true;
	for (int i=0; i<currentAnnotatedParamsCounti++) {
			return true;
	if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
		return true;
	if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
		return true;
	if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature()))
		return true;
	char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames();
	char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames();
	if (currentThrownExceptions != otherThrownExceptions) { // TypeConstants.NoExceptions
		int currentThrownExceptionsLength = currentThrownExceptions == null ? 0 : currentThrownExceptions.length;
		int otherThrownExceptionsLength = otherThrownExceptions == null ? 0 : otherThrownExceptions.length;
		if (currentThrownExceptionsLength != otherThrownExceptionsLength)
			return true;
		for (int k = 0; k < currentThrownExceptionsLengthk++)
			if (!CharOperation.equals(currentThrownExceptions[k], otherThrownExceptions[k]))
				return true;
	return false;
This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos will be therefore fully initialized and we can get rid of the bytes.
private void initialize() throws ClassFormatException {
	try {
		for (int i = 0, max = this.i < maxi++) {
		for (int i = 0, max = this.i < maxi++) {
		if (this. != null) {
			for (int i = 0, max = this..lengthi < maxi++) {
		if (this. != null) {
			for (int i = 0, max = this..lengthi < maxi++) {
catch(RuntimeException e) {
		throw exception;
Answer true if the receiver is an anonymous type, false otherwise

Returns:
boolean
public boolean isAnonymous() {
	if (this. == nullreturn false;
	char[] innerSourceName = this..getSourceName();
	return (innerSourceName == null || innerSourceName.length == 0);
Answer whether the receiver contains the resolved binary form or the unresolved source form of the type.

Returns:
boolean
public boolean isBinaryType() {
	return true;
Answer true if the receiver is a local type, false otherwise

Returns:
boolean
public boolean isLocal() {
	if (this. == nullreturn false;
	if (this..getEnclosingTypeName() != nullreturn false;
	char[] innerSourceName = this..getSourceName();
	return (innerSourceName != null && innerSourceName.length > 0);
Answer true if the receiver is a member type, false otherwise

Returns:
boolean
public boolean isMember() {
	if (this. == nullreturn false;
	if (this..getEnclosingTypeName() == nullreturn false;
	char[] innerSourceName = this..getSourceName();
	return (innerSourceName != null && innerSourceName.length > 0);	 // protection against ill-formed attributes (67600)