Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java

Issue 1373723003: Fix javac --incremental by using jmake for dependency analysis (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@aidl
Patch Set: fix license check Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java b/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ece22d9c336884a617caceb1d4afa33023cd9db
--- /dev/null
+++ b/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java
@@ -0,0 +1,595 @@
+/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved
+ *
+ * This program is distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+package org.pantsbuild.jmake;
+
+import java.lang.reflect.Modifier;
+
+
+/**
+ * This class implements reading a byte array representing a class file and converting it into ClassInfo.
+ *
+ * @author Misha Dmitriev
+ * 2 March 2005
+ */
+public class ClassFileReader extends BinaryFileReader {
+
+ public static final int JAVA_MAGIC = -889275714; // 0xCAFEBABE
+ public static final int JAVA_MINOR_VERSION = 0;
+ public static final int JAVA_MIN_MAJOR_VERSION = 45;
+ public static final int JAVA_MIN_MINOR_VERSION = 3;
+ public static final int DEFAULT_MAJOR_VERSION = 46;
+ public static final int DEFAULT_MINOR_VERSION = 0;
+ public static final int JDK14_MAJOR_VERSION = 48;
+ public static final int JDK15_MAJOR_VERSION = 49;
+ public static final int JDK16_MAJOR_VERSION = 50;
+ public static final int JDK17_MAJOR_VERSION = 51;
+ public static final int JDK18_MAJOR_VERSION = 52;
+ public static final int CONSTANT_Utf8 = 1;
+ public static final int CONSTANT_Unicode = 2;
+ public static final int CONSTANT_Integer = 3;
+ public static final int CONSTANT_Float = 4;
+ public static final int CONSTANT_Long = 5;
+ public static final int CONSTANT_Double = 6;
+ public static final int CONSTANT_Class = 7;
+ public static final int CONSTANT_String = 8;
+ public static final int CONSTANT_Fieldref = 9;
+ public static final int CONSTANT_Methodref = 10;
+ public static final int CONSTANT_InterfaceMethodref = 11;
+ public static final int CONSTANT_NameandType = 12;
+ public static final int CONSTANT_MethodHandle = 15;
+ public static final int CONSTANT_MethodType = 16;
+ public static final int CONSTANT_InvokeDynamic = 18;
+ private ClassInfo classInfo = null;
+ private int cpOffsets[];
+ private Object cpObjectCache[];
+ private byte cpTags[];
+
+ public void readClassFile(byte[] classFile, ClassInfo classInfo, String classFileFullPath, boolean readFullInfo) {
+ initBuf(classFile, classFileFullPath);
+ this.classInfo = classInfo;
+
+ readPreamble();
+ readConstantPool(readFullInfo);
+ readIntermediate();
+ if (readFullInfo) {
+ readFields();
+ readMethods();
+ readAttributes();
+ }
+ }
+
+ private int versionWord(int major, int minor) {
+ return major * 1000 + minor;
+ }
+
+ private void readPreamble() {
+ int magic = nextInt();
+ if (magic != JAVA_MAGIC) {
+ throw classFileParseException("Illegal start of class file");
+ }
+ int minorVersion = nextChar();
+ int majorVersion = nextChar();
+ if (majorVersion > JDK14_MAJOR_VERSION ||
+ versionWord(majorVersion, minorVersion) <
+ versionWord(JAVA_MIN_MAJOR_VERSION, JAVA_MIN_MINOR_VERSION) ) {
+ if (majorVersion == JDK18_MAJOR_VERSION) {
+ classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_18;
+ } else if (majorVersion == JDK17_MAJOR_VERSION) {
+ classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_17;
+ } else if (majorVersion == JDK16_MAJOR_VERSION) {
+ classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_16;
+ } else if (majorVersion == JDK15_MAJOR_VERSION) {
+ classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_15;
+ } else {
+ throw classFileParseException("Wrong version: " + majorVersion + "." + minorVersion);
+ }
+ } else {
+ classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST;
+ }
+ }
+
+ private void readConstantPool(boolean readFullInfo) {
+ int classRefsNo = 0;
+ int fieldRefsNo = 0;
+ int methodRefsNo = 0;
+
+ cpOffsets = new int[nextChar()];
+ cpTags = new byte[cpOffsets.length];
+ int ofs, len, classIdx, nameAndTypeIdx, nameIdx, sigIdx, utf8Idx;
+ int i = 1;
+ while (i < cpOffsets.length) {
+ byte tag = buf[curBufPos++];
+ cpOffsets[i] = curBufPos;
+ cpTags[i] = tag;
+ i++;
+ switch (tag) {
+ case CONSTANT_Utf8:
+ len = nextChar();
+ curBufPos += len;
+ break;
+
+ case CONSTANT_Class:
+ classRefsNo++;
+ curBufPos += 2;
+ break;
+
+ case CONSTANT_String:
+ case CONSTANT_MethodType:
+ curBufPos += 2;
+ break;
+
+ case CONSTANT_Fieldref:
+ fieldRefsNo++;
+ curBufPos += 4;
+ break;
+
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ methodRefsNo++;
+ curBufPos += 4;
+ break;
+
+ case CONSTANT_MethodHandle:
+ curBufPos += 3;
+ break;
+
+ case CONSTANT_NameandType:
+ case CONSTANT_Integer:
+ case CONSTANT_Float:
+ case CONSTANT_InvokeDynamic:
+ curBufPos += 4;
+ break;
+
+ case CONSTANT_Long:
+ case CONSTANT_Double:
+ curBufPos += 8;
+ i++;
+ break;
+
+ default:
+ throw classFileParseException("Bad constant pool tag: " + tag + " at " + Integer.toString(curBufPos - 1));
+ }
+ }
+
+ cpObjectCache = new Object[cpOffsets.length];
+ if (!readFullInfo) {
+ return;
+ }
+
+ classInfo.cpoolRefsToClasses = new String[classRefsNo];
+ classInfo.isRefClassArray = new boolean[classRefsNo];
+ classInfo.cpoolRefsToFieldClasses = new String[fieldRefsNo];
+ classInfo.cpoolRefsToFieldNames = new String[fieldRefsNo];
+ classInfo.cpoolRefsToFieldSignatures = new String[fieldRefsNo];
+ classInfo.cpoolRefsToMethodClasses = new String[methodRefsNo];
+ classInfo.cpoolRefsToMethodNames = new String[methodRefsNo];
+ classInfo.cpoolRefsToMethodSignatures = new String[methodRefsNo];
+
+ int curClassRef = 0;
+ int curFieldRef = 0;
+ int curMethodRef = 0;
+
+ for (i = 0; i < cpOffsets.length; i++) {
+ ofs = cpOffsets[i];
+ switch (cpTags[i]) {
+ case CONSTANT_Class:
+ utf8Idx = getChar(ofs);
+ classInfo.cpoolRefsToClasses[curClassRef++] =
+ classNameAtCPIndex(utf8Idx, classInfo.isRefClassArray, curClassRef - 1);
+ //System.out.println("Read cpool ref to class: " + classInfo.cpoolRefsToClasses[curClassRef-1]);
+ break;
+
+ case CONSTANT_Fieldref:
+ classIdx = getChar(ofs);
+ nameAndTypeIdx = getChar(ofs + 2);
+ if (cpTags[classIdx] != CONSTANT_Class || cpTags[nameAndTypeIdx] != CONSTANT_NameandType) {
+ badCPReference(ofs, i);
+ }
+ classInfo.cpoolRefsToFieldClasses[curFieldRef] =
+ classNameAtCPIndex(getChar(cpOffsets[classIdx]));
+
+ ofs = cpOffsets[nameAndTypeIdx];
+ nameIdx = getChar(ofs);
+ sigIdx = getChar(ofs + 2);
+ if (cpTags[nameIdx] != CONSTANT_Utf8 || cpTags[sigIdx] != CONSTANT_Utf8) {
+ badCPReference(ofs, i);
+ }
+ classInfo.cpoolRefsToFieldNames[curFieldRef] =
+ utf8AtCPIndex(nameIdx);
+ classInfo.cpoolRefsToFieldSignatures[curFieldRef] =
+ signatureAtCPIndex(sigIdx);
+ //System.out.println("Read cpool ref to field: " + classInfo.cpoolRefsToFieldNames[curFieldRef] + " " +
+ // classInfo.cpoolRefsToFieldSignatures[curFieldRef]);
+ curFieldRef++;
+ break;
+
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ classIdx = getChar(ofs);
+ nameAndTypeIdx = getChar(ofs + 2);
+ if (cpTags[classIdx] != CONSTANT_Class || cpTags[nameAndTypeIdx] != CONSTANT_NameandType) {
+ badCPReference(ofs, i);
+ }
+ classInfo.cpoolRefsToMethodClasses[curMethodRef] =
+ classNameAtCPIndex(getChar(cpOffsets[classIdx]));
+
+ ofs = cpOffsets[nameAndTypeIdx];
+ nameIdx = getChar(ofs);
+ sigIdx = getChar(ofs + 2);
+ if (cpTags[nameIdx] != CONSTANT_Utf8 || cpTags[sigIdx] != CONSTANT_Utf8) {
+ badCPReference(ofs, i);
+ }
+ classInfo.cpoolRefsToMethodNames[curMethodRef] =
+ utf8AtCPIndex(nameIdx);
+ classInfo.cpoolRefsToMethodSignatures[curMethodRef] =
+ signatureAtCPIndex(sigIdx);
+ //System.out.println("Read cpool ref to method: " + classInfo.cpoolRefsToMethodNames[curMethodRef] + " " +
+ // classInfo.cpoolRefsToMethodSignatures[curMethodRef]);
+ curMethodRef++;
+ break;
+ }
+ }
+ }
+
+ private void readIntermediate() {
+ int i, classIdx, superClassIdx;
+
+ classInfo.accessFlags = nextChar();
+ classIdx = nextChar();
+ if (cpTags[classIdx] != CONSTANT_Class) {
+ throw classFileParseException("Bad reference to this class name");
+ }
+ classInfo.name = classNameAtCPIndex(getChar(cpOffsets[classIdx]));
+ superClassIdx = nextChar();
+ if (!"java/lang/Object".equals(classInfo.name)) {
+ if (cpTags[superClassIdx] != CONSTANT_Class) {
+ throw classFileParseException("Bad reference to super class name");
+ }
+ classInfo.superName =
+ classNameAtCPIndex(getChar(cpOffsets[superClassIdx]));
+ }
+
+ char intfCount = nextChar();
+ if (intfCount != 0) {
+ classInfo.interfaces = new String[intfCount];
+ for (i = 0; i < intfCount; i++) {
+ classIdx = nextChar();
+ if (cpTags[classIdx] != CONSTANT_Class) {
+ throw classFileParseException("Bad reference to an implemented interface");
+ }
+ classInfo.interfaces[i] =
+ classNameAtCPIndex(getChar(cpOffsets[classIdx]));
+ }
+ }
+ }
+
+ private void readFields() {
+ int i, j;
+
+ char definedFieldCount = nextChar();
+ if (definedFieldCount == 0) {
+ return;
+ }
+
+ String names[] = new String[definedFieldCount];
+ String signatures[] = new String[definedFieldCount];
+ char accessFlags[] = new char[definedFieldCount];
+
+ // We are not going to record information on private fields which have either primitive or non-project-class
+ // (typically core-class) types. Such fields cannot affect anything except their own class, so we don't need them.
+ int ri = 0;
+
+ for (i = 0; i < definedFieldCount; i++) {
+ char flags = nextChar();
+ String name = utf8AtCPIndex(nextChar());
+ String sig = signatureAtCPIndex(nextChar());
+
+ boolean recordField =
+ !(Modifier.isPrivate(flags) &&
+ (ClassInfo.isPrimitiveFieldSig(sig) || classInfo.isNonProjectClassTypeFieldSig(sig)));
+
+ int attrCount = nextChar();
+ for (j = 0; j < attrCount; j++) {
+ int attrNameIdx = nextChar();
+ int attrLen = nextInt();
+ if (recordField && utf8AtCPIndex(attrNameIdx).equals("ConstantValue") &&
+ Modifier.isFinal(flags)) {
+ if (classInfo.primitiveConstantInitValues == null) {
+ classInfo.primitiveConstantInitValues =
+ new Object[definedFieldCount];
+ }
+ int constValueIdx = nextChar();
+ switch (cpTags[constValueIdx]) {
+ case CONSTANT_String:
+ classInfo.primitiveConstantInitValues[ri] =
+ utf8AtCPIndex(getChar(cpOffsets[constValueIdx]));
+ break;
+
+ case CONSTANT_Integer:
+ classInfo.primitiveConstantInitValues[ri] =
+ Integer.valueOf(getInt(cpOffsets[constValueIdx]));
+ break;
+
+ case CONSTANT_Long:
+ classInfo.primitiveConstantInitValues[ri] =
+ Long.valueOf(getLong(cpOffsets[constValueIdx]));
+ break;
+
+ case CONSTANT_Float:
+ classInfo.primitiveConstantInitValues[ri] =
+ Float.valueOf(getFloat(cpOffsets[constValueIdx]));
+ break;
+
+ case CONSTANT_Double:
+ classInfo.primitiveConstantInitValues[ri] =
+ Double.valueOf(getDouble(cpOffsets[constValueIdx]));
+ break;
+
+ default:
+ badCPEntry(constValueIdx);
+ }
+
+ } else {
+ curBufPos += attrLen;
+ }
+ }
+
+ if (recordField) {
+ names[ri] = name;
+ signatures[ri] = sig;
+ accessFlags[ri] = flags;
+ ri++;
+ }
+ }
+
+ if (ri == definedFieldCount) {
+ classInfo.fieldNames = names;
+ classInfo.fieldSignatures = signatures;
+ classInfo.fieldAccessFlags = accessFlags;
+ } else if (ri > 0) {
+ classInfo.fieldNames = new String[ri];
+ classInfo.fieldSignatures = new String[ri];
+ classInfo.fieldAccessFlags = new char[ri];
+ System.arraycopy(names, 0, classInfo.fieldNames, 0, ri);
+ System.arraycopy(signatures, 0, classInfo.fieldSignatures, 0, ri);
+ System.arraycopy(accessFlags, 0, classInfo.fieldAccessFlags, 0, ri);
+ }
+ }
+
+ private void readMethods() {
+ int i, j;
+
+ char methodCount = nextChar();
+ if (methodCount == 0) {
+ return;
+ }
+
+ String names[] = new String[methodCount];
+ String signatures[] = new String[methodCount];
+ char accessFlags[] = new char[methodCount];
+
+ for (i = 0; i < methodCount; i++) {
+ accessFlags[i] = nextChar();
+ names[i] = utf8AtCPIndex(nextChar());
+ signatures[i] = signatureAtCPIndex(nextChar());
+
+ int attrCount = nextChar();
+ for (j = 0; j < attrCount; j++) {
+ int attrNameIdx = nextChar();
+ int attrLen = nextInt();
+ if (utf8AtCPIndex(attrNameIdx).equals("Exceptions")) {
+ if (classInfo.checkedExceptions == null) {
+ classInfo.checkedExceptions = new String[methodCount][];
+ }
+ int nExceptions = nextChar();
+ String exceptions[] = new String[nExceptions];
+ for (int k = 0; k < nExceptions; k++) {
+ int excClassIdx = nextChar();
+ if (cpTags[excClassIdx] != CONSTANT_Class) {
+ badCPEntry(excClassIdx);
+ }
+ exceptions[k] =
+ classNameAtCPIndex(getChar(cpOffsets[excClassIdx]));
+ }
+ classInfo.checkedExceptions[i] = exceptions;
+ } else {
+ curBufPos += attrLen;
+ }
+ }
+ }
+
+ classInfo.methodNames = names;
+ classInfo.methodSignatures = signatures;
+ classInfo.methodAccessFlags = accessFlags;
+ }
+
+ /**
+ * This method actually reads only the information related to the nested classes, and
+ * records only those of them which are first level nested classes of this class. The class
+ * may also reference other classes which are not package members through the same
+ * InnerClasses attribute - their names would be processed when their respective enclosing
+ * classes are read.
+ */
+ private void readAttributes() {
+ String nestedClassPrefix = classInfo.name + "$";
+
+ char attrCount = nextChar();
+
+ for (int i = 0; i < attrCount; i++) {
+ int attrNameIdx = nextChar();
+ int attrLen = nextInt();
+ if (utf8AtCPIndex(attrNameIdx).equals("InnerClasses")) {
+ int nOfClasses = nextChar();
+ String nestedClasses[] = new String[nOfClasses];
+ char nestedClassAccessFlags[] = new char[nOfClasses];
+ boolean nestedClassNonMember[] = new boolean[nOfClasses];
+ int curIdx = 0;
+ for (int j = 0; j < nOfClasses; j++) {
+ int innerClassInfoIdx = nextChar();
+ int outerClassInfoIdx = nextChar();
+ int innerClassNameIdx = nextChar();
+ char innerClassAccessFlags = nextChar();
+
+ // Even if a class is private or non-member (innerClassAccessFlags has private bit set or
+ // outerClassInfoIdx == 0), we still should take this class into account, since it may e.g. extend
+ // a public class/implement a public interface, which, in turn, may be changed incompatibly.
+
+ String nestedClassFullName = classNameAtCPIndex(getChar(cpOffsets[innerClassInfoIdx]));
+
+ // We are only interested the nested classes whose enclosing class is this one.
+ if (!nestedClassFullName.startsWith(nestedClassPrefix))
+ continue;
+
+ // We are only interested in the directly nested classes of this class.
+ String nestedClassNameSuffix = nestedClassFullName.substring(nestedClassPrefix.length());
+
+ if (innerClassNameIdx == 0) {
+ // Nested class is anonymous. Suffix must be all digits.
+ if (findFirstNonDigit(nestedClassNameSuffix) != -1)
+ continue;
+ } else {
+ // Nested class is named.
+ String nestedClassSimpleName = utf8AtCPIndex(innerClassNameIdx);
+ // The simple case is Outer$Inner.
+ if (!nestedClassNameSuffix.equals(nestedClassSimpleName)) {
+ // The more complicated case is a local class. In JDK 1.5+ These are named,
+ // e.g., Outer$1Inner. Pre-JDK 1.5 they are named e.g., Outer$1$Inner.
+ int p = findFirstNonDigit(nestedClassNameSuffix);
+ if (p == -1)
+ continue;
+ if (classInfo.javacTargetRelease == Utils.JAVAC_TARGET_RELEASE_OLDEST &&
+ nestedClassNameSuffix.charAt(p++) != '$')
+ continue;
+ if (!nestedClassNameSuffix.substring(p).equals(nestedClassSimpleName))
+ continue;
+ }
+ }
+
+ // The name has passed all checks, so register it.
+
+ nestedClasses[curIdx] = nestedClassFullName;
+ nestedClassAccessFlags[curIdx] = innerClassAccessFlags;
+ nestedClassNonMember[curIdx] = (outerClassInfoIdx == 0);
+ curIdx++;
+ }
+ if (curIdx == nOfClasses) {
+ classInfo.nestedClasses = nestedClasses;
+ classInfo.nestedClassAccessFlags = nestedClassAccessFlags;
+ classInfo.nestedClassNonMember = nestedClassNonMember;
+ } else if (curIdx > 0) {
+ // We found fewer nested classes for this class than we originally expected, but still more than 0.
+ // Create a new array to fit their number exactly.
+ classInfo.nestedClasses = new String[curIdx];
+ classInfo.nestedClassAccessFlags = new char[curIdx];
+ classInfo.nestedClassNonMember = new boolean[curIdx];
+ System.arraycopy(nestedClasses, 0, classInfo.nestedClasses, 0, curIdx);
+ System.arraycopy(nestedClassAccessFlags, 0, classInfo.nestedClassAccessFlags, 0, curIdx);
+ System.arraycopy(nestedClassNonMember, 0, classInfo.nestedClassNonMember, 0, curIdx);
+ }
+ } else {
+ curBufPos += attrLen;
+ }
+ }
+ }
+
+ private int findFirstNonDigit(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ if (!Character.isDigit(s.charAt(i)))
+ return i;
+ }
+ return -1;
+ }
+
+ private String utf8AtCPIndex(int idx) {
+ if (cpTags[idx] != CONSTANT_Utf8) {
+ throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant");
+ }
+ if (cpObjectCache[idx] == null) {
+ int utf8Len = getChar(cpOffsets[idx]);
+ // String interning reduces the size of the disk database very significantly
+ // (by one-third in one observed case), and also speeds up database search.
+ cpObjectCache[idx] =
+ (new String(buf, cpOffsets[idx] + 2, utf8Len)).intern();
+ }
+ return (String) cpObjectCache[idx];
+ }
+
+ private String classNameAtCPIndex(int idx) {
+ return classNameAtCPIndex(idx, null, 0);
+ }
+
+ /**
+ * Read class name at the given CONSTANT_Utf8 constant pool index, and return it
+ * trimmed of the possible '[' and 'L' prefixes and the ';' suffix.
+ */
+ private String classNameAtCPIndex(int idx, boolean isRefClassArray[], int isArrayIdx) {
+ if (cpTags[idx] != CONSTANT_Utf8) {
+ throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant");
+ }
+ boolean isArray = false;
+ if (cpObjectCache[idx] == null) {
+ int utf8Len = getChar(cpOffsets[idx]);
+ int stPos = cpOffsets[idx] + 2;
+ int initStPos = stPos;
+ while (buf[stPos] == '[') {
+ stPos++;
+ }
+ if (stPos != initStPos) {
+ isArray = true;
+ if (buf[stPos] == 'L') {
+ stPos++;
+ utf8Len--; // To get rid of the terminating ';'
+ }
+ }
+ utf8Len = utf8Len - (stPos - initStPos);
+ cpObjectCache[idx] = (new String(buf, stPos, utf8Len)).intern();
+ if (isRefClassArray != null) {
+ isRefClassArray[isArrayIdx] = isArray;
+ }
+ }
+ return (String) cpObjectCache[idx];
+ }
+
+ // We replace all "Lclassname;" in signatures with "@classname#" to simplify signature parsing during reference checking
+ private String signatureAtCPIndex(int idx) {
+ if (cpTags[idx] != CONSTANT_Utf8) {
+ throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant");
+ }
+ if (cpObjectCache[idx] == null) {
+ int utf8Len = getChar(cpOffsets[idx]);
+ byte tmp[] = new byte[utf8Len];
+ System.arraycopy(buf, cpOffsets[idx] + 2, tmp, 0, utf8Len);
+ boolean inClassName = false;
+ for (int i = 0; i < utf8Len; i++) {
+ if (!inClassName) {
+ if (tmp[i] == 'L') {
+ tmp[i] = '@';
+ inClassName = true;
+ }
+ } else if (tmp[i] == ';') {
+ tmp[i] = '#';
+ inClassName = false;
+ }
+ }
+ cpObjectCache[idx] = (new String(tmp)).intern();
+ }
+ return (String) cpObjectCache[idx];
+ }
+
+ private void badCPReference(int ofs, int i) {
+ throw classFileParseException("Bad constant pool reference: " + ofs + " from entry " + i);
+ }
+
+ private void badCPEntry(int entryNo) {
+ throw classFileParseException("Constant pool entry " + entryNo + " : invalid type");
+ }
+
+ private PrivateException classFileParseException(String msg) {
+ return new PrivateException(new PublicExceptions.ClassFileParseException(
+ "Error reading class file " + fileFullPath + ":\n" + msg));
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698