2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package gov.nasa.jpf.jvm;
23 import gov.nasa.jpf.JPFException;
24 import gov.nasa.jpf.util.BailOut;
25 import gov.nasa.jpf.util.BinaryClassSource;
26 import gov.nasa.jpf.vm.ClassParseException;
29 * class to read and dissect Java classfile contents (as specified by the Java VM
30 * spec http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#16628
32 public class ClassFile extends BinaryClassSource {
34 public static final int CONSTANT_UTF8 = 1;
35 public static final int CONSTANT_INTEGER = 3;
36 public static final int CONSTANT_FLOAT = 4;
37 public static final int CONSTANT_LONG = 5;
38 public static final int CONSTANT_DOUBLE = 6;
39 public static final int CONSTANT_CLASS = 7;
40 public static final int CONSTANT_STRING = 8;
41 public static final int FIELD_REF = 9;
42 public static final int METHOD_REF = 10;
43 public static final int INTERFACE_METHOD_REF = 11;
44 public static final int NAME_AND_TYPE = 12;
45 public static final int METHOD_HANDLE = 15;
46 public static final int METHOD_TYPE = 16;
47 public static final int INVOKE_DYNAMIC = 18;
49 public static final int REF_GETFIELD = 1;
50 public static final int REF_GETSTATIC = 2;
51 public static final int REF_PUTFIELD = 3;
52 public static final int REF_PUTSTATIC = 4;
53 public static final int REF_INVOKEVIRTUAL = 5;
54 public static final int REF_INVOKESTATIC = 6;
55 public static final int REF_INVOKESPECIAL = 7;
56 public static final int REF_NEW_INVOKESPECIAL = 8;
57 public static final int REF_INVOKEINTERFACE = 9;
59 // used to store types in cpValue[]
60 public static enum CpInfo {
72 InterfaceMethodRef, // 11
82 // <2do> this is going away
83 String requestedTypeName; // the type name that caused this classfile to be loaded
86 int[] cpPos; // cpPos[i] holds data start index for cp_entry i (0 is unused)
87 Object[] cpValue; // cpValue[i] hold the String/Integer/Float/Double associated with corresponding cp_entries
90 public ClassFile (byte[] data, int offset){
94 public ClassFile (byte[] data){
98 public ClassFile (String typeName, byte[] data){
101 this.requestedTypeName = typeName;
104 public ClassFile (String typeName, byte[] data, int offset){
107 this.requestedTypeName = typeName;
110 public ClassFile (File file) throws ClassParseException {
114 public ClassFile (String pathName) throws ClassParseException {
115 super( new File(pathName));
122 * set classfile data. This is mainly provided to allow
123 * on-the-fly classfile instrumentation with 3rd party libraries
125 * BEWARE - like getData(), this method can cause parsing to fail if the
126 * provided data does not conform to the VM specs. In particular, this
127 * method should ONLY be called before executing parse(ClassFileReader) and
128 * will otherwise throw a JPFException
130 public void setData(byte[] newData){
132 throw new JPFException("concurrent modification of ClassFile data");
139 * return the typename this classfile gets loaded for
140 * <2do> this is going away
142 public String getRequestedTypeName(){
143 return requestedTypeName;
147 //--- general attributes
148 public static final String SYNTHETIC_ATTR = "Synthetic";
149 public static final String DEPRECATED_ATTR = "Deprecated";
150 public static final String SIGNATURE_ATTR = "Signature";
151 public static final String RUNTIME_INVISIBLE_ANNOTATIONS_ATTR = "RuntimeInvisibleAnnotations";
152 public static final String RUNTIME_VISIBLE_ANNOTATIONS_ATTR = "RuntimeVisibleAnnotations";
153 public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR = "RuntimeVisibleTypeAnnotations";
155 //--- standard field attributes
156 public static final String CONST_VALUE_ATTR = "ConstantValue";
158 protected final static String[] stdFieldAttrs = {
159 CONST_VALUE_ATTR, SYNTHETIC_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
160 RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR };
163 //--- standard method attributes
164 public static final String CODE_ATTR = "Code";
165 public static final String EXCEPTIONS_ATTR = "Exceptions";
166 public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS_ATTR = "RuntimeInvisibleParameterAnnotations";
167 public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTR = "RuntimeVisibleParameterAnnotations";
168 public static final String ANNOTATIONDEFAULT_ATTR = "AnnotationDefault";
170 protected final static String[] stdMethodAttrs = {
171 CODE_ATTR, EXCEPTIONS_ATTR, SYNTHETIC_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
172 RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR,
173 RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS_ATTR,
174 RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTR,
175 RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR,
176 ANNOTATIONDEFAULT_ATTR
180 //--- standard code attributes
181 public static final String LINE_NUMBER_TABLE_ATTR = "LineNumberTable";
182 public static final String LOCAL_VAR_TABLE_ATTR = "LocalVariableTable";
184 protected final static String[] stdCodeAttrs = { LINE_NUMBER_TABLE_ATTR, LOCAL_VAR_TABLE_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR };
187 //--- standard class attributes
188 public static final String SOURCE_FILE_ATTR = "SourceFile";
189 public static final String INNER_CLASSES_ATTR = "InnerClasses";
190 public static final String ENCLOSING_METHOD_ATTR = "EnclosingMethod";
191 public static final String BOOTSTRAP_METHOD_ATTR = "BootstrapMethods";
193 protected final static String[] stdClassAttrs = {
194 SOURCE_FILE_ATTR, DEPRECATED_ATTR, INNER_CLASSES_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
195 RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR,
196 ENCLOSING_METHOD_ATTR, BOOTSTRAP_METHOD_ATTR };
199 protected String internStdAttrName(int cpIdx, String name, String[] stdNames){
200 for (int i=0; i<stdNames.length; i++){
201 if (stdNames[i] == name) return name;
203 for (int i=0; i<stdNames.length; i++){
204 String stdName = stdNames[i];
205 if (stdName.equals(name)){
206 cpValue[cpIdx] = stdName;
214 //--- constpool access
216 //--- the primitive info cpValue
217 public String utf8At(int utf8InfoIdx){
218 //assert data[cpPos[utf8InfoIdx]] == 1 : "not a utf8_info tag";
219 return (String) cpValue[utf8InfoIdx];
222 public int intAt(int intInfoIdx){
223 //assert data[cpPos[intInfoIdx]] == 3 : "not a int_info tag";
224 return (Integer) cpValue[intInfoIdx];
227 public float floatAt(int floatInfoIdx){
228 //assert data[cpPos[floatInfoIdx]] == 4 : "not a float_info tag";
229 return (Float) cpValue[floatInfoIdx];
232 public long longAt(int longInfoIdx){
233 //assert data[cpPos[longInfoIdx]] == 5 : "not a long_info tag";
234 return (Long) cpValue[longInfoIdx];
237 public double doubleAt(int doubleInfoIdx){
238 //assert data[cpPos[doubleInfoIdx]] == 6 : "not a double_info tag";
239 return (Double) cpValue[doubleInfoIdx];
242 //--- those two are delegated but resolved
243 public String classNameAt(int classInfoIdx){
244 //assert data[cpPos[classInfoIdx]] == 7 : "not a Class_info tag";
245 return (String) cpValue[classInfoIdx];
248 public String stringAt(int stringInfoIdx){
249 //assert data[cpPos[stringInfoIdx]] == 8 : "not a String_info tag";
250 return (String) cpValue[stringInfoIdx];
253 //--- composite infos
255 // the generic ones (if we don't care what kind of reference type this is)
256 public String refClassNameAt(int cpIdx){
257 return (String) cpValue[ u2(cpPos[cpIdx]+1)];
259 public String refNameAt(int cpIdx){
260 return utf8At( u2( cpPos[ u2(cpPos[cpIdx]+3)]+1));
262 public String refDescriptorAt(int cpIdx){
263 return utf8At( u2( cpPos[ u2(cpPos[cpIdx]+3)]+3));
266 public int mhRefTypeAt (int methodHandleInfoIdx){
267 return u1(cpPos[methodHandleInfoIdx]+1);
269 public int mhMethodRefIndexAt (int methodHandleInfoIdx){
270 return u2(cpPos[methodHandleInfoIdx]+2);
273 // those could check ref types
274 public String fieldClassNameAt(int fieldRefInfoIdx){
275 //assert data[cpPos[fieldRefInfoIdx]] == 9 : "not a Fieldref_info tag";
276 return (String) cpValue[ u2(cpPos[fieldRefInfoIdx]+1)];
278 public String fieldNameAt(int fieldRefInfoIdx){
279 return utf8At( u2( cpPos[ u2(cpPos[fieldRefInfoIdx]+3)]+1));
281 public String fieldDescriptorAt(int fieldRefInfoIdx){
282 return utf8At( u2( cpPos[ u2(cpPos[fieldRefInfoIdx]+3)]+3));
285 public String methodClassNameAt(int methodRefInfoIdx){
286 return (String) cpValue[ u2(cpPos[methodRefInfoIdx]+1)];
288 public String methodNameAt(int methodRefInfoIdx){
289 return utf8At( u2( cpPos[ u2(cpPos[methodRefInfoIdx]+3)]+1));
291 public String methodDescriptorAt(int methodRefInfoIdx){
292 return utf8At( u2( cpPos[ u2(cpPos[methodRefInfoIdx]+3)]+3));
295 public String methodTypeDescriptorAt (int methodTypeInfoIdx){
296 return utf8At( u2(cpPos[methodTypeInfoIdx]+1));
299 public String interfaceMethodClassNameAt(int ifcMethodRefInfoIdx){
300 return (String) cpValue[ u2(cpPos[ifcMethodRefInfoIdx]+1)];
302 public String interfaceMethodNameAt(int ifcMethodRefInfoIdx){
303 return utf8At( u2( cpPos[ u2(cpPos[ifcMethodRefInfoIdx]+3)]+1));
305 public String interfaceMethodDescriptorAt(int ifcMethodRefInfoIdx){
306 return utf8At( u2( cpPos[ u2(cpPos[ifcMethodRefInfoIdx]+3)]+3));
309 public int bootstrapMethodIndex (int cpInvokeDynamicIndex){
310 return u2(cpPos[cpInvokeDynamicIndex]+1);
312 public String samMethodNameAt(int cpInvokeDynamicIndex) {
313 return utf8At( u2( cpPos[ u2(cpPos[cpInvokeDynamicIndex]+3)]+1));
315 public String callSiteDescriptor(int cpInvokeDynamicIndex) {
316 return utf8At( u2( cpPos[ u2(cpPos[cpInvokeDynamicIndex]+3)]+3));
319 public String getRefTypeName (int refCode){
321 case REF_GETFIELD: return "getfield";
322 case REF_GETSTATIC: return "getstatic";
323 case REF_PUTFIELD: return "putfield";
324 case REF_PUTSTATIC: return "putstatic";
325 case REF_INVOKEVIRTUAL: return "invokevirtual";
326 case REF_INVOKESTATIC: return "invokestatic";
327 case REF_INVOKESPECIAL: return "invokespecial";
328 case REF_NEW_INVOKESPECIAL: return "new-invokespecial";
329 case REF_INVOKEINTERFACE: return "invokeinterface";
335 public String getTypeName (int typeCode){
337 case 4: return "boolean";
338 case 5: return "char";
339 case 6: return "float";
340 case 7: return "double";
341 case 8: return "byte";
342 case 9: return "short";
343 case 10: return "int";
344 case 11: return "long";
359 //--- traverse/analyze the const pool (this is rather exotic)
361 public int getNumberOfCpEntries(){
362 return cpValue.length;
365 public Object getCpValue (int i){
369 public int getCpTag (int i){
370 return data[cpPos[i]];
374 * the result can be used as input for u2(dataIndex)
376 * NOTE - this returns -1 for the dreaded unused extra entries associated
377 * with ConstantDouble and ConstantLong
379 public int getDataPosOfCpEntry (int i){
383 //--- standard attributes
385 public Object getConstValueAttribute(int dataPos){
386 int cpIdx = u2(dataPos);
387 Object v = cpValue[cpIdx];
391 public String getSourceFileAttribute(int dataPos){
392 // SourceFile_attribute { u2 attr_name_idx; u4 attr_length; u2 sourcefile_idx<utf8>; }
394 int cpIdx = u2(dataPos + 6);
395 Object v = cpValue[cpIdx];
400 //--- low level readers
402 public final int u1(int dataIdx){
403 return data[dataIdx] & 0xff;
406 public final int u2(int dataIdx){
407 return ((data[dataIdx]&0xff) << 8) | (data[dataIdx+1]&0xff);
410 public final int i1(int dataIdx) {
411 return data[dataIdx++];
414 public final int i2(int dataIdx) {
416 return (data[idx++] << 8) | (data[idx]&0xff);
419 public final int readU2(){
422 return ((data[idx++]&0xff) << 8) | (data[idx]&0xff);
425 // TODO: DIRTY HACKS!!!
426 public final int readU4(){
429 byte[] data = this.data;
431 return ((data[idx++]&0xff) <<24) | ((data[idx++]&0xff) << 16) | ((data[idx++]&0xff) << 8) | (data[idx]&0xff);
434 public final int readI2() {
437 return (data[idx++] << 8) | (data[idx]&0xff);
440 public final int readI4(){
443 byte[] data = this.data;
445 return (data[idx++] <<24) | ((data[idx++]&0xff) << 16) | ((data[idx++]&0xff) << 8) | (data[idx]&0xff);
449 //--- reader notifications
450 private void setClass(ClassFileReader reader, String clsName, String superClsName, int flags, int cpCount) throws ClassParseException {
452 reader.setClass( this, clsName, superClsName, flags, cpCount);
456 private void setInterfaceCount(ClassFileReader reader, int ifcCount){
458 reader.setInterfaceCount( this, ifcCount);
461 private void setInterface(ClassFileReader reader, int ifcIndex, String ifcName){
463 reader.setInterface( this, ifcIndex, ifcName);
466 private void setInterfacesDone(ClassFileReader reader){
468 reader.setInterfacesDone( this);
473 private void setFieldCount(ClassFileReader reader, int fieldCount){
475 reader.setFieldCount( this, fieldCount);
479 private void setField(ClassFileReader reader, int fieldIndex, int accessFlags, String name, String descriptor){
481 reader.setField( this, fieldIndex, accessFlags, name, descriptor);
484 private void setFieldAttributeCount(ClassFileReader reader, int fieldIndex, int attrCount){
486 reader.setFieldAttributeCount( this, fieldIndex, attrCount);
489 private void setFieldAttribute(ClassFileReader reader, int fieldIndex, int attrIndex, String name, int attrLength){
490 int p = pos + attrLength;
491 reader.setFieldAttribute( this, fieldIndex, attrIndex, name, attrLength);
494 private void setFieldAttributesDone(ClassFileReader reader, int fieldIndex){
496 reader.setFieldAttributesDone( this, fieldIndex);
499 private void setFieldDone(ClassFileReader reader, int fieldIndex){
501 reader.setFieldDone( this, fieldIndex);
504 private void setFieldsDone(ClassFileReader reader){
506 reader.setFieldsDone( this);
509 private void setConstantValue(ClassFileReader reader, Object tag, Object value){
511 reader.setConstantValue( this, tag, value);
515 private void setMethodCount(ClassFileReader reader, int methodCount){
517 reader.setMethodCount( this, methodCount);
520 private void setMethod(ClassFileReader reader, int methodIndex, int accessFlags, String name, String descriptor){
522 reader.setMethod( this, methodIndex, accessFlags, name, descriptor);
525 private void setMethodAttributeCount(ClassFileReader reader, int methodIndex, int attrCount){
527 reader.setMethodAttributeCount( this, methodIndex, attrCount);
530 private void setMethodAttribute(ClassFileReader reader, int methodIndex, int attrIndex, String name, int attrLength){
531 int p = pos + attrLength;
532 reader.setMethodAttribute( this, methodIndex, attrIndex, name, attrLength);
535 private void setMethodAttributesDone(ClassFileReader reader, int methodIndex){
537 reader.setMethodAttributesDone( this, methodIndex);
540 private void setMethodDone(ClassFileReader reader, int methodIndex){
542 reader.setMethodDone( this, methodIndex);
545 private void setMethodsDone(ClassFileReader reader){
547 reader.setMethodsDone( this);
550 private void setExceptionCount(ClassFileReader reader, Object tag, int exceptionCount){
552 reader.setExceptionCount( this, tag, exceptionCount);
555 private void setExceptionsDone(ClassFileReader reader, Object tag){
557 reader.setExceptionsDone( this, tag);
560 private void setException(ClassFileReader reader, Object tag, int exceptionIndex, String exceptionType){
562 reader.setException( this, tag, exceptionIndex, exceptionType);
565 private void setCode(ClassFileReader reader, Object tag, int maxStack, int maxLocals, int codeLength){
566 int p = pos + codeLength;
567 reader.setCode( this, tag, maxStack, maxLocals, codeLength);
570 private void setExceptionTableCount(ClassFileReader reader, Object tag, int exceptionTableCount){
572 reader.setExceptionHandlerTableCount( this, tag, exceptionTableCount);
575 private void setExceptionTableEntry(ClassFileReader reader, Object tag, int exceptionIndex,
576 int startPc, int endPc, int handlerPc, String catchType){
578 reader.setExceptionHandler( this, tag, exceptionIndex, startPc, endPc, handlerPc, catchType);
581 private void setExceptionTableDone(ClassFileReader reader, Object tag){
583 reader.setExceptionHandlerTableDone( this, tag);
587 private void setCodeAttributeCount(ClassFileReader reader, Object tag, int attrCount){
589 reader.setCodeAttributeCount( this, tag, attrCount);
592 private void setCodeAttribute(ClassFileReader reader, Object tag, int attrIndex, String name, int attrLength){
593 int p = pos + attrLength;
594 reader.setCodeAttribute( this, tag, attrIndex, name, attrLength);
597 private void setCodeAttributesDone(ClassFileReader reader, Object tag){
599 reader.setCodeAttributesDone( this, tag);
603 private void setLineNumberTableCount(ClassFileReader reader, Object tag, int lineNumberCount){
605 reader.setLineNumberTableCount( this, tag, lineNumberCount);
608 private void setLineNumber(ClassFileReader reader, Object tag, int lineIndex, int lineNumber, int startPc){
610 reader.setLineNumber( this, tag, lineIndex, lineNumber, startPc);
613 private void setLineNumberTableDone(ClassFileReader reader, Object tag){
615 reader.setLineNumberTableDone( this, tag);
619 private void setLocalVarTableCount(ClassFileReader reader, Object tag, int localVarCount){
621 reader.setLocalVarTableCount( this, tag, localVarCount);
624 private void setLocalVar(ClassFileReader reader, Object tag, int localVarIndex, String varName, String descriptor,
625 int scopeStartPc, int scopeEndPc, int slotIndex){
627 reader.setLocalVar( this, tag, localVarIndex, varName, descriptor, scopeStartPc, scopeEndPc, slotIndex);
630 private void setLocalVarTableDone(ClassFileReader reader, Object tag){
632 reader.setLocalVarTableDone( this, tag);
637 private void setClassAttributeCount(ClassFileReader reader, int attrCount){
639 reader.setClassAttributeCount( this, attrCount);
642 private void setClassAttribute(ClassFileReader reader, int attrIndex, String name, int attrLength){
643 int p = pos + attrLength;
644 reader.setClassAttribute( this, attrIndex, name, attrLength);
647 private void setClassAttributesDone(ClassFileReader reader){
649 reader.setClassAttributesDone(this);
653 private void setSourceFile(ClassFileReader reader, Object tag, String pathName){
655 reader.setSourceFile( this, tag, pathName);
659 private void setBootstrapMethodCount (ClassFileReader reader, Object tag, int bootstrapMethodCount){
661 reader.setBootstrapMethodCount( this, tag, bootstrapMethodCount);
664 private void setBootstrapMethod (ClassFileReader reader, Object tag, int idx,
665 int refKind, String cls, String mth, String descriptor, int[] cpArgs){
667 reader.setBootstrapMethod( this, tag, idx, refKind, cls, mth, descriptor, cpArgs);
670 private void setBootstrapMethodsDone (ClassFileReader reader, Object tag){
672 reader.setBootstrapMethodsDone( this, tag);
676 private void setInnerClassCount(ClassFileReader reader, Object tag, int innerClsCount){
678 reader.setInnerClassCount( this, tag, innerClsCount);
681 private void setInnerClass(ClassFileReader reader, Object tag, int innerClsIndex, String outerName, String innerName,
682 String innerSimpleName, int accessFlags){
684 reader.setInnerClass( this, tag, innerClsIndex, outerName, innerName, innerSimpleName, accessFlags);
687 private void setEnclosingMethod(ClassFileReader reader, Object tag, String enclosingClass, String enclosedMethod, String descriptor){
689 reader.setEnclosingMethod( this, tag, enclosingClass, enclosedMethod, descriptor);
692 private void setInnerClassesDone(ClassFileReader reader, Object tag){
694 reader.setInnerClassesDone(this, tag);
698 private void setAnnotationCount(ClassFileReader reader, Object tag, int annotationCount){
700 reader.setAnnotationCount( this, tag, annotationCount);
703 private boolean setAnnotation(ClassFileReader reader, Object tag, int annotationIndex, String annotationType){
706 reader.setAnnotation( this, tag, annotationIndex, annotationType);
709 } catch (SkipAnnotation sa) {
710 this.skipAnnotation(false);
716 * This is largely lifted from AnnotationParser.java
719 * u2 num_element_value_pairs;
721 * u2 element_name_index;
722 * element_value value;
723 * } element_value_pairs[num_element_value_pairs]
726 private void skipAnnotation(boolean skipTypeIndex) {
727 if(skipTypeIndex) { // we may want to skip after reading the type name
730 int numKV = readU2();
731 for(int i = 0; i < numKV; i++) {
732 readU2(); // skip name
738 * Skips an element_value
740 private void skipMemberValue() {
741 int tag = readUByte();
743 case 'e': // Enum value
744 pos += 4; // an enum value is a struct of two shorts, for 4 bytes total
747 skipAnnotation(true);
753 pos += 2; // either two bye const val index or two byte class info index
757 private void skipArray() {
759 for(int i = 0; i < len; i++) {
764 private void setAnnotationsDone(ClassFileReader reader, Object tag){
766 reader.setAnnotationsDone(this, tag);
770 private void setTypeAnnotationCount(ClassFileReader reader, Object tag, int annotationCount){
772 reader.setTypeAnnotationCount( this, tag, annotationCount);
775 private void setTypeAnnotationsDone(ClassFileReader reader, Object tag){
777 reader.setTypeAnnotationsDone(this, tag);
782 private void setAnnotationValueCount(ClassFileReader reader, Object tag, int annotationIndex, int nValuePairs){
784 reader.setAnnotationValueCount( this, tag, annotationIndex, nValuePairs);
787 private void setPrimitiveAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
788 String elementName, int arrayIndex, Object val){
790 reader.setPrimitiveAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
793 private void setStringAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
794 String elementName, int arrayIndex, String s){
796 reader.setStringAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, s);
799 private void setClassAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
800 String elementName, int arrayIndex, String typeName){
802 reader.setClassAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, typeName);
806 private void setAnnotationFieldValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex) {
808 reader.setAnnotationFieldValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex);
812 private void setEnumAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
813 String elementName, int arrayIndex, String enumType, String enumValue){
815 reader.setEnumAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, enumType, enumValue);
819 private void setAnnotationValueElementCount(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
820 String elementName, int elementCount){
822 reader.setAnnotationValueElementCount(this, tag, annotationIndex, valueIndex, elementName, elementCount);
825 private void setAnnotationValueElementsDone(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
828 reader.setAnnotationValueElementsDone(this, tag, annotationIndex, valueIndex, elementName);
832 public void setAnnotationValuesDone(ClassFileReader reader, Object tag, int annotationIndex){
834 reader.setAnnotationValuesDone(this, tag, annotationIndex);
838 private void setParameterCount(ClassFileReader reader, Object tag, int parameterCount){
840 reader.setParameterCount(this, tag, parameterCount);
843 private void setParameterAnnotationCount(ClassFileReader reader, Object tag, int paramIndex, int annotationCount){
845 reader.setParameterAnnotationCount(this, tag, paramIndex, annotationCount);
849 private boolean setParameterAnnotation(ClassFileReader reader, Object tag, int annotationIndex, String annotationType){
852 reader.setParameterAnnotation( this, tag, annotationIndex, annotationType);
855 } catch(SkipAnnotation s) {
856 this.skipAnnotation(false);
860 private void setParameterAnnotationsDone(ClassFileReader reader, Object tag, int paramIndex){
862 reader.setParameterAnnotationsDone(this, tag, paramIndex);
865 private void setParametersDone(ClassFileReader reader, Object tag){
867 reader.setParametersDone(this, tag);
871 public void setSignature(ClassFileReader reader, Object tag, String signature){
873 reader.setSignature(this, tag, signature);
880 * this is the main parsing routine that uses the ClassFileReader interface
881 * to tell clients about the classfile contents
883 * ClassFile structure: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#74353
884 * u4 magic; // 0xcafebabe
888 * u2 constant_pool_count;
889 * cp_entry constant_pool[constant_pool_count-1];
895 * u2 interfaces_count;
896 * u2 interfaces[interfaces_count];
899 * field_info fields[fields_count];
902 * method_info methods[methods_count];
904 * u2 attributes_count;
905 * attribute_info attributes[attributes_count];
907 public void parse( ClassFileReader reader) throws ClassParseException {
912 int magic = readI4();
913 if (magic != 0xCAFEBABE) {
914 error("wrong magic: " + Integer.toHexString(magic));
917 // we don't do much with the version numbers yet
918 int minor = readU2();
919 int major = readU2();
921 // get the const pool
922 int cpCount = readU2();
923 cpPos = new int[cpCount];
924 cpValue = new Object[cpCount];
927 // the class essentials
928 int accessFlags = readU2();
931 String clsName = (String) cpValue[cpIdx];
934 String superClsName = (String) cpValue[cpIdx];
937 setClass(reader, clsName, superClsName, accessFlags, cpCount);
940 int ifcCount = readU2();
941 parseInterfaces(reader, ifcCount);
944 int fieldCount = readU2();
945 parseFields(reader, fieldCount);
948 int methodCount = readU2();
949 parseMethods(reader, methodCount);
952 int classAttrCount = readU2();
953 parseClassAttributes(reader, classAttrCount);
956 // nothing, just a control exception to shortcut the classfile parsing
961 //--- constpool parsing
963 public static String readModifiedUTF8String( byte[] data, int pos, int len) throws ClassParseException {
965 int n = 0; // the number of chars in buf
966 char[] buf = new char[len]; // it can't be more, but it can be less chars
968 // \u0001 - \u007f : single byte chars: 0xxxxxxx
969 // \u0000 and \u0080 - \u07ff : double byte chars: 110xxxxx, 10xxxxxx
970 // \u0800 - \uffff : tripple byte chars: 1110xxxx, 10xxxxxx, 10xxxxxx
973 for (int i=pos; i<max; i++){
974 int c = data[i] & 0xff;
975 if ((c & 0x80) == 0){ // single byte char 0xxxxxxx
979 if ((c & 0x40) != 0){ // 11xxxxxx
981 // for the sake of efficiency, we don't check for the trailing zero bit in the marker,
982 // we just mask it out
983 if ((c & 0x20) == 0) { // 110xxxxx - double byte char
984 buf[n++] = (char) (((c & 0x1f) << 6) | (data[++i] & 0x3f));
986 } else { // 1110xxxx - tripple byte char
987 buf[n++] = (char) (((c & 0x0f) << 12) | ((data[++i] & 0x3f) << 6) | (data[++i] & 0x3f));
991 throw new ClassParseException("malformed modified UTF-8 input: ");
996 return new String(buf, 0, n);
1000 // the protected methods are called automatically, the public parse..Attr() methods
1001 // are called optionally from the corresponding ClassFileReader.set..Attribute() method.
1002 // Note that these calls have to provide the ClassFileReader as an argument because
1003 // we might actually switch to another reader (e.g. MethodInfos for parseCodeAttr)
1005 protected void parseCp(int cpCount) throws ClassParseException {
1008 byte[] data = this.data;
1009 int[] dataIdx = this.cpPos;
1010 Object[] values = this.cpValue;
1012 //--- first pass: store data index values and convert non-delegating constant values
1013 // cp_entry[0] is traditionally unused
1014 for (int i=1; i<cpCount; i++) {
1017 error("illegal constpool tag");
1019 case CONSTANT_UTF8: // utf8_info { u1 tag; u2 length; u1 bytes[length]; }
1021 int len = ((data[j++]&0xff) <<8) | (data[j++]&0xff);
1023 String s = readModifiedUTF8String( data, j, len);
1030 error("illegal constpool tag");
1032 case CONSTANT_INTEGER: // Integer_info { u1 tag; u4 bytes; }
1035 int iVal = (data[j++]&0xff)<<24 | (data[j++]&0xff)<<16 | (data[j++]&0xff)<<8 | (data[j++]&0xff);
1036 values[i] = new Integer(iVal);
1039 case CONSTANT_FLOAT: // Float_info { u1 tag; u4 bytes; }
1042 int iBits = (data[j++]&0xff)<<24 | (data[j++]&0xff)<<16 | (data[j++]&0xff)<<8 | (data[j++]&0xff);
1043 float fVal = Float.intBitsToFloat(iBits);
1044 values[i] = new Float(fVal);
1047 case CONSTANT_LONG: // Long_info { u1 tag; u4 high_bytes; u4 low_bytes; }
1049 long lVal = (data[j++]&0xffL)<<56 | (data[j++]&0xffL)<<48 | (data[j++]&0xffL)<<40 | (data[j++]&0xffL)<<32
1050 | (data[j++]&0xffL)<<24 | (data[j++]&0xffL)<<16 | (data[j++]&0xffL)<<8 | (data[j++]&0xffL);
1051 values[i] = new Long(lVal);
1053 dataIdx[++i] = -1; // 8 byte cpValue occupy 2 index slots
1056 case CONSTANT_DOUBLE: // Double_info { u1 tag; u4 high_bytes; u4 low_bytes; }
1059 long lBits = (data[j++]&0xffL)<<56 | (data[j++]&0xffL)<<48 | (data[j++]&0xffL)<<40 | (data[j++]&0xffL)<<32
1060 | (data[j++]&0xffL)<<24 | (data[j++]&0xffL)<<16 | (data[j++]&0xffL)<<8 | (data[j++]&0xffL);
1061 double dVal = Double.longBitsToDouble(lBits);
1062 values[i] = new Double(dVal);
1064 dataIdx[++i] = -1; // 8 byte cpValue occupy 2 index slots
1067 case CONSTANT_CLASS: // Class_info { u1 tag; u2 name_index<utf8>; }
1069 values[i] = CpInfo.ConstantClass;
1074 case CONSTANT_STRING: // String_info { u1 tag; u2 string_index<utf8>; }
1076 values[i] = CpInfo.ConstantString;
1081 case FIELD_REF: // Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
1083 values[i] = CpInfo.FieldRef;
1087 case METHOD_REF: // Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
1089 values[i] = CpInfo.MethodRef;
1093 case INTERFACE_METHOD_REF: // InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
1095 values[i] = CpInfo.InterfaceMethodRef;
1099 case NAME_AND_TYPE: // NameAndType_info { u1 tag; u2 name_index<utf8>; u2 descriptor_index<utf8>; }
1101 values[i] = CpInfo.NameAndType;
1106 //--- the Java 8 ones
1108 case METHOD_HANDLE: // MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index<mthref>; }
1110 values[i] = CpInfo.MethodHandle;
1114 case METHOD_TYPE: // MethodType_info { u1 tag; u2 descriptor_index<utf8>; }
1116 values[i] = CpInfo.MethodType;
1120 case INVOKE_DYNAMIC: // InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; }
1122 values[i] = CpInfo.InvokeDynamic;
1127 error("illegal constpool tag: " + data[j]);
1133 //--- second pass: store values of delegating constant values
1134 for (int i=1; i<cpCount; i++){
1135 Object v = cpValue[i];
1137 // we store string and class constants as their utf8 string values
1138 if (v == CpInfo.ConstantClass || v == CpInfo.ConstantString){
1139 cpValue[i] = cpValue[u2(cpPos[i]+1)];
1144 protected void parseInterfaces(ClassFileReader reader, int ifcCount){
1146 setInterfaceCount(reader, ifcCount);
1148 for (int i=0; i<ifcCount; i++){
1149 int cpIdx = readU2();
1150 setInterface(reader, i, classNameAt(cpIdx));
1153 setInterfacesDone(reader);
1157 protected void parseFields(ClassFileReader reader, int fieldCount) {
1159 setFieldCount(reader, fieldCount);
1161 for (int i=0; i<fieldCount; i++){
1162 int accessFlags = readU2();
1164 int cpIdx = readU2();
1165 String name = utf8At(cpIdx);
1168 String descriptor = utf8At(cpIdx);
1170 setField(reader, i, accessFlags, name, descriptor);
1172 int attrCount = readU2();
1173 parseFieldAttributes(reader, i, attrCount);
1175 setFieldDone(reader, i);
1178 setFieldsDone(reader);
1181 protected void parseFieldAttributes(ClassFileReader reader, int fieldIdx, int attrCount){
1182 setFieldAttributeCount(reader, fieldIdx, attrCount);
1184 for (int i=0; i<attrCount; i++){
1185 int cpIdx = readU2();
1186 String name = utf8At(cpIdx);
1188 name = internStdAttrName(cpIdx, name, stdFieldAttrs);
1190 int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1191 setFieldAttribute(reader, fieldIdx, i, name, attrLength);
1194 setFieldAttributesDone(reader, fieldIdx);
1198 * optionally called by reader to obtain a ConstantValue field attribute
1200 * ConstantValue {u2 attrName<utf8>; u4 attrLength; u2 constIndex<class|string|int|float|long|double> }
1202 * pos is at constIndex
1204 public void parseConstValueAttr(ClassFileReader reader, Object tag){
1205 int cpIdx = readU2();
1206 setConstantValue(reader, tag, cpValue[cpIdx]);
1211 protected void parseMethods(ClassFileReader reader, int methodCount) {
1213 setMethodCount(reader, methodCount);
1215 for (int i=0; i<methodCount; i++){
1216 int accessFlags = readU2();
1218 int cpIdx = readU2();
1219 String name = utf8At(cpIdx);
1222 String descriptor = utf8At(cpIdx);
1224 setMethod(reader, i, accessFlags, name, descriptor);
1226 int attrCount = readU2();
1227 parseMethodAttributes(reader, i, attrCount);
1229 setMethodDone(reader, i);
1232 setMethodsDone(reader);
1235 protected void parseMethodAttributes(ClassFileReader reader, int methodIdx, int attrCount){
1236 setMethodAttributeCount(reader, methodIdx, attrCount);
1238 for (int i=0; i<attrCount; i++){
1239 int cpIdx = readU2();
1240 String name = utf8At(cpIdx);
1242 name = internStdAttrName(cpIdx, name, stdMethodAttrs);
1244 int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1245 setMethodAttribute(reader, methodIdx, i, name, attrLength);
1248 setMethodAttributesDone(reader, methodIdx);
1251 public void parseExceptionAttr (ClassFileReader reader, Object tag){
1252 int exceptionCount = readU2();
1253 setExceptionCount(reader, tag, exceptionCount);
1255 for (int i=0; i<exceptionCount; i++){
1256 int cpIdx = readU2();
1257 String exceptionType = classNameAt(cpIdx);
1258 setException(reader, tag, i, exceptionType);
1261 setExceptionsDone(reader, tag);
1265 * (optionally) called by reader from within the setMethodAttribute() notification
1266 * This means we have recursive notification since this is a variable length
1267 * attribute that has variable length attributes
1269 * Code_attribute { u2 attr_name_index<utf8>; u4 attr_length;
1270 * u2 max_stack; u2 max_locals;
1271 * u4 code_length; u1 code[code_length];
1272 * u2 exception_table_length;
1273 * { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type<class_entry>;
1274 * } exception_table[exception_table_length];
1275 * u2 attributes_count;
1276 * attribute_info attributes[attributes_count]; }
1278 * pos is at max_stack
1280 public void parseCodeAttr (ClassFileReader reader, Object tag){
1281 int maxStack = readU2();
1282 int maxLocals = readU2();
1283 int codeLength = readI4(); // no code length > 2GB supported
1284 int codeStartPos = pos;
1286 setCode(reader, tag, maxStack, maxLocals, codeLength);
1288 int exceptionCount = readU2();
1289 setExceptionTableCount(reader, tag, exceptionCount);
1291 for (int i = 0; i < exceptionCount; i++) {
1292 int startPc = readU2();
1293 int endPc = readU2();
1294 int handlerPc = readU2();
1296 int cpIdx = readU2();
1297 String catchType = (String) cpValue[cpIdx]; // a Constant_class
1299 setExceptionTableEntry(reader, tag, i, startPc, endPc, handlerPc, catchType);
1301 setExceptionTableDone(reader, tag);
1303 int attrCount = readU2();
1304 parseCodeAttrAttributes(reader, tag, attrCount);
1308 protected void parseCodeAttrAttributes(ClassFileReader reader, Object tag, int attrCount){
1310 setCodeAttributeCount(reader, tag, attrCount);
1312 for (int i=0; i<attrCount; i++){
1313 int cpIdx = readU2();
1314 String name = utf8At(cpIdx);
1316 name = internStdAttrName(cpIdx, name, stdCodeAttrs);
1318 int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1319 setCodeAttribute(reader, tag, i, name, attrLength);
1322 setCodeAttributesDone(reader, tag);
1326 * optionally called from ClassFileReader.setCodeAttribute() to parse LineNumberTables
1327 * LineNumberTable { u2 attrName; u4 attrLength;
1329 * { u2 startPc; u2 lineNumber; } [lineCount] };
1330 * pos is at lineCount
1332 public void parseLineNumberTableAttr(ClassFileReader reader, Object tag){
1333 int lineCount = readU2();
1334 setLineNumberTableCount(reader, tag, lineCount);
1336 for (int i=0; i<lineCount; i++){
1337 int startPc = readU2();
1338 int lineNumber = readU2();
1339 setLineNumber(reader, tag, i, lineNumber, startPc);
1342 setLineNumberTableDone(reader, tag);
1347 * optionally called from ClassFileReader.setCodeAttribute() to parse LocalVarTables
1348 * LocalVarTableTable { u2 attrName; u4 attrLength;
1350 * { u2 startPc; u2 lineNumber; } [lineCount] };
1351 * pos is at localVarCount
1353 public void parseLocalVarTableAttr(ClassFileReader reader, Object tag){
1354 int localVarCount = readU2();
1355 setLocalVarTableCount(reader, tag, localVarCount);
1357 for (int i=0; i<localVarCount; i++){
1358 int startPc = readU2();
1359 int length = readU2();
1360 int cpIdx = readU2();
1361 String varName = (String) cpValue[cpIdx];
1363 String descriptor = (String) cpValue[cpIdx];
1364 int slotIndex = readU2();
1366 setLocalVar(reader, tag, i, varName, descriptor, startPc, startPc+length-1, slotIndex );
1369 setLocalVarTableDone(reader, tag);
1373 protected void parseClassAttributes(ClassFileReader reader, int attrCount){
1375 setClassAttributeCount(reader, attrCount);
1377 for (int i=0; i<attrCount; i++){
1378 int cpIdx = readU2();
1379 String name = utf8At(cpIdx);
1381 name = internStdAttrName(cpIdx, name, stdClassAttrs);
1383 int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1384 setClassAttribute(reader, i, name, attrLength);
1387 setClassAttributesDone(reader);
1392 * (optionally) called by ClassFileReader from within setClassAttribute() notification
1394 * InnerClass { u2 nameIdx<utf8>; u4 length; u2 sourceFile<utf8>; }
1396 public void parseSourceFileAttr(ClassFileReader reader, Object tag){
1397 int cpIdx = readU2();
1398 String pathName = utf8At(cpIdx);
1399 setSourceFile(reader, tag, pathName);
1403 * (optionally) called by ClassFileReader from within setClassAttribute() notification
1409 * { u2 innerCls<cls>;
1411 * u2 innerName<utf8>;
1412 * u2 innerAccessFlags;
1413 * } classes[classCount] }
1416 * pos is at classCount
1418 public void parseInnerClassesAttr(ClassFileReader reader, Object tag){
1419 int innerClsCount = readU2();
1420 setInnerClassCount(reader, tag, innerClsCount);
1422 for (int i = 0; i < innerClsCount; i++) {
1423 int cpIdx = readU2();
1424 String innerClsName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1426 String outerClsName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1428 String innerSimpleName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1429 int accessFlags = readU2();
1431 setInnerClass(reader, tag, i, outerClsName, innerClsName, innerSimpleName, accessFlags);
1434 setInnerClassesDone(reader, tag);
1438 * EnclosingMethod_attribute {
1439 * u2 attribute_name_index;
1440 * u4 attribute_length;
1441 * u2 class_index -> Class_info { u1 tag; u2 name_index->utf8 }
1442 * u2 method_index -> NameAndType_info { u1 tag; u2 name_index->utf8; u2 descriptor_index->utf8 }
1445 public void parseEnclosingMethodAttr(ClassFileReader reader, Object tag){
1446 String enclosedMethod = null;
1447 String descriptor = null;
1449 int cpIdx = readU2(); // start of Class_info
1450 String enclosingClass = nameAt(cpIdx);
1452 cpIdx = readU2(); // start of NameAndType_info
1454 // check if this is inside a method - we also get EnclosingMethod_infos for
1455 // classes that are not immediately enclosed
1457 enclosedMethod = nameAt(cpIdx);
1458 descriptor = descriptorAt(cpIdx);
1461 setEnclosingMethod(reader, tag, enclosingClass, enclosedMethod, descriptor);
1465 * BootstrapMethods_attribute {
1466 * u2 attribute_name_index;
1467 * u4 attribute_length;
1468 * u2 num_bootstrap_methods;
1469 * { u2 bootstrap_method_ref; -> MethodHandle
1470 * u2 num_bootstrap_arguments;
1471 * u2 bootstrap_arguments[num_bootstrap_arguments];
1472 * } bootstrap_methods[num_bootstrap_methods];
1475 * pos is at num_bootstrap_methods
1477 public void parseBootstrapMethodAttr (ClassFileReader reader, Object tag){
1478 int nBootstrapMethods = readU2();
1480 setBootstrapMethodCount(reader, tag, nBootstrapMethods);
1482 for (int i=0; i<nBootstrapMethods; i++){
1483 int cpMhIdx = readU2();
1484 int nArgs = readU2();
1485 int[] bmArgs = new int[nArgs];
1486 for (int j=0; j<nArgs; j++){
1487 bmArgs[j] = readU2();
1490 // kind of this method handle
1491 int refKind = mhRefTypeAt(cpMhIdx);
1493 // CONSTANT_Methodref_info structure
1494 int mrefIdx = mhMethodRefIndexAt(cpMhIdx);
1496 String clsName = methodClassNameAt(mrefIdx);
1497 String mthName = methodNameAt(mrefIdx);
1498 String descriptor = methodDescriptorAt(mrefIdx);
1500 setBootstrapMethod(reader, tag, i, refKind, clsName, mthName, descriptor, bmArgs);
1503 setBootstrapMethodsDone( reader, tag);
1506 String nameAt(int nameTypeInfoIdx) {
1507 return utf8At(u2(cpPos[nameTypeInfoIdx] + 1));
1510 String descriptorAt (int nameTypeInfoIdx){
1511 return utf8At( u2( cpPos[nameTypeInfoIdx]+3));
1514 // those are as per http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf
1520 * u2 const_value_index;
1521 * { u2 type_name_index; u2 const_name_index; } enum_const_value;
1522 * u2 class_info_index;
1523 * annotation annotation_value;
1524 * { u2 num_values; element_value values[num_values]; } array_value;
1527 * valid tags are primitve type codes B,C,D,F,I,J,S,Z
1528 * plus: 's'=String, 'e'=enum, 'c'=class, '@'=annotation, '['=array
1530 void parseAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex){
1534 int t = readUByte();
1537 // booleans have to be treated differently since there is no CONSTANT_Boolean, i.e. values are
1538 // stored as CONSTANT_Integer in the constpool, i.e. the cpValue doesn't have the right type
1540 val = cpValue[cpIdx];
1541 val = Boolean.valueOf((Integer)val == 1);
1542 setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1547 val = cpValue[cpIdx];
1548 val = Byte.valueOf(((Integer)val).byteValue());
1549 setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1554 val = cpValue[cpIdx];
1555 val = Character.valueOf((char)((Integer)val).shortValue());
1556 setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1561 val = cpValue[cpIdx];
1562 val = Short.valueOf(((Integer)val).shortValue());
1563 setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1571 val = cpValue[cpIdx];
1572 setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1577 String s = (String) cpValue[cpIdx];
1578 setStringAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, s);
1583 String enumTypeName = (String)cpValue[cpIdx];
1585 String enumConstName = (String)cpValue[cpIdx];
1586 setEnumAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, enumTypeName, enumConstName);
1591 String className = (String)cpValue[cpIdx];
1592 setClassAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, className);
1596 parseAnnotation(reader, tag, -1, false); // getting recursive here
1597 setAnnotationFieldValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex);
1601 int arrayLen = readU2();
1602 setAnnotationValueElementCount(reader, tag, annotationIndex, valueIndex, elementName, arrayLen);
1603 for (int i=0; i<arrayLen; i++){
1604 parseAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, i);
1606 setAnnotationValueElementsDone(reader, tag, annotationIndex, valueIndex, elementName);
1614 * u2 num_element_value_pairs;
1616 * u2 element_name_index;
1617 * element_value value;
1618 * } element_value_pairs[num_element_value_pairs]
1621 void parseAnnotation (ClassFileReader reader, Object tag, int annotationIndex, boolean isParameterAnnotation){
1622 int cpIdx = readU2();
1623 String annotationType = (String)cpValue[cpIdx];
1624 boolean parseValues;
1625 if (isParameterAnnotation){
1626 parseValues = setParameterAnnotation(reader, tag, annotationIndex, annotationType);
1628 parseValues = setAnnotation(reader, tag, annotationIndex, annotationType);
1631 parseAnnotationValues(reader, tag, annotationIndex);
1635 void parseAnnotationValues (ClassFileReader reader, Object tag, int annotationIndex){
1636 int nValuePairs = readU2();
1637 setAnnotationValueCount(reader, tag, annotationIndex, nValuePairs);
1639 for (int i=0; i<nValuePairs; i++){
1640 int cpIdx = readU2();
1641 String elementName = (String)cpValue[cpIdx];
1642 parseAnnotationValue(reader, tag, annotationIndex, i, elementName, -1);
1645 setAnnotationValuesDone(reader, tag, annotationIndex);
1649 * class, field, method annotation attributes (only one per target)
1651 * Runtime[In]VisibleAnnotations_attribute {
1652 * u2 attribute_name_index;
1653 * u4 attribute_length;
1654 * u2 num_annotations; << pos
1655 * annotation annotations[num_annotations];
1658 public void parseAnnotationsAttr (ClassFileReader reader, Object tag){
1659 int numAnnotations = readU2();
1660 setAnnotationCount(reader, tag, numAnnotations);
1662 for (int i=0; i<numAnnotations; i++){
1663 parseAnnotation(reader, tag, i, false);
1666 setAnnotationsDone(reader, tag);
1670 // JSR 308 type annotation target types
1671 public static final int CLASS_TYPE_PARAMETER = 0x00;
1672 public static final int METHOD_TYPE_PARAMETER = 0x01;
1673 public static final int CLASS_EXTENDS = 0x10;
1674 public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
1675 public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
1676 public static final int FIELD = 0x13;
1677 public static final int METHOD_RETURN = 0x14;
1678 public static final int METHOD_RECEIVER = 0x15;
1679 public static final int METHOD_FORMAL_PARAMETER = 0x16;
1680 public static final int THROWS = 0x17;
1681 public static final int LOCAL_VARIABLE = 0x40;
1682 public static final int RESOURCE_VARIABLE = 0x41;
1683 public static final int EXCEPTION_PARAMETER = 0x42;
1684 public static final int INSTANCEOF = 0x43;
1685 public static final int NEW = 0x44;
1686 public static final int CONSTRUCTOR_REFERENCE = 0x45;
1687 public static final int METHOD_REFERENCE = 0x46;
1688 public static final int CAST = 0x47;
1689 public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
1690 public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
1691 public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4a;
1692 public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4b;
1694 public static String getTargetTypeName (int targetType){
1695 switch (targetType){
1696 case CLASS_TYPE_PARAMETER: return "class type parameter";
1697 case METHOD_TYPE_PARAMETER: return "method type parameter";
1698 case CLASS_EXTENDS: return "super class";
1699 case CLASS_TYPE_PARAMETER_BOUND: return "class type parameter bound";
1700 case METHOD_TYPE_PARAMETER_BOUND: return "method type parameter bound";
1701 case FIELD: return "field";
1702 case METHOD_RETURN: return "method return";
1703 case METHOD_RECEIVER: return "method receiver";
1704 case METHOD_FORMAL_PARAMETER: return "method formal parameter";
1705 case THROWS: return "throws";
1706 case LOCAL_VARIABLE: return "local variable";
1707 case RESOURCE_VARIABLE: return "resource variable";
1708 case EXCEPTION_PARAMETER: return "exception parameter";
1709 case INSTANCEOF: return "instanceof";
1710 case NEW: return "new";
1711 case CONSTRUCTOR_REFERENCE: return "ctor reference";
1712 case METHOD_REFERENCE: return "method reference";
1713 case CAST: return "case";
1714 case METHOD_INVOCATION_TYPE_ARGUMENT: return "method invocation type argument";
1715 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: return "ctor reference type argument";
1716 case METHOD_REFERENCE_TYPE_ARGUMENT: return "method reference type argument";
1718 return "<unknown target type 0x" + Integer.toHexString(targetType);
1722 public static String getTypePathEncoding (short[] typePath){
1723 if (typePath == null){
1727 StringBuffer sb = new StringBuffer();
1728 for (int i=0; i<typePath.length;i++){
1729 int e = typePath[i];
1731 sb.append( Integer.toString((e>>8) & 0xff));
1732 sb.append( Integer.toString(e & 0xff));
1736 return sb.toString();
1739 public static String getScopeEncoding (long[] scopeEntries){
1740 StringBuffer sb = new StringBuffer();
1741 for (int i=0; i<scopeEntries.length;i++){
1742 long e = scopeEntries[i];
1743 int slotIndex = (int)(e & 0xffff);
1744 int length = (int)((e >> 16) & 0xffff);
1745 int startPc = (int)((e >> 32) & 0xffff);
1752 sb.append( Integer.toString(startPc));
1754 sb.append( Integer.toString(startPc + length-1));
1756 sb.append(slotIndex);
1759 return sb.toString();
1762 // JSR 308 type annotation, which adds 3 fields to the old annotation structure
1764 // type_annotation {
1765 // u1 target_type; // targeted program element (sec 3.2)
1766 // union { // ?? this is probably packed - variable size unions make no sense
1767 // type_parameter_target;
1768 // supertype_target;
1769 // type_parameter_bound_target;
1771 // method_formal_parameter_target;
1776 // type_argument_target;
1777 // } target_info; // targeted program element (sec 3.3)
1779 // type_path target_path; // encoding of annotation position in compound type (array, generic, etc., sec 3.4)
1781 // // standard annotation fields
1782 // u2 type_index; // the annotation type
1783 // u2 num_element_value_pairs;
1785 // u2 element_name_index;
1786 // element_value value;
1787 // } element_value_pairs[num_element_value_pairs];
1790 // struct type_path {
1792 // type_path_entry path[path_length];
1795 // struct type_path_entry {
1796 // u1 type_path_kind;
1797 // // 0: deeper in array type
1798 // // 1: deeper in nested type
1799 // // 2: bound of wildcard typearg
1800 // // 3: type argument of parameterized type
1801 // u1 type_argument_index;
1802 // // 0, if type_path_kind == 0,1,2
1803 // // 0-based index of type arg in parameterized type if type_path_kind i== 3
1806 int getTargetInfoSize (int targetType){
1807 int len = 3; // max static length are xx_TYPE_ARGUMENTs
1808 if (targetType == LOCAL_VARIABLE || targetType == RESOURCE_VARIABLE){
1809 len = Math.max( len, u2(pos) * 6); // three u2 values per entry
1815 int getTypePathSize (short[] typePath){
1816 int typePathSize = 1;
1817 if (typePath != null) {
1818 typePathSize += typePath.length * 2;
1820 return typePathSize;
1824 short[] readTypePath (){
1825 short[] typePath = null;
1827 int pathLength = readUByte();
1828 if (pathLength > 0){
1829 typePath = new short[pathLength];
1830 for (int i=0; i<pathLength; i++){
1831 int pathKind = (short)readUByte();
1832 int argIdx = (short)readUByte();
1833 typePath[i]= (short)((pathKind << 8) | argIdx);
1840 String readAnnotationType (){
1841 int cpIdx = readU2();
1842 String annotationType = (String)cpValue[cpIdx];
1843 return annotationType;
1846 void setTypeAnnotation (ClassFileReader reader, Object tag, int annotationIndex) {
1847 int targetType = readUByte();
1849 switch (targetType){
1850 case CLASS_TYPE_PARAMETER:
1851 case METHOD_TYPE_PARAMETER: {
1852 // type_parameter_target { u1 type_parameter_index; }
1853 int typeParamIdx = readUByte();
1854 reader.setTypeParameterAnnotation( this, tag, annotationIndex, targetType, typeParamIdx, readTypePath(), readAnnotationType());
1857 case CLASS_EXTENDS: {
1858 // supertype_target { u2 supertype_index; }
1859 int superTypeIdx = readU2();
1860 reader.setSuperTypeAnnotation( this, tag, annotationIndex, targetType, superTypeIdx, readTypePath(), readAnnotationType());
1863 case CLASS_TYPE_PARAMETER_BOUND:
1864 case METHOD_TYPE_PARAMETER_BOUND: {
1865 // type_parameter_bound_target { u1 type_parameter_index; u1 bound_index; }
1866 int typeParamIdx = readUByte();
1867 int boundIdx = readUByte();
1868 reader.setTypeParameterBoundAnnotation(this, tag, annotationIndex, targetType, typeParamIdx, boundIdx, readTypePath(), readAnnotationType());
1872 case METHOD_RECEIVER:
1875 reader.setTypeAnnotation( this, tag, annotationIndex, targetType, readTypePath(), readAnnotationType());
1878 case METHOD_FORMAL_PARAMETER: {
1879 // method_formal_parameter_target { u1 method_formal_parameter_index; }
1880 int formalParamIdx = readUByte();
1881 reader.setFormalParameterAnnotation( this, tag, annotationIndex, targetType, formalParamIdx, readTypePath(), readAnnotationType());
1885 // throws_target { u2 throws_type_index; }
1886 int throwsTypeIdx = readU2();
1887 reader.setThrowsAnnotation( this, tag, annotationIndex, targetType, throwsTypeIdx, readTypePath(), readAnnotationType());
1890 case LOCAL_VARIABLE:
1891 case RESOURCE_VARIABLE: {
1892 // this can't just refer to a LocalVarInfo since those depend on debug compile options
1894 // localvar_target {
1895 // u2 table_length; // number of entries, not bytes
1898 // u2 length; // bytecode offset length
1899 // u2 index; // local var idx
1900 // } table[table_length];
1902 int tableLength = readU2();
1903 long[] scopeEntries = new long[tableLength];
1904 for (int i=0; i<tableLength; i++){
1905 int startPc = readU2();
1906 int length = readU2();
1907 int slotIdx = readU2();
1908 scopeEntries[i] = ((long)startPc << 32) | ((long)length << 16) | slotIdx;
1910 reader.setVariableAnnotation( this, tag, annotationIndex, targetType, scopeEntries, readTypePath(), readAnnotationType());
1913 case EXCEPTION_PARAMETER: {
1914 // catch_target { u2 exception_table_index; }
1915 int exceptionIdx = readU2();
1916 reader.setExceptionParameterAnnotation( this, tag, annotationIndex, targetType, exceptionIdx, readTypePath(), readAnnotationType());
1920 case METHOD_REFERENCE:
1921 case CONSTRUCTOR_REFERENCE:
1923 // offset_target { u2 offset; } // insn offset within bytecode
1924 int offset = readU2();
1925 reader.setBytecodeAnnotation(this, tag, annotationIndex, targetType, offset, readTypePath(), readAnnotationType());
1929 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
1930 case METHOD_INVOCATION_TYPE_ARGUMENT:
1931 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
1932 case METHOD_REFERENCE_TYPE_ARGUMENT: {
1933 // type_argument_target {
1935 // u1 type_argument_index;
1937 int offset = readU2();
1938 int typeArgIdx = readUByte();
1939 reader.setBytecodeTypeParameterAnnotation(this, tag, annotationIndex, targetType, offset, typeArgIdx, readTypePath(), readAnnotationType());
1944 // <2do - report this to the reader
1945 throw new RuntimeException("unknown type annotation target: 0x" + Integer.toHexString(targetType));
1950 void parseTypeAnnotation (ClassFileReader reader, Object tag, int annotationIndex) {
1952 // this does the respective setXTypeAnnotation() reader callback
1953 //dumpData(pos, 16);
1954 setTypeAnnotation(reader, tag, annotationIndex);
1956 // now set the annotation value pairs
1957 parseAnnotationValues( reader, tag, annotationIndex);
1961 * Runtime[In]VisibleTypeAnnotations_attribute {
1962 * u2 attribute_name_index;
1963 * u4 attribute_length;
1964 * u2 num_annotations;
1965 * type_annotation annotations[num_annotations];
1968 public void parseTypeAnnotationsAttr (ClassFileReader reader, Object tag) {
1969 int numAnnotations = readU2();
1970 setTypeAnnotationCount(reader, tag, numAnnotations);
1972 for (int i=0; i<numAnnotations; i++){
1973 parseTypeAnnotation(reader, tag, i);
1976 setTypeAnnotationsDone(reader, tag);
1980 * RuntimeInvisibleParameterAnnotations_attribute {
1981 * u2 attribute_name_index;
1982 * u4 attribute_length;
1983 * u1 num_parameters; << pos
1985 * u2 num_annotations;
1986 * annotation annotations[num_annotations];
1987 * } parameter_annotations[num_parameters];
1990 public void parseParameterAnnotationsAttr(ClassFileReader reader, Object tag){
1991 int numParameters = readUByte();
1992 setParameterCount(reader, tag, numParameters);
1993 for (int i=0; i<numParameters; i++){
1994 int numAnnotations = readU2();
1996 setParameterAnnotationCount(reader, tag, i, numAnnotations);
1997 for (int j=0; j<numAnnotations; j++){
1998 parseAnnotation(reader, tag, j, true);
2000 setParameterAnnotationsDone(reader, tag, i);
2002 setParametersDone(reader, tag);
2006 * Signature_attribute {
2007 * u2 attribute_name_index;
2009 * u2 signature-index << pos
2012 public void parseSignatureAttr(ClassFileReader reader, Object tag){
2013 int cpIdx = readU2();
2014 setSignature(reader, tag, utf8At(cpIdx));
2019 * AnnotationDefault_attribute {
2020 * u2 attribute_name_index;
2021 * u4 attribute_length;
2022 * element_value default_value; << pos
2025 public void parseAnnotationDefaultAttr(ClassFileReader reader, Object tag){
2026 parseAnnotationValue(reader, tag, -1, -1, null, -1);
2030 // EnclosingMethod_attribute {
2031 // u2 attribute_name_index;
2032 // u4 attribute_length;
2037 // LocalVariableTypeTable_attribute { // Code attr
2038 // u2 attribute_name_index;
2039 // u4 attribute_length;
2040 // u2 local_variable_type_table_length;
2045 // u2 signature_index;
2047 // } local_variable_type_table[local_variable_type_table_length];
2053 public void parseBytecode(JVMByteCodeReader reader, Object tag, int codeLength){
2060 boolean isWide = false; // modifier for Xload,Xstore,ret and iinc
2063 int endPos = pos+codeLength;
2067 while (pos < endPos){
2068 pc = pos - startPos;
2070 int opcode = readUByte();
2075 case 1: // aconst_null
2076 reader.aconst_null();
2078 case 2: // iconst_m1
2102 case 10: // lconst_1
2105 case 11: // fconst_0
2108 case 12: // fconst_1
2111 case 13: // fconst_2
2114 case 14: // dconst_0
2117 case 15: // dconst_1
2121 constVal = readByte();
2122 reader.bipush(constVal);
2125 constVal = readI2();
2126 reader.sipush(constVal);
2129 cpIdx = readUByte();
2134 reader.ldc_w_(cpIdx);
2138 reader.ldc2_w(cpIdx);
2141 localVarIndex = isWide ? readU2() : readUByte();
2142 reader.iload(localVarIndex);
2145 localVarIndex = isWide ? readU2() : readUByte();
2146 reader.lload(localVarIndex);
2149 localVarIndex = isWide ? readU2() : readUByte();
2150 reader.fload(localVarIndex);
2153 localVarIndex = isWide ? readU2() : readUByte();
2154 reader.dload(localVarIndex);
2157 localVarIndex = isWide ? readU2() : readUByte();
2158 reader.aload(localVarIndex);
2245 localVarIndex = isWide ? readU2() : readUByte();
2246 reader.istore(localVarIndex);
2249 localVarIndex = isWide ? readU2() : readUByte();
2250 reader.lstore(localVarIndex);
2253 localVarIndex = isWide ? readU2() : readUByte();
2254 reader.fstore(localVarIndex);
2257 localVarIndex = isWide ? readU2() : readUByte();
2258 reader.dstore(localVarIndex);
2261 localVarIndex = isWide ? readU2() : readUByte();
2262 reader.astore(localVarIndex);
2264 case 59: // istore_0
2267 case 60: // istore_1
2270 case 61: // istore_2
2273 case 62: // istore_3
2276 case 63: // lstore_0
2279 case 64: // lstore_1
2282 case 65: // lstore_2
2285 case 66: // lstore_3
2288 case 67: // fstore_0
2291 case 68: // fstore_1
2294 case 69: // fstore_2
2297 case 70: // fstore_3
2312 case 75: // astore_0
2315 case 76: // astore_1
2318 case 77: // astore_2
2321 case 78: // astore_3
2485 localVarIndex = readU2();
2486 constVal = readI2();
2488 localVarIndex = readUByte();
2489 constVal = readByte();
2491 reader.iinc(localVarIndex, constVal);
2555 reader.ifeq(offset);
2559 reader.ifne(offset);
2563 reader.iflt(offset);
2567 reader.ifge(offset);
2571 reader.ifgt(offset);
2575 reader.ifle(offset);
2577 case 159: // if_icmpeq
2579 reader.if_icmpeq(offset);
2581 case 160: // if_icmpne
2583 reader.if_icmpne(offset);
2585 case 161: // if_icmplt
2587 reader.if_icmplt(offset);
2589 case 162: // if_icmpge
2591 reader.if_icmpge(offset);
2593 case 163: // if_icmpgt
2595 reader.if_icmpgt(offset);
2597 case 164: // if_icmple
2599 reader.if_icmple(offset);
2601 case 165: // if_acmpeq
2603 reader.if_acmpeq(offset);
2605 case 166: // if_acmpne
2607 reader.if_acmpne(offset);
2611 reader.goto_(offset);
2618 localVarIndex = isWide ? readU2() : readUByte();
2619 reader.ret(localVarIndex);
2621 case 170: // tableswitch
2622 pos = (((pc+4)>>2)<<2)+startPos; // skip over padding
2624 defaultOffset = readI4();
2626 int high = readI4();
2628 int len = high-low+1;
2629 nextPos = pos + len*4;
2630 reader.tableswitch(defaultOffset, low, high);
2633 case 171: // lookupswitch
2634 pos = (((pc+4)>>2)<<2)+startPos; // skip over padding
2636 defaultOffset = readI4();
2637 int nPairs = readI4();
2639 nextPos = pos + (nPairs*8);
2640 reader.lookupswitch(defaultOffset, nPairs);
2643 case 172: // ireturn
2646 case 173: // lreturn
2649 case 174: // freturn
2652 case 175: // dreturn
2655 case 176: // areturn
2661 case 178: // getstatic
2662 cpIdx = readU2(); // CP index of fieldRef
2663 reader.getstatic(cpIdx);
2665 case 179: // putstatic
2666 cpIdx = readU2(); // CP index of fieldRef
2667 reader.putstatic(cpIdx);
2669 case 180: // getfield
2670 cpIdx = readU2(); // CP index of fieldRef
2671 reader.getfield(cpIdx);
2673 case 181: // putfield
2674 cpIdx = readU2(); // CP index of fieldRef
2675 reader.putfield(cpIdx);
2677 case 182: // invokevirtual
2678 cpIdx = readU2(); // CP index of methodRef
2679 reader.invokevirtual(cpIdx);
2681 case 183: // invokespecial
2682 cpIdx = readU2(); // CP index of methodRef
2683 reader.invokespecial(cpIdx);
2685 case 184: // invokestatic
2686 cpIdx = readU2(); // CP index of methodRef
2687 reader.invokestatic(cpIdx);
2689 case 185: // invokeinterface
2690 cpIdx = readU2(); // CP index of methodRef
2691 int count = readUByte();
2692 int zero = readUByte(); // must be 0
2693 reader.invokeinterface(cpIdx, count, zero);
2695 case 186: // invokedynamic
2696 cpIdx = readU2(); // CP index of bootstrap method
2699 reader.invokedynamic(cpIdx);
2705 case 188: // newarray
2706 int aType = readUByte();
2707 reader.newarray(aType);
2709 case 189: // anewarray
2710 cpIdx = readU2(); // CP index of component type
2711 reader.anewarray(cpIdx);
2713 case 190: // arraylength
2714 reader.arraylength();
2719 case 192: // checkcast
2720 cpIdx = readU2(); // cast type cp index
2721 reader.checkcast(cpIdx);
2723 case 193: // instanceof
2724 cpIdx = readU2(); // check type cp index
2725 reader.instanceof_(cpIdx);
2727 case 194: // monitorenter
2728 reader.monitorenter();
2730 case 195: // monitorexit
2731 reader.monitorexit();
2735 // affects immediate operand width if next bytecode is:
2736 // iload,fload,aload,lload,dload,
2737 // istore,fstore,astore,lstore,dstore
2741 case 197: // multianewarray
2743 int dimensions = readUByte();
2744 reader.multianewarray(cpIdx, dimensions);
2748 reader.ifnull(offset);
2750 case 199: // ifnonnull
2752 reader.ifnonnull(offset);
2756 reader.goto_w(offset);
2760 reader.jsr_w(offset);
2765 reader.unknown(opcode);
2768 isWide = false; // reset wide modifier
2773 //--- those can only be called from within a JVMByteCodeReader.tableswitch() notification
2774 public void parseTableSwitchEntries(JVMByteCodeReader reader, int low, int high){
2775 for (int val=low; val<=high; val++){
2776 int offset = readI4();
2777 reader.tableswitchEntry(val, offset);
2780 public int getTableSwitchOffset(int low, int high, int defaultOffset, int val){
2781 if (val < low || val > high){
2782 return defaultOffset;
2785 int n = Math.abs(val - low);
2787 int pcOffset = readI4();
2792 //--- those can only be called from within a JVMByteCodeReader.lookupswitch() notification
2793 public void parseLookupSwitchEntries(JVMByteCodeReader reader, int nEntries){
2794 for (int i=0; i<nEntries; i++){
2795 int value = readI4();
2796 int offset = readI4();
2797 reader.lookupswitchEntry(i, value, offset);
2800 public int getLookupSwitchOffset(int nEntries, int defaultOffset, int val){
2801 for (int i=0; i<nEntries; i++){
2802 int match = readI4();
2805 } else if (val == match) {
2806 int offset = readI4();
2812 return defaultOffset;