d3dbdb5290433d2ed8321128ce7569d62c951961
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / ClassFile.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
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
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
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.
17  */
18
19 package gov.nasa.jpf.jvm;
20
21 import gov.nasa.jpf.jvm.JVMByteCodeReader;
22 import gov.nasa.jpf.vm.ClassParseException;
23 import gov.nasa.jpf.JPFException;
24 import gov.nasa.jpf.util.BailOut;
25 import gov.nasa.jpf.util.BinaryClassSource;
26
27 import java.io.File;
28
29 /**
30  * class to read and dissect Java classfile contents (as specified by the Java VM
31  * spec  http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#16628
32  */
33 public class ClassFile extends BinaryClassSource {
34
35   public static final int CONSTANT_UTF8 = 1;
36   public static final int CONSTANT_INTEGER = 3;
37   public static final int CONSTANT_FLOAT = 4;
38   public static final int CONSTANT_LONG = 5;
39   public static final int CONSTANT_DOUBLE = 6;
40   public static final int CONSTANT_CLASS = 7;
41   public static final int CONSTANT_STRING = 8;
42   public static final int FIELD_REF = 9;
43   public static final int METHOD_REF = 10;
44   public static final int INTERFACE_METHOD_REF = 11;
45   public static final int NAME_AND_TYPE = 12;
46   public static final int METHOD_HANDLE = 15;
47   public static final int METHOD_TYPE = 16;
48   public static final int INVOKE_DYNAMIC = 18;
49
50   public static final int REF_GETFIELD = 1;
51   public static final int REF_GETSTATIC = 2;
52   public static final int REF_PUTFIELD = 3;
53   public static final int REF_PUTSTATIC = 4;
54   public static final int REF_INVOKEVIRTUAL = 5;
55   public static final int REF_INVOKESTATIC = 6;
56   public static final int REF_INVOKESPECIAL = 7;
57   public static final int REF_NEW_INVOKESPECIAL = 8;
58   public static final int REF_INVOKEINTERFACE = 9;
59
60   // used to store types in cpValue[]
61   public static enum CpInfo {
62     Unused_0,                 // 0
63     ConstantUtf8,             // 1
64     Unused_2,                 // 2
65     ConstantInteger,          // 3
66     ConstantFloat,            // 4
67     ConstantLong,             // 5
68     ConstantDouble,           // 6
69     ConstantClass,            // 7
70     ConstantString,           // 8
71     FieldRef,                 // 9
72     MethodRef,                // 10
73     InterfaceMethodRef,       // 11
74     NameAndType,              // 12
75     Unused_13,
76     Unused_14,
77     MethodHandle,             // 15
78     MethodType,               // 16
79     Unused_17,
80     InvokeDynamic             // 18
81   }
82
83   // <2do> this is going away
84   String requestedTypeName; // the type name that caused this classfile to be loaded
85
86   // the const pool
87   int[] cpPos;     // cpPos[i] holds data start index for cp_entry i (0 is unused)
88   Object[] cpValue; // cpValue[i] hold the String/Integer/Float/Double associated with corresponding cp_entries
89   
90   //--- ctors
91   public ClassFile (byte[] data, int offset){
92     super(data,offset);
93   }
94
95   public ClassFile (byte[] data){
96     super(data,0);
97   }
98
99   public ClassFile (String typeName, byte[] data){
100     super(data,0);
101     
102     this.requestedTypeName = typeName;
103   }
104   
105   public ClassFile (String typeName, byte[] data, int offset){
106     super(data, offset);
107     
108     this.requestedTypeName = typeName;
109   }
110
111   public ClassFile (File file) throws ClassParseException {
112     super(file);
113   }
114
115   public ClassFile (String pathName)  throws ClassParseException {
116     super( new File(pathName));
117   }
118
119
120
121   
122   /**
123    * set classfile data.  This is mainly provided to allow
124    * on-the-fly classfile instrumentation with 3rd party libraries
125    * 
126    * BEWARE - like getData(), this method can cause parsing to fail if the
127    * provided data does not conform to the VM specs. In particular, this
128    * method should ONLY be called before executing parse(ClassFileReader) and
129    * will otherwise throw a JPFException
130    */
131   public void setData(byte[] newData){
132     if (cpPos != null){
133       throw new JPFException("concurrent modification of ClassFile data");
134     }
135     
136     data = newData;
137   }
138   
139   /**
140    * return the typename this classfile gets loaded for
141    * <2do> this is going away
142    */
143   public String getRequestedTypeName(){
144     return requestedTypeName;
145   }
146
147
148   //--- general attributes
149   public static final String SYNTHETIC_ATTR = "Synthetic";
150   public static final String DEPRECATED_ATTR = "Deprecated";
151   public static final String SIGNATURE_ATTR = "Signature";
152   public static final String RUNTIME_INVISIBLE_ANNOTATIONS_ATTR = "RuntimeInvisibleAnnotations";
153   public static final String RUNTIME_VISIBLE_ANNOTATIONS_ATTR = "RuntimeVisibleAnnotations";
154   public static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR = "RuntimeVisibleTypeAnnotations";
155
156   //--- standard field attributes
157   public static final String CONST_VALUE_ATTR = "ConstantValue";
158
159   protected final static String[] stdFieldAttrs = {
160     CONST_VALUE_ATTR, SYNTHETIC_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
161     RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR };
162
163
164   //--- standard method attributes
165   public static final String CODE_ATTR = "Code";
166   public static final String EXCEPTIONS_ATTR = "Exceptions";
167   public static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS_ATTR = "RuntimeInvisibleParameterAnnotations";
168   public static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTR = "RuntimeVisibleParameterAnnotations";
169   public static final String ANNOTATIONDEFAULT_ATTR = "AnnotationDefault";
170
171   protected final static String[] stdMethodAttrs = { 
172     CODE_ATTR, EXCEPTIONS_ATTR, SYNTHETIC_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
173     RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR,
174     RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS_ATTR,
175     RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTR,
176     RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR,
177     ANNOTATIONDEFAULT_ATTR
178   };
179
180
181   //--- standard code attributes
182   public static final String LINE_NUMBER_TABLE_ATTR = "LineNumberTable";
183   public static final String LOCAL_VAR_TABLE_ATTR = "LocalVariableTable";
184
185   protected final static String[] stdCodeAttrs = { LINE_NUMBER_TABLE_ATTR, LOCAL_VAR_TABLE_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR };
186
187
188   //--- standard class attributes
189   public static final String  SOURCE_FILE_ATTR = "SourceFile";
190   public static final String  INNER_CLASSES_ATTR = "InnerClasses";
191   public static final String  ENCLOSING_METHOD_ATTR = "EnclosingMethod";
192   public static final String  BOOTSTRAP_METHOD_ATTR = "BootstrapMethods";
193   
194   protected final static String[] stdClassAttrs = {
195     SOURCE_FILE_ATTR, DEPRECATED_ATTR, INNER_CLASSES_ATTR, DEPRECATED_ATTR, SIGNATURE_ATTR,
196     RUNTIME_INVISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_ANNOTATIONS_ATTR, RUNTIME_VISIBLE_TYPE_ANNOTATIONS_ATTR,
197     ENCLOSING_METHOD_ATTR, BOOTSTRAP_METHOD_ATTR };
198
199
200   protected String internStdAttrName(int cpIdx, String name, String[] stdNames){
201     for (int i=0; i<stdNames.length; i++){
202       if (stdNames[i] == name) return name;
203     }
204     for (int i=0; i<stdNames.length; i++){
205       String stdName = stdNames[i];
206       if (stdName.equals(name)){
207         cpValue[cpIdx] = stdName;
208         return stdName;
209       }
210     }
211     return name;
212   }
213
214
215   //--- constpool access
216
217   //--- the primitive info cpValue
218   public String utf8At(int utf8InfoIdx){
219     //assert data[cpPos[utf8InfoIdx]] == 1 : "not a utf8_info tag";
220     return (String) cpValue[utf8InfoIdx];
221   }
222
223   public int intAt(int intInfoIdx){
224     //assert data[cpPos[intInfoIdx]] == 3 : "not a int_info tag";
225     return (Integer) cpValue[intInfoIdx];
226   }
227
228   public float floatAt(int floatInfoIdx){
229     //assert data[cpPos[floatInfoIdx]] == 4 : "not a float_info tag";
230     return (Float) cpValue[floatInfoIdx];
231   }
232
233   public long longAt(int longInfoIdx){
234     //assert data[cpPos[longInfoIdx]] == 5 : "not a long_info tag";
235     return (Long) cpValue[longInfoIdx];
236   }
237
238   public double doubleAt(int doubleInfoIdx){
239     //assert data[cpPos[doubleInfoIdx]] == 6 : "not a double_info tag";
240     return (Double) cpValue[doubleInfoIdx];
241   }
242
243   //--- those two are delegated but resolved
244   public String classNameAt(int classInfoIdx){
245     //assert data[cpPos[classInfoIdx]] == 7 : "not a Class_info tag";
246     return (String) cpValue[classInfoIdx];
247   }
248
249   public String stringAt(int stringInfoIdx){
250     //assert data[cpPos[stringInfoIdx]] == 8 : "not a String_info tag";
251     return (String) cpValue[stringInfoIdx];
252   }
253
254   //--- composite infos
255
256   // the generic ones (if we don't care what kind of reference type this is)
257   public String refClassNameAt(int cpIdx){
258     return (String) cpValue[ u2(cpPos[cpIdx]+1)];
259   }
260   public String refNameAt(int cpIdx){
261     return utf8At( u2( cpPos[ u2(cpPos[cpIdx]+3)]+1));
262   }
263   public String refDescriptorAt(int cpIdx){
264     return utf8At( u2( cpPos[ u2(cpPos[cpIdx]+3)]+3));
265   }
266
267   public int mhRefTypeAt (int methodHandleInfoIdx){
268     return u1(cpPos[methodHandleInfoIdx]+1);
269   }
270   public int mhMethodRefIndexAt  (int methodHandleInfoIdx){
271     return u2(cpPos[methodHandleInfoIdx]+2);
272   }
273   
274   // those could check ref types
275   public String fieldClassNameAt(int fieldRefInfoIdx){
276     //assert data[cpPos[fieldRefInfoIdx]] == 9 : "not a Fieldref_info tag";
277     return (String) cpValue[ u2(cpPos[fieldRefInfoIdx]+1)];
278   }
279   public String fieldNameAt(int fieldRefInfoIdx){
280     return utf8At( u2( cpPos[ u2(cpPos[fieldRefInfoIdx]+3)]+1));
281   }
282   public String fieldDescriptorAt(int fieldRefInfoIdx){
283     return utf8At( u2( cpPos[ u2(cpPos[fieldRefInfoIdx]+3)]+3));
284   }
285
286   public String methodClassNameAt(int methodRefInfoIdx){
287     return (String) cpValue[ u2(cpPos[methodRefInfoIdx]+1)];
288   }
289   public String methodNameAt(int methodRefInfoIdx){
290     return utf8At( u2( cpPos[ u2(cpPos[methodRefInfoIdx]+3)]+1));
291   }
292   public String methodDescriptorAt(int methodRefInfoIdx){
293     return utf8At( u2( cpPos[ u2(cpPos[methodRefInfoIdx]+3)]+3));
294   }
295
296   public String methodTypeDescriptorAt (int methodTypeInfoIdx){
297     return utf8At( u2(cpPos[methodTypeInfoIdx]+1));
298   }
299   
300   public String interfaceMethodClassNameAt(int ifcMethodRefInfoIdx){
301     return (String) cpValue[ u2(cpPos[ifcMethodRefInfoIdx]+1)];
302   }
303   public String interfaceMethodNameAt(int ifcMethodRefInfoIdx){
304     return utf8At( u2( cpPos[ u2(cpPos[ifcMethodRefInfoIdx]+3)]+1));
305   }
306   public String interfaceMethodDescriptorAt(int ifcMethodRefInfoIdx){
307     return utf8At( u2( cpPos[ u2(cpPos[ifcMethodRefInfoIdx]+3)]+3));
308   }
309   
310   public int bootstrapMethodIndex (int cpInvokeDynamicIndex){
311     return u2(cpPos[cpInvokeDynamicIndex]+1);
312   }
313   public String samMethodNameAt(int cpInvokeDynamicIndex) {
314     return utf8At( u2( cpPos[ u2(cpPos[cpInvokeDynamicIndex]+3)]+1)); 
315   }
316   public String callSiteDescriptor(int cpInvokeDynamicIndex) {
317     return utf8At( u2( cpPos[ u2(cpPos[cpInvokeDynamicIndex]+3)]+3)); 
318   }
319   
320   public String getRefTypeName (int refCode){
321     switch (refCode){
322       case REF_GETFIELD:      return "getfield";
323       case REF_GETSTATIC:     return "getstatic";
324       case REF_PUTFIELD:      return "putfield";
325       case REF_PUTSTATIC:     return "putstatic";
326       case REF_INVOKEVIRTUAL: return "invokevirtual";
327       case REF_INVOKESTATIC:  return "invokestatic";
328       case REF_INVOKESPECIAL: return "invokespecial";
329       case REF_NEW_INVOKESPECIAL: return "new-invokespecial";
330       case REF_INVOKEINTERFACE: return "invokeinterface";
331       default:
332         return "<unknown>";
333     }
334   }
335   
336   public String getTypeName (int typeCode){
337     switch(typeCode){
338       case 4: return "boolean";
339       case 5: return "char";
340       case 6: return "float";
341       case 7: return "double";
342       case 8: return "byte";
343       case 9: return "short";
344       case 10: return "int";
345       case 11: return "long";
346       default:
347         return "<unknown>";
348     }
349   }
350
351   @Override
352   public int getPos(){
353     return pos;
354   }
355
356   public int getPc(){
357     return pc;
358   }
359
360   //--- traverse/analyze the const pool (this is rather exotic)
361
362   public int getNumberOfCpEntries(){
363     return cpValue.length;
364   }
365
366   public Object getCpValue (int i){
367     return cpValue[i];
368   }
369
370   public int getCpTag (int i){
371     return data[cpPos[i]];
372   }
373
374   /**
375    * the result can be used as input for u2(dataIndex)
376    *
377    * NOTE - this returns -1 for the dreaded unused extra entries associated
378    * with ConstantDouble and ConstantLong
379    */
380   public int getDataPosOfCpEntry (int i){
381     return cpPos[i];
382   }
383
384   //--- standard attributes
385
386   public Object getConstValueAttribute(int dataPos){
387     int cpIdx = u2(dataPos);
388     Object v = cpValue[cpIdx];
389     return v;
390   }
391
392   public String getSourceFileAttribute(int dataPos){
393     // SourceFile_attribute { u2 attr_name_idx; u4 attr_length; u2 sourcefile_idx<utf8>; }
394
395     int cpIdx = u2(dataPos + 6);
396     Object v = cpValue[cpIdx];
397     return (String)v;
398   }
399
400   
401   //--- low level readers
402
403   public final int u1(int dataIdx){
404     return data[dataIdx] & 0xff;
405   }
406
407   public final int u2(int dataIdx){
408     return ((data[dataIdx]&0xff) << 8) | (data[dataIdx+1]&0xff);
409   }
410
411   public final int i1(int dataIdx) {
412     return data[dataIdx++];
413   }
414
415   public final int i2(int dataIdx) {
416     int idx = dataIdx;
417     return (data[idx++] << 8) | (data[idx]&0xff);
418   }
419
420   public final int readU2(){
421     int idx = pos;
422     pos += 2;
423     return ((data[idx++]&0xff) << 8) | (data[idx]&0xff);
424   }
425
426   public final int readI2() {
427     int idx = pos;
428     pos += 2;
429     return (data[idx++] << 8) | (data[idx]&0xff);
430   }
431
432   public final int readI4(){
433     int idx = pos;
434     pos += 4;
435     byte[] data = this.data;
436
437     return (data[idx++] <<24) | ((data[idx++]&0xff) << 16) | ((data[idx++]&0xff) << 8) | (data[idx]&0xff);
438   }
439
440   
441   //--- reader notifications
442   private void setClass(ClassFileReader reader, String clsName, String superClsName, int flags, int cpCount) throws ClassParseException {
443     int p = pos;
444     reader.setClass( this, clsName, superClsName, flags, cpCount);
445     pos = p;
446   }
447
448   private void setInterfaceCount(ClassFileReader reader, int ifcCount){
449     int p = pos;
450     reader.setInterfaceCount( this, ifcCount);
451     pos = p;
452   }
453   private void setInterface(ClassFileReader reader, int ifcIndex, String ifcName){
454     int p = pos;
455     reader.setInterface( this, ifcIndex, ifcName);
456     pos = p;
457   }
458   private void setInterfacesDone(ClassFileReader reader){
459     int p = pos;
460     reader.setInterfacesDone( this);
461     pos = p;
462   }
463
464
465   private void setFieldCount(ClassFileReader reader, int fieldCount){
466     int p = pos;
467     reader.setFieldCount( this, fieldCount);
468     pos = p;
469
470   }
471   private void setField(ClassFileReader reader, int fieldIndex, int accessFlags, String name, String descriptor){
472     int p = pos;
473     reader.setField( this, fieldIndex, accessFlags, name, descriptor);
474     pos = p;
475   }
476   private void setFieldAttributeCount(ClassFileReader reader, int fieldIndex, int attrCount){
477     int p = pos;
478     reader.setFieldAttributeCount( this, fieldIndex, attrCount);
479     pos = p;
480   }
481   private void setFieldAttribute(ClassFileReader reader, int fieldIndex, int attrIndex, String name, int attrLength){
482     int p = pos + attrLength;
483     reader.setFieldAttribute( this, fieldIndex, attrIndex, name, attrLength);
484     pos = p;
485   }
486   private void setFieldAttributesDone(ClassFileReader reader, int fieldIndex){
487     int p = pos;
488     reader.setFieldAttributesDone( this, fieldIndex);
489     pos = p;
490   }
491   private void setFieldDone(ClassFileReader reader, int fieldIndex){
492     int p = pos;
493     reader.setFieldDone( this, fieldIndex);
494     pos = p;
495   }
496   private void setFieldsDone(ClassFileReader reader){
497     int p = pos;
498     reader.setFieldsDone( this);
499     pos = p;
500   }
501   private void setConstantValue(ClassFileReader reader, Object tag, Object value){
502     int p = pos;
503     reader.setConstantValue( this, tag, value);
504     pos = p;
505   }
506
507   private void setMethodCount(ClassFileReader reader, int methodCount){
508     int p = pos;
509     reader.setMethodCount( this, methodCount);
510     pos = p;
511   }
512   private void setMethod(ClassFileReader reader, int methodIndex, int accessFlags, String name, String descriptor){
513     int p = pos;
514     reader.setMethod( this, methodIndex, accessFlags, name, descriptor);
515     pos = p;
516   }
517   private void setMethodAttributeCount(ClassFileReader reader, int methodIndex, int attrCount){
518     int p = pos;
519     reader.setMethodAttributeCount( this, methodIndex, attrCount);
520     pos = p;
521   }
522   private void setMethodAttribute(ClassFileReader reader, int methodIndex, int attrIndex, String name, int attrLength){
523     int p = pos + attrLength;
524     reader.setMethodAttribute( this, methodIndex, attrIndex, name, attrLength);
525     pos = p;
526   }
527   private void setMethodAttributesDone(ClassFileReader reader, int methodIndex){
528     int p = pos;
529     reader.setMethodAttributesDone( this, methodIndex);
530     pos = p;
531   }
532   private void setMethodDone(ClassFileReader reader, int methodIndex){
533     int p = pos;
534     reader.setMethodDone( this, methodIndex);
535     pos = p;
536   }
537   private void setMethodsDone(ClassFileReader reader){
538     int p = pos;
539     reader.setMethodsDone( this);
540     pos = p;
541   }
542   private void setExceptionCount(ClassFileReader reader, Object tag, int exceptionCount){
543     int p = pos;
544     reader.setExceptionCount( this, tag, exceptionCount);
545     pos = p;
546   }
547   private void setExceptionsDone(ClassFileReader reader, Object tag){
548     int p = pos;
549     reader.setExceptionsDone( this, tag);
550     pos = p;
551   }
552   private void setException(ClassFileReader reader, Object tag, int exceptionIndex, String exceptionType){
553     int p = pos;
554     reader.setException( this, tag, exceptionIndex, exceptionType);
555     pos = p;
556   }
557   private void setCode(ClassFileReader reader, Object tag, int maxStack, int maxLocals, int codeLength){
558     int p = pos + codeLength;
559     reader.setCode( this, tag, maxStack, maxLocals, codeLength);
560     pos = p;
561   }
562   private void setExceptionTableCount(ClassFileReader reader, Object tag, int exceptionTableCount){
563     int p = pos;
564     reader.setExceptionHandlerTableCount( this, tag, exceptionTableCount);
565     pos = p;
566   }
567   private void setExceptionTableEntry(ClassFileReader reader, Object tag, int exceptionIndex,
568           int startPc, int endPc, int handlerPc, String catchType){
569     int p = pos;
570     reader.setExceptionHandler( this, tag, exceptionIndex, startPc, endPc, handlerPc, catchType);
571     pos = p;
572   }
573   private void setExceptionTableDone(ClassFileReader reader, Object tag){
574     int p = pos;
575     reader.setExceptionHandlerTableDone( this, tag);
576     pos = p;
577   }
578
579   private void setCodeAttributeCount(ClassFileReader reader, Object tag, int attrCount){
580     int p = pos;
581     reader.setCodeAttributeCount( this, tag, attrCount);
582     pos = p;
583   }
584   private void setCodeAttribute(ClassFileReader reader, Object tag, int attrIndex, String name, int attrLength){
585     int p = pos + attrLength;
586     reader.setCodeAttribute( this, tag, attrIndex, name, attrLength);
587     pos = p;
588   }
589   private void setCodeAttributesDone(ClassFileReader reader, Object tag){
590     int p = pos;
591     reader.setCodeAttributesDone( this, tag);
592     pos = p;
593   }
594           
595   private void setLineNumberTableCount(ClassFileReader reader, Object tag, int lineNumberCount){
596     int p = pos;
597     reader.setLineNumberTableCount( this, tag, lineNumberCount);
598     pos = p;
599   }
600   private void setLineNumber(ClassFileReader reader, Object tag, int lineIndex, int lineNumber, int startPc){
601     int p = pos;
602     reader.setLineNumber( this, tag, lineIndex, lineNumber, startPc);
603     pos = p;
604   }
605   private void setLineNumberTableDone(ClassFileReader reader, Object tag){
606     int p = pos;
607     reader.setLineNumberTableDone( this, tag);
608     pos = p;
609   }
610
611   private void setLocalVarTableCount(ClassFileReader reader, Object tag, int localVarCount){
612     int p = pos;
613     reader.setLocalVarTableCount( this, tag, localVarCount);
614     pos = p;
615   }
616   private void setLocalVar(ClassFileReader reader, Object tag, int localVarIndex, String varName, String descriptor,
617                       int scopeStartPc, int scopeEndPc, int slotIndex){
618     int p = pos;
619     reader.setLocalVar( this, tag, localVarIndex, varName, descriptor, scopeStartPc, scopeEndPc, slotIndex);
620     pos = p;
621   }
622   private void setLocalVarTableDone(ClassFileReader reader, Object tag){
623     int p = pos;
624     reader.setLocalVarTableDone( this, tag);
625     pos = p;
626   }
627
628
629   private void setClassAttributeCount(ClassFileReader reader, int attrCount){
630     int p = pos;
631     reader.setClassAttributeCount( this, attrCount);
632     pos = p;
633   }
634   private void setClassAttribute(ClassFileReader reader, int attrIndex, String name, int attrLength){
635     int p = pos + attrLength;
636     reader.setClassAttribute( this, attrIndex, name, attrLength);
637     pos = p;
638   }
639   private void setClassAttributesDone(ClassFileReader reader){
640     int p = pos;
641     reader.setClassAttributesDone(this);
642     pos = p;
643   }
644
645   private void setSourceFile(ClassFileReader reader, Object tag, String pathName){
646     int p = pos;
647     reader.setSourceFile( this, tag, pathName);
648     pos = p;
649   }
650   
651   private void setBootstrapMethodCount (ClassFileReader reader, Object tag, int bootstrapMethodCount){
652     int p = pos;
653     reader.setBootstrapMethodCount( this, tag, bootstrapMethodCount);
654     pos = p;    
655   }
656   private void setBootstrapMethod (ClassFileReader reader, Object tag, int idx, 
657                                    int refKind, String cls, String mth, String descriptor, int[] cpArgs){
658     int p = pos;
659     reader.setBootstrapMethod( this, tag, idx, refKind, cls, mth, descriptor, cpArgs);
660     pos = p;    
661   }
662   private void setBootstrapMethodsDone (ClassFileReader reader, Object tag){
663     int p = pos;
664     reader.setBootstrapMethodsDone( this, tag);
665     pos = p;    
666   }
667   
668   private void setInnerClassCount(ClassFileReader reader, Object tag, int innerClsCount){
669     int p = pos;
670     reader.setInnerClassCount( this, tag, innerClsCount);
671     pos = p;
672   }
673   private void setInnerClass(ClassFileReader reader, Object tag, int innerClsIndex, String outerName, String innerName,
674           String innerSimpleName, int accessFlags){
675     int p = pos;
676     reader.setInnerClass( this, tag, innerClsIndex, outerName, innerName, innerSimpleName, accessFlags);
677     pos = p;
678   }
679   private void setEnclosingMethod(ClassFileReader reader, Object tag, String enclosingClass, String enclosedMethod, String descriptor){
680     int p = pos;
681           reader.setEnclosingMethod( this, tag, enclosingClass, enclosedMethod, descriptor);
682           pos = p;
683   }
684   private void setInnerClassesDone(ClassFileReader reader, Object tag){
685     int p = pos;
686     reader.setInnerClassesDone(this, tag);
687     pos = p;
688   }
689
690   private void setAnnotationCount(ClassFileReader reader, Object tag, int annotationCount){
691     int p = pos;
692     reader.setAnnotationCount( this, tag, annotationCount);
693     pos = p;
694   }
695   private void setAnnotation(ClassFileReader reader, Object tag, int annotationIndex, String annotationType){
696     int p = pos;
697     reader.setAnnotation( this, tag, annotationIndex, annotationType);
698     pos = p;
699   }
700   private void setAnnotationsDone(ClassFileReader reader, Object tag){
701     int p = pos;
702     reader.setAnnotationsDone(this, tag);
703     pos = p;
704   }
705
706   private void setTypeAnnotationCount(ClassFileReader reader, Object tag, int annotationCount){
707     int p = pos;
708     reader.setTypeAnnotationCount( this, tag, annotationCount);
709     pos = p;
710   }
711   private void setTypeAnnotationsDone(ClassFileReader reader, Object tag){
712     int p = pos;
713     reader.setTypeAnnotationsDone(this, tag);
714     pos = p;
715   }
716
717   
718   private void setAnnotationValueCount(ClassFileReader reader, Object tag, int annotationIndex, int nValuePairs){
719     int p = pos;
720     reader.setAnnotationValueCount( this, tag, annotationIndex, nValuePairs);
721     pos = p;
722   }
723   private void setPrimitiveAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
724           String elementName, int arrayIndex, Object val){
725     int p = pos;
726     reader.setPrimitiveAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
727     pos = p;
728   }
729   private void setStringAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
730           String elementName, int arrayIndex, String s){
731     int p = pos;
732     reader.setStringAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, s);
733     pos = p;
734   }
735   private void setClassAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
736           String elementName, int arrayIndex, String typeName){
737     int p = pos;
738     reader.setClassAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, typeName);
739     pos = p;
740   }
741   private void setEnumAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
742           String elementName, int arrayIndex, String enumType, String enumValue){
743     int p = pos;
744     reader.setEnumAnnotationValue( this, tag, annotationIndex, valueIndex, elementName, arrayIndex, enumType, enumValue);
745     pos = p;
746   }
747
748   private void setAnnotationValueElementCount(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
749           String elementName, int elementCount){
750     int p = pos;
751     reader.setAnnotationValueElementCount(this, tag, annotationIndex, valueIndex, elementName, elementCount);
752     pos = p;
753   }
754   private void setAnnotationValueElementsDone(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex,
755           String elementName){
756     int p = pos;
757     reader.setAnnotationValueElementsDone(this, tag, annotationIndex, valueIndex, elementName);
758     pos = p;
759   }
760
761   public void setAnnotationValuesDone(ClassFileReader reader, Object tag, int annotationIndex){
762     int p = pos;
763     reader.setAnnotationValuesDone(this, tag, annotationIndex);
764     pos = p;
765   }
766
767   private void setParameterCount(ClassFileReader reader, Object tag, int parameterCount){
768     int p = pos;
769     reader.setParameterCount(this, tag, parameterCount);
770     pos = p;
771   }
772   private void setParameterAnnotationCount(ClassFileReader reader, Object tag, int paramIndex, int annotationCount){
773     int p = pos;
774     reader.setParameterAnnotationCount(this, tag, paramIndex, annotationCount);
775     pos = p;
776   }
777   private void setParameterAnnotation(ClassFileReader reader, Object tag, int annotationIndex, String annotationType){
778     int p = pos;
779     reader.setParameterAnnotation( this, tag, annotationIndex, annotationType);
780     pos = p;
781   }
782   private void setParameterAnnotationsDone(ClassFileReader reader, Object tag, int paramIndex){
783     int p = pos;
784     reader.setParameterAnnotationsDone(this, tag, paramIndex);
785     pos = p;
786   }
787   private void setParametersDone(ClassFileReader reader, Object tag){
788     int p = pos;
789     reader.setParametersDone(this, tag);
790     pos = p;
791   }
792
793   public void setSignature(ClassFileReader reader, Object tag, String signature){
794     int p = pos;
795     reader.setSignature(this, tag, signature);
796     pos = p;
797   }
798
799   //--- parsing
800
801   /**
802    * this is the main parsing routine that uses the ClassFileReader interface
803    * to tell clients about the classfile contents
804    *
805    * ClassFile structure: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#74353
806    *   u4 magic;  // 0xcafebabe
807    *   u2 minor_version;
808    *   u2 major_version;
809    *
810    *   u2 constant_pool_count;
811    *   cp_entry constant_pool[constant_pool_count-1];
812    *   u2 access_flags;
813    *
814    *   u2 this_class;
815    *   u2 super_class;
816    *
817    *   u2 interfaces_count;
818    *   u2 interfaces[interfaces_count];
819    *
820    *   u2 fields_count;
821    *   field_info fields[fields_count];
822    *
823    *   u2 methods_count;
824    *   method_info methods[methods_count];
825    *
826    *   u2 attributes_count;
827    *   attribute_info attributes[attributes_count];
828    */
829   public void parse( ClassFileReader reader)  throws ClassParseException {
830     int cpIdx;
831
832     try {
833       // yeah, cafebabe
834       int magic = readI4();
835       if (magic != 0xCAFEBABE) {
836         error("wrong magic: " + Integer.toHexString(magic));
837       }
838
839       // we don't do much with the version numbers yet
840       int minor = readU2();
841       int major = readU2();
842
843       // get the const pool
844       int cpCount = readU2();
845       cpPos = new int[cpCount];
846       cpValue = new Object[cpCount];
847       parseCp(cpCount);
848
849       // the class essentials
850       int accessFlags = readU2();
851
852       cpIdx = readU2();
853       String clsName = (String) cpValue[cpIdx];
854
855       cpIdx = readU2();
856       String superClsName = (String) cpValue[cpIdx];
857
858
859       setClass(reader, clsName, superClsName, accessFlags, cpCount);
860
861       // interfaces
862       int ifcCount = readU2();
863       parseInterfaces(reader, ifcCount);
864
865       // fields
866       int fieldCount = readU2();
867       parseFields(reader, fieldCount);
868
869       // methods
870       int methodCount = readU2();
871       parseMethods(reader, methodCount);
872
873       // class attributes
874       int classAttrCount = readU2();
875       parseClassAttributes(reader, classAttrCount);
876
877     } catch (BailOut x){
878       // nothing, just a control exception to shortcut the classfile parsing
879     }
880   }
881
882
883   //--- constpool parsing
884
885   public static String readModifiedUTF8String( byte[] data, int pos, int len) throws ClassParseException {
886     
887     int n = 0; // the number of chars in buf
888     char[] buf = new char[len]; // it can't be more, but it can be less chars
889     
890     // \u0001 - \u007f             : single byte chars:  0xxxxxxx
891     // \u0000 and \u0080 - \u07ff  : double byte chars:  110xxxxx, 10xxxxxx
892     // \u0800 - \uffff             : tripple byte chars: 1110xxxx, 10xxxxxx, 10xxxxxx
893     
894     int max = pos+len;
895     for (int i=pos; i<max; i++){
896       int c = data[i] & 0xff;
897       if ((c & 0x80) == 0){ // single byte char  0xxxxxxx
898         buf[n++] = (char)c;
899         
900       } else {
901         if ((c & 0x40) != 0){      // 11xxxxxx
902           
903           // for the sake of efficiency, we don't check for the trailing zero bit in the marker,
904           // we just mask it out
905           if ((c & 0x20) == 0) {   // 110xxxxx - double byte char
906             buf[n++] = (char) (((c & 0x1f) << 6) | (data[++i] & 0x3f));
907             
908           } else {                 // 1110xxxx - tripple byte char
909             buf[n++] = (char) (((c & 0x0f) << 12) | ((data[++i] & 0x3f) << 6) | (data[++i] & 0x3f));
910           }
911           
912         } else {
913           throw new ClassParseException("malformed modified UTF-8 input: ");
914         }
915       }
916     }
917     
918     return new String(buf, 0, n);
919   }
920
921   
922   // the protected methods are called automatically, the public parse..Attr() methods
923   // are called optionally from the corresponding ClassFileReader.set..Attribute() method.
924   // Note that these calls have to provide the ClassFileReader as an argument because
925   // we might actually switch to another reader (e.g. MethodInfos for parseCodeAttr)
926
927   protected void parseCp(int cpCount)  throws ClassParseException {
928     int j = pos;
929
930     byte[] data = this.data;
931     int[] dataIdx = this.cpPos;
932     Object[] values = this.cpValue;
933
934     //--- first pass: store data index values and convert non-delegating constant values
935     // cp_entry[0] is traditionally unused
936     for (int i=1; i<cpCount; i++) {
937       switch (data[j]){
938         case 0:
939           error("illegal constpool tag");
940
941         case CONSTANT_UTF8:  // utf8_info { u1 tag; u2 length; u1 bytes[length]; }
942           dataIdx[i] = j++;
943           int len = ((data[j++]&0xff) <<8) | (data[j++]&0xff);
944
945           String s = readModifiedUTF8String( data, j, len);
946           values[i] = s;
947
948           j += len;
949           break;
950
951         case 2:
952           error("illegal constpool tag");
953
954         case CONSTANT_INTEGER:  // Integer_info { u1 tag; u4 bytes; }
955           dataIdx[i] = j++;
956
957           int iVal = (data[j++]&0xff)<<24 | (data[j++]&0xff)<<16 | (data[j++]&0xff)<<8 | (data[j++]&0xff);
958           values[i] = new Integer(iVal);
959           break;
960
961         case CONSTANT_FLOAT:  // Float_info  { u1 tag; u4 bytes; }
962           dataIdx[i] = j++;
963
964           int iBits = (data[j++]&0xff)<<24 | (data[j++]&0xff)<<16 | (data[j++]&0xff)<<8 | (data[j++]&0xff);
965           float fVal = Float.intBitsToFloat(iBits);
966           values[i] = new Float(fVal);
967           break;
968
969         case CONSTANT_LONG:  // Long_info { u1 tag; u4 high_bytes; u4 low_bytes; }
970           dataIdx[i] = j++;
971           long lVal =  (data[j++]&0xffL)<<56 | (data[j++]&0xffL)<<48 | (data[j++]&0xffL)<<40 | (data[j++]&0xffL)<<32
972                     | (data[j++]&0xffL)<<24 | (data[j++]&0xffL)<<16 | (data[j++]&0xffL)<<8 | (data[j++]&0xffL);
973           values[i] = new Long(lVal);
974
975           dataIdx[++i] = -1;  // 8 byte cpValue occupy 2 index slots
976           break;
977
978         case CONSTANT_DOUBLE:  // Double_info  { u1 tag; u4 high_bytes; u4 low_bytes; }
979           dataIdx[i] = j++;
980
981           long lBits = (data[j++]&0xffL)<<56 | (data[j++]&0xffL)<<48 | (data[j++]&0xffL)<<40 | (data[j++]&0xffL)<<32
982                     | (data[j++]&0xffL)<<24 | (data[j++]&0xffL)<<16 | (data[j++]&0xffL)<<8 | (data[j++]&0xffL);
983           double dVal = Double.longBitsToDouble(lBits);
984           values[i] = new Double(dVal);
985
986           dataIdx[++i] = -1;  // 8 byte cpValue occupy 2 index slots
987           break;
988
989         case CONSTANT_CLASS:  // Class_info { u1 tag; u2 name_index<utf8>; }
990           dataIdx[i] = j;
991           values[i] = CpInfo.ConstantClass;
992
993           j += 3;
994           break;
995
996         case CONSTANT_STRING:  // String_info { u1 tag; u2 string_index<utf8>; }
997           dataIdx[i] = j;
998           values[i] = CpInfo.ConstantString;
999
1000           j += 3;
1001           break;
1002
1003         case FIELD_REF:  // Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
1004           dataIdx[i] = j;
1005           values[i] = CpInfo.FieldRef;
1006           j += 5;
1007           break;
1008
1009         case METHOD_REF: // Methodref_info  { u1 tag; u2 class_index; u2 name_and_type_index; }
1010           dataIdx[i] = j;
1011           values[i] = CpInfo.MethodRef;
1012           j += 5;
1013           break;
1014
1015         case INTERFACE_METHOD_REF: // InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
1016           dataIdx[i] = j;
1017           values[i] = CpInfo.InterfaceMethodRef;
1018           j += 5;
1019           break;
1020
1021         case NAME_AND_TYPE: // NameAndType_info { u1 tag; u2 name_index<utf8>; u2 descriptor_index<utf8>; }
1022           dataIdx[i] = j;
1023           values[i] = CpInfo.NameAndType;
1024
1025           j += 5;
1026           break;
1027
1028         //--- the Java 8 ones
1029           
1030         case METHOD_HANDLE: // MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index<mthref>; }
1031           dataIdx[i] = j;
1032           values[i] = CpInfo.MethodHandle;
1033           j += 4;
1034           break;
1035           
1036         case METHOD_TYPE:  // MethodType_info { u1 tag;  u2 descriptor_index<utf8>; }
1037           dataIdx[i] = j;
1038           values[i] = CpInfo.MethodType;
1039           j += 3;
1040           break;
1041
1042         case INVOKE_DYNAMIC: //  InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; }
1043           dataIdx[i] = j;
1044           values[i] = CpInfo.InvokeDynamic;
1045           j += 5;
1046           break;
1047           
1048         default:
1049           error("illegal constpool tag: " + data[j]);
1050       }
1051     }
1052
1053     pos = j;
1054
1055     //--- second pass: store values of delegating constant values
1056     for (int i=1; i<cpCount; i++){
1057       Object v = cpValue[i];
1058
1059       // we store string and class constants as their utf8 string values
1060       if (v == CpInfo.ConstantClass || v == CpInfo.ConstantString){
1061          cpValue[i] = cpValue[u2(cpPos[i]+1)];
1062       }
1063     }
1064   }
1065
1066   protected void parseInterfaces(ClassFileReader reader, int ifcCount){
1067
1068     setInterfaceCount(reader, ifcCount);
1069
1070     for (int i=0; i<ifcCount; i++){
1071       int cpIdx = readU2();
1072       setInterface(reader, i, classNameAt(cpIdx));
1073     }
1074
1075     setInterfacesDone(reader);
1076   }
1077
1078   //--- fields
1079   protected void parseFields(ClassFileReader reader, int fieldCount) {
1080
1081     setFieldCount(reader, fieldCount);
1082
1083     for (int i=0; i<fieldCount; i++){
1084       int accessFlags = readU2();
1085
1086       int cpIdx = readU2();
1087       String name = utf8At(cpIdx);
1088
1089       cpIdx = readU2();
1090       String descriptor = utf8At(cpIdx);
1091
1092       setField(reader, i, accessFlags, name, descriptor);
1093
1094       int attrCount = readU2();
1095       parseFieldAttributes(reader, i, attrCount);
1096
1097       setFieldDone(reader, i);
1098     }
1099
1100     setFieldsDone(reader);
1101   }
1102
1103   protected void parseFieldAttributes(ClassFileReader reader, int fieldIdx, int attrCount){
1104     setFieldAttributeCount(reader, fieldIdx, attrCount);
1105
1106     for (int i=0; i<attrCount; i++){
1107       int cpIdx = readU2();
1108       String name = utf8At(cpIdx);
1109
1110       name = internStdAttrName(cpIdx, name, stdFieldAttrs);
1111
1112       int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1113       setFieldAttribute(reader, fieldIdx, i, name, attrLength);
1114     }
1115
1116     setFieldAttributesDone(reader, fieldIdx);
1117   }
1118
1119   /**
1120    * optionally called by reader to obtain a ConstantValue field attribute
1121    * 
1122    *   ConstantValue {u2 attrName<utf8>; u4 attrLength; u2 constIndex<class|string|int|float|long|double> }
1123    * 
1124    * pos is at constIndex
1125    */
1126   public void parseConstValueAttr(ClassFileReader reader, Object tag){
1127     int cpIdx = readU2();
1128     setConstantValue(reader, tag, cpValue[cpIdx]);
1129   }
1130
1131
1132   //--- methods
1133   protected void parseMethods(ClassFileReader reader, int methodCount) {
1134
1135     setMethodCount(reader, methodCount);
1136
1137     for (int i=0; i<methodCount; i++){
1138       int accessFlags = readU2();
1139
1140       int cpIdx = readU2();
1141       String name = utf8At(cpIdx);
1142
1143       cpIdx = readU2();
1144       String descriptor = utf8At(cpIdx);
1145
1146       setMethod(reader, i, accessFlags, name, descriptor);
1147
1148       int attrCount = readU2();
1149       parseMethodAttributes(reader, i, attrCount);
1150
1151       setMethodDone(reader, i);
1152     }
1153
1154     setMethodsDone(reader);
1155   }
1156
1157   protected void parseMethodAttributes(ClassFileReader reader, int methodIdx, int attrCount){
1158     setMethodAttributeCount(reader, methodIdx, attrCount);
1159
1160     for (int i=0; i<attrCount; i++){
1161       int cpIdx = readU2();
1162       String name = utf8At(cpIdx);
1163
1164       name = internStdAttrName(cpIdx, name, stdMethodAttrs);
1165
1166       int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1167       setMethodAttribute(reader, methodIdx, i, name, attrLength);
1168     }
1169
1170     setMethodAttributesDone(reader, methodIdx);
1171   }
1172
1173   public void parseExceptionAttr (ClassFileReader reader, Object tag){
1174     int exceptionCount = readU2();
1175     setExceptionCount(reader, tag, exceptionCount);
1176
1177     for (int i=0; i<exceptionCount; i++){
1178       int cpIdx = readU2();
1179       String exceptionType = classNameAt(cpIdx);
1180       setException(reader, tag, i, exceptionType);
1181     }
1182
1183     setExceptionsDone(reader, tag);
1184   }
1185
1186   /**
1187    * (optionally) called by reader from within the setMethodAttribute() notification
1188    * This means we have recursive notification since this is a variable length
1189    * attribute that has variable length attributes
1190    *
1191    * Code_attribute { u2 attr_name_index<utf8>; u4 attr_length;
1192    *                  u2 max_stack; u2 max_locals;
1193    *                  u4 code_length; u1 code[code_length];
1194    *                  u2 exception_table_length;
1195    *                  { u2 start_pc; u2 end_pc; u2  handler_pc; u2  catch_type<class_entry>;
1196    *                  } exception_table[exception_table_length];
1197    *                  u2 attributes_count;
1198    *                  attribute_info attributes[attributes_count];  }
1199    *
1200    * pos is at max_stack
1201    */
1202   public void parseCodeAttr (ClassFileReader reader, Object tag){
1203     int maxStack = readU2();
1204     int maxLocals = readU2();
1205     int codeLength = readI4();  // no code length > 2GB supported
1206     int codeStartPos = pos;
1207
1208     setCode(reader, tag, maxStack, maxLocals, codeLength);
1209
1210     int exceptionCount = readU2();
1211     setExceptionTableCount(reader, tag, exceptionCount);
1212
1213     for (int i = 0; i < exceptionCount; i++) {
1214       int startPc = readU2();
1215       int endPc = readU2();
1216       int handlerPc = readU2();
1217
1218       int cpIdx = readU2();
1219       String catchType = (String) cpValue[cpIdx]; // a Constant_class
1220
1221       setExceptionTableEntry(reader, tag, i, startPc, endPc, handlerPc, catchType);
1222     }
1223     setExceptionTableDone(reader, tag);
1224
1225     int attrCount = readU2();
1226     parseCodeAttrAttributes(reader, tag, attrCount);
1227   }
1228
1229
1230   protected void parseCodeAttrAttributes(ClassFileReader reader, Object tag, int attrCount){
1231
1232     setCodeAttributeCount(reader, tag, attrCount);
1233
1234     for (int i=0; i<attrCount; i++){
1235       int cpIdx = readU2();
1236       String name = utf8At(cpIdx);
1237
1238       name = internStdAttrName(cpIdx, name, stdCodeAttrs);
1239
1240       int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1241       setCodeAttribute(reader, tag, i, name, attrLength);
1242     }
1243
1244     setCodeAttributesDone(reader, tag);
1245   }
1246
1247   /**
1248    * optionally called from ClassFileReader.setCodeAttribute() to parse LineNumberTables
1249    *   LineNumberTable { u2 attrName; u4 attrLength;
1250    *                     u2 lineCount;
1251    *                     { u2 startPc; u2 lineNumber; } [lineCount] };
1252    * pos is at lineCount
1253    */
1254   public void parseLineNumberTableAttr(ClassFileReader reader, Object tag){
1255     int lineCount = readU2();
1256     setLineNumberTableCount(reader, tag, lineCount);
1257     
1258     for (int i=0; i<lineCount; i++){
1259       int startPc = readU2();
1260       int lineNumber = readU2();
1261       setLineNumber(reader, tag, i, lineNumber, startPc);
1262     }
1263
1264     setLineNumberTableDone(reader, tag);
1265   }
1266
1267   
1268   /**
1269    * optionally called from ClassFileReader.setCodeAttribute() to parse LocalVarTables
1270    *   LocalVarTableTable { u2 attrName; u4 attrLength;
1271    *                        u2 localVarCount;
1272    *                        { u2 startPc; u2 lineNumber; } [lineCount] };
1273    * pos is at localVarCount
1274    */
1275   public void parseLocalVarTableAttr(ClassFileReader reader, Object tag){
1276     int localVarCount = readU2();
1277     setLocalVarTableCount(reader, tag, localVarCount);
1278     
1279     for (int i=0; i<localVarCount; i++){
1280       int startPc = readU2();
1281       int length = readU2();
1282       int cpIdx = readU2();
1283       String varName = (String) cpValue[cpIdx];
1284       cpIdx = readU2();
1285       String descriptor = (String)  cpValue[cpIdx];
1286       int slotIndex = readU2();
1287       
1288       setLocalVar(reader, tag, i, varName, descriptor, startPc, startPc+length-1, slotIndex );
1289     }
1290
1291     setLocalVarTableDone(reader, tag);
1292   }
1293
1294   //--- class
1295   protected void parseClassAttributes(ClassFileReader reader, int attrCount){
1296
1297     setClassAttributeCount(reader, attrCount);
1298
1299     for (int i=0; i<attrCount; i++){
1300       int cpIdx = readU2();
1301       String name = utf8At(cpIdx);
1302
1303       name = internStdAttrName(cpIdx, name, stdClassAttrs);
1304
1305       int attrLength = readI4(); // actually U4, but we don't support 2GB attributes
1306       setClassAttribute(reader, i, name, attrLength);
1307     }
1308
1309     setClassAttributesDone(reader);
1310   }
1311
1312
1313   /**
1314    * (optionally) called by ClassFileReader from within setClassAttribute() notification
1315    *
1316    * InnerClass { u2 nameIdx<utf8>; u4 length; u2 sourceFile<utf8>; }
1317    */
1318   public void parseSourceFileAttr(ClassFileReader reader, Object tag){
1319     int cpIdx = readU2();
1320     String pathName = utf8At(cpIdx);
1321     setSourceFile(reader, tag, pathName);
1322   }
1323
1324   /**
1325    * (optionally) called by ClassFileReader from within setClassAttribute() notification
1326    *
1327    * InnerClass { 
1328    *    u2 nameIdx<utf8>; 
1329    *    u4 length;
1330    *    u2 classCount;
1331    *    { u2 innerCls<cls>;
1332    *      u2 outerCls<cls>;
1333    *      u2 innerName<utf8>; 
1334    *      u2 innerAccessFlags;
1335    *    } classes[classCount] }
1336    * }
1337    * 
1338    * pos is at classCount
1339    */
1340   public void parseInnerClassesAttr(ClassFileReader reader, Object tag){
1341     int innerClsCount = readU2();    
1342     setInnerClassCount(reader, tag, innerClsCount);
1343
1344     for (int i = 0; i < innerClsCount; i++) {
1345       int cpIdx = readU2();
1346       String innerClsName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1347       cpIdx = readU2();
1348       String outerClsName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1349       cpIdx = readU2();
1350       String innerSimpleName = (cpIdx != 0) ? (String) cpValue[cpIdx] : null;
1351       int accessFlags = readU2();
1352
1353       setInnerClass(reader, tag, i, outerClsName, innerClsName, innerSimpleName, accessFlags);
1354     }
1355
1356     setInnerClassesDone(reader, tag);
1357   }
1358   
1359   /**
1360    * EnclosingMethod_attribute {
1361    *   u2 attribute_name_index;
1362    *   u4 attribute_length;
1363    *   u2 class_index     -> Class_info { u1 tag; u2 name_index->utf8 }
1364    *   u2 method_index    -> NameAndType_info { u1 tag; u2 name_index->utf8; u2 descriptor_index->utf8 }
1365    * }
1366    */
1367   public void parseEnclosingMethodAttr(ClassFileReader reader, Object tag){
1368     String enclosedMethod = null;
1369     String descriptor = null;
1370     
1371     int cpIdx = readU2(); // start of Class_info
1372     String enclosingClass =  nameAt(cpIdx);
1373     
1374     cpIdx = readU2(); // start of NameAndType_info
1375     
1376     // check if this is inside a method - we also get EnclosingMethod_infos for
1377     // classes that are not immediately enclosed
1378     if (cpIdx != 0){
1379       enclosedMethod = nameAt(cpIdx);    
1380       descriptor = descriptorAt(cpIdx);
1381     }
1382     
1383     setEnclosingMethod(reader, tag, enclosingClass, enclosedMethod, descriptor);
1384   }
1385   
1386   /**
1387    * BootstrapMethods_attribute {
1388    *     u2 attribute_name_index;
1389    *     u4 attribute_length;
1390    *     u2 num_bootstrap_methods;
1391    *     {   u2 bootstrap_method_ref; -> MethodHandle
1392    *         u2 num_bootstrap_arguments;
1393    *         u2 bootstrap_arguments[num_bootstrap_arguments];
1394    *     } bootstrap_methods[num_bootstrap_methods];
1395    * }
1396    * 
1397    * pos is at num_bootstrap_methods
1398   */
1399   public void parseBootstrapMethodAttr (ClassFileReader reader, Object tag){
1400     int nBootstrapMethods = readU2();
1401     
1402     setBootstrapMethodCount(reader, tag, nBootstrapMethods);
1403     
1404     for (int i=0; i<nBootstrapMethods; i++){
1405       int cpMhIdx = readU2();
1406       int nArgs = readU2();
1407       int[] bmArgs = new int[nArgs];
1408       for (int j=0; j<nArgs; j++){
1409         bmArgs[j] = readU2();
1410       }
1411       
1412       // kind of this method handle
1413       int refKind = mhRefTypeAt(cpMhIdx);
1414       
1415       // CONSTANT_Methodref_info structure
1416       int mrefIdx = mhMethodRefIndexAt(cpMhIdx);
1417       
1418       String clsName = methodClassNameAt(mrefIdx);
1419       String mthName = methodNameAt(mrefIdx);
1420       String descriptor = methodDescriptorAt(mrefIdx);
1421       
1422       setBootstrapMethod(reader, tag, i, refKind, clsName, mthName, descriptor, bmArgs);
1423     }
1424     
1425     setBootstrapMethodsDone( reader, tag);
1426   }
1427   
1428   String nameAt(int nameTypeInfoIdx) {
1429     return utf8At(u2(cpPos[nameTypeInfoIdx] + 1));
1430   }
1431   
1432   String descriptorAt (int nameTypeInfoIdx){
1433     return utf8At( u2( cpPos[nameTypeInfoIdx]+3));
1434   }
1435
1436 // those are as per http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf
1437
1438   /*
1439    *   element_value {
1440    *     u1 tag;
1441    *     union {
1442    *       u2 const_value_index;
1443    *       { u2 type_name_index; u2 const_name_index; } enum_const_value;
1444    *       u2 class_info_index;
1445    *       annotation annotation_value;
1446    *       { u2 num_values; element_value values[num_values]; } array_value;
1447    *     } value;
1448    *   }
1449    *   valid tags are primitve type codes B,C,D,F,I,J,S,Z
1450    *   plus:   's'=String, 'e'=enum, 'c'=class, '@'=annotation, '['=array
1451    */
1452   void parseAnnotationValue(ClassFileReader reader, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex){
1453     int cpIdx;
1454     Object val;
1455
1456     int t = readUByte();
1457     switch (t){
1458       case 'Z':
1459         // booleans have to be treated differently since there is no CONSTANT_Boolean, i.e. values are
1460         // stored as CONSTANT_Integer in the constpool, i.e. the cpValue doesn't have the right type
1461         cpIdx = readU2();
1462         val = cpValue[cpIdx];
1463         val = Boolean.valueOf((Integer)val == 1);
1464         setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1465         break;        
1466
1467       case 'B':
1468         cpIdx = readU2();
1469         val = cpValue[cpIdx];
1470         val = Byte.valueOf(((Integer)val).byteValue());
1471         setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1472         break;
1473         
1474       case 'C':
1475         cpIdx = readU2();
1476         val = cpValue[cpIdx];
1477         val = Character.valueOf((char)((Integer)val).shortValue());
1478         setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1479         break;
1480         
1481       case 'S':
1482         cpIdx = readU2();
1483         val = cpValue[cpIdx];
1484         val = Short.valueOf(((Integer)val).shortValue());
1485         setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1486         break;
1487
1488       case 'I':
1489       case 'F':
1490       case 'D':
1491       case 'J':
1492         cpIdx = readU2();
1493         val = cpValue[cpIdx];
1494         setPrimitiveAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, val);
1495         break;
1496
1497       case 's':
1498         cpIdx = readU2();
1499         String s = (String) cpValue[cpIdx];
1500         setStringAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, s);
1501         break;
1502
1503       case 'e':
1504         cpIdx = readU2();
1505         String enumTypeName = (String)cpValue[cpIdx];
1506         cpIdx = readU2();
1507         String enumConstName = (String)cpValue[cpIdx];
1508         setEnumAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, enumTypeName, enumConstName);
1509         break;
1510
1511       case 'c':
1512         cpIdx = readU2();
1513         String className = (String)cpValue[cpIdx];
1514         setClassAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, arrayIndex, className);
1515         break;
1516
1517       case '@':
1518         parseAnnotation(reader, tag, 0, false);  // getting recursive here
1519         break;
1520
1521       case '[':
1522         int arrayLen = readU2();
1523         setAnnotationValueElementCount(reader, tag, annotationIndex, valueIndex, elementName, arrayLen);
1524         for (int i=0; i<arrayLen; i++){
1525           parseAnnotationValue(reader, tag, annotationIndex, valueIndex, elementName, i);
1526         }
1527         setAnnotationValueElementsDone(reader, tag, annotationIndex, valueIndex, elementName);
1528         break;
1529     }
1530   }
1531
1532   /*
1533    *   annotation {
1534    *     u2 type_index;
1535    *     u2 num_element_value_pairs;
1536    *     {
1537    *       u2 element_name_index;
1538    *       element_value value;
1539    *     } element_value_pairs[num_element_value_pairs]
1540    *   }
1541    */
1542   void parseAnnotation (ClassFileReader reader, Object tag, int annotationIndex, boolean isParameterAnnotation){
1543     int cpIdx = readU2();
1544     String annotationType = (String)cpValue[cpIdx];
1545
1546     if (isParameterAnnotation){
1547       setParameterAnnotation(reader, tag, annotationIndex, annotationType);
1548     } else {
1549       setAnnotation(reader, tag, annotationIndex, annotationType);
1550     }
1551
1552     parseAnnotationValues(reader, tag, annotationIndex);
1553   }
1554
1555   void parseAnnotationValues (ClassFileReader reader, Object tag, int annotationIndex){
1556     int nValuePairs = readU2();
1557     setAnnotationValueCount(reader, tag, annotationIndex, nValuePairs);
1558
1559     for (int i=0; i<nValuePairs; i++){
1560       int cpIdx = readU2();
1561       String elementName = (String)cpValue[cpIdx];
1562       parseAnnotationValue(reader, tag, annotationIndex, i, elementName, -1);
1563     }
1564
1565     setAnnotationValuesDone(reader, tag, annotationIndex);
1566   }
1567   
1568   /*
1569    * class, field, method annotation attributes (only one per target)
1570    *
1571    *  Runtime[In]VisibleAnnotations_attribute {
1572    *     u2 attribute_name_index;
1573    *     u4 attribute_length;
1574    *     u2 num_annotations;        << pos
1575    *     annotation annotations[num_annotations];
1576    *   }
1577    */
1578   public void parseAnnotationsAttr (ClassFileReader reader, Object tag){
1579     int numAnnotations = readU2();
1580     setAnnotationCount(reader, tag, numAnnotations);
1581
1582     for (int i=0; i<numAnnotations; i++){
1583       parseAnnotation(reader, tag, i, false);
1584     }
1585
1586     setAnnotationsDone(reader, tag);
1587   }
1588
1589   
1590   // JSR 308 type annotation target types
1591   public static final int CLASS_TYPE_PARAMETER                 = 0x00;
1592   public static final int METHOD_TYPE_PARAMETER                = 0x01;
1593   public static final int CLASS_EXTENDS                        = 0x10;
1594   public static final int CLASS_TYPE_PARAMETER_BOUND           = 0x11;
1595   public static final int METHOD_TYPE_PARAMETER_BOUND          = 0x12;
1596   public static final int FIELD                                = 0x13;
1597   public static final int METHOD_RETURN                        = 0x14;
1598   public static final int METHOD_RECEIVER                      = 0x15;
1599   public static final int METHOD_FORMAL_PARAMETER              = 0x16;
1600   public static final int THROWS                               = 0x17;
1601   public static final int LOCAL_VARIABLE                       = 0x40;
1602   public static final int RESOURCE_VARIABLE                    = 0x41;
1603   public static final int EXCEPTION_PARAMETER                  = 0x42;
1604   public static final int INSTANCEOF                           = 0x43;
1605   public static final int NEW                                  = 0x44;
1606   public static final int CONSTRUCTOR_REFERENCE                = 0x45;
1607   public static final int METHOD_REFERENCE                     = 0x46;
1608   public static final int CAST                                 = 0x47;
1609   public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
1610   public static final int METHOD_INVOCATION_TYPE_ARGUMENT      = 0x49;
1611   public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT  = 0x4a;
1612   public static final int METHOD_REFERENCE_TYPE_ARGUMENT       = 0x4b;  
1613   
1614   public static String getTargetTypeName (int targetType){
1615     switch (targetType){
1616       case CLASS_TYPE_PARAMETER: return "class type parameter";
1617       case METHOD_TYPE_PARAMETER: return "method type parameter";
1618       case CLASS_EXTENDS: return "super class";
1619       case CLASS_TYPE_PARAMETER_BOUND: return "class type parameter bound";
1620       case METHOD_TYPE_PARAMETER_BOUND: return "method type parameter bound";
1621       case FIELD: return "field";
1622       case METHOD_RETURN: return "method return";
1623       case METHOD_RECEIVER: return "method receiver";
1624       case METHOD_FORMAL_PARAMETER: return "method formal parameter";
1625       case THROWS: return "throws";
1626       case LOCAL_VARIABLE: return "local variable";
1627       case RESOURCE_VARIABLE: return "resource variable";
1628       case EXCEPTION_PARAMETER: return "exception parameter";
1629       case INSTANCEOF: return "instanceof";
1630       case NEW: return "new";
1631       case CONSTRUCTOR_REFERENCE: return "ctor reference";
1632       case METHOD_REFERENCE: return "method reference";
1633       case CAST: return "case";
1634       case METHOD_INVOCATION_TYPE_ARGUMENT: return "method invocation type argument";
1635       case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: return "ctor reference type argument";
1636       case METHOD_REFERENCE_TYPE_ARGUMENT: return "method reference type argument";
1637       default:
1638         return "<unknown target type 0x" + Integer.toHexString(targetType);
1639     }
1640   }
1641   
1642   public static String getTypePathEncoding (short[] typePath){
1643     if (typePath == null){
1644       return "()";
1645     }
1646     
1647     StringBuffer sb = new StringBuffer();
1648     for (int i=0; i<typePath.length;i++){
1649       int e = typePath[i];
1650       sb.append('(');
1651       sb.append( Integer.toString((e>>8) & 0xff));
1652       sb.append( Integer.toString(e & 0xff));
1653       sb.append(')');
1654     }
1655     
1656     return sb.toString();
1657   }
1658   
1659   public static String getScopeEncoding (long[] scopeEntries){
1660     StringBuffer sb = new StringBuffer();
1661     for (int i=0; i<scopeEntries.length;i++){
1662       long e = scopeEntries[i];
1663       int slotIndex = (int)(e & 0xffff);
1664       int length = (int)((e >> 16) & 0xffff);
1665       int startPc = (int)((e >> 32) & 0xffff);
1666       
1667       if (i>0){
1668         sb.append(',');
1669       }
1670       
1671       sb.append('[');
1672       sb.append( Integer.toString(startPc));
1673       sb.append("..");
1674       sb.append( Integer.toString(startPc + length-1));
1675       sb.append("]#");
1676       sb.append(slotIndex);
1677     }
1678     
1679     return sb.toString();
1680   }
1681   
1682   // JSR 308 type annotation, which adds 3 fields to the old annotation structure
1683   //
1684   //  type_annotation {
1685   //      u1 target_type;        // targeted program element (sec 3.2)
1686   //      union {                // ?? this is probably packed - variable size unions make no sense
1687   //          type_parameter_target;
1688   //          supertype_target;
1689   //          type_parameter_bound_target;
1690   //          empty_target;
1691   //          method_formal_parameter_target;
1692   //          throws_target;
1693   //          localvar_target;
1694   //          catch_target;
1695   //          offset_target;
1696   //          type_argument_target;
1697   //      } target_info;         // targeted program element (sec 3.3)
1698   //
1699   //      type_path target_path; // encoding of annotation position in compound type (array, generic, etc., sec 3.4)
1700   //
1701   //                             // standard annotation fields
1702   //      u2 type_index;         // the annotation type
1703   //      u2 num_element_value_pairs;
1704   //      {
1705   //          u2 element_name_index;
1706   //          element_value value;
1707   //      } element_value_pairs[num_element_value_pairs];
1708   //  }
1709   //
1710   //  struct type_path {
1711   //    u1              path_length;
1712   //    type_path_entry path[path_length];
1713   //  }
1714   //
1715   //  struct type_path_entry {
1716   //    u1 type_path_kind;
1717   //        // 0: deeper in array type
1718   //        // 1: deeper in nested type
1719   //        // 2: bound of wildcard typearg
1720   //        // 3: type argument of parameterized type
1721   //    u1 type_argument_index;
1722   //        // 0, if type_path_kind == 0,1,2
1723   //        // 0-based index of type arg in parameterized type if type_path_kind i== 3
1724   //  }
1725   
1726   int getTargetInfoSize (int targetType){
1727     int len = 3; // max static length are xx_TYPE_ARGUMENTs
1728     if (targetType == LOCAL_VARIABLE || targetType == RESOURCE_VARIABLE){
1729       len = Math.max( len, u2(pos) * 6); // three u2 values per entry
1730     }
1731     
1732     return len;
1733   }
1734
1735   int getTypePathSize (short[] typePath){
1736     int typePathSize = 1;
1737     if (typePath != null) {
1738       typePathSize += typePath.length * 2;
1739     }
1740     return typePathSize;
1741   }
1742   
1743   
1744   short[] readTypePath (){
1745     short[] typePath = null;
1746     
1747     int pathLength = readUByte();
1748     if (pathLength > 0){
1749       typePath = new short[pathLength];
1750       for (int i=0; i<pathLength; i++){
1751         int pathKind = (short)readUByte();
1752         int argIdx = (short)readUByte();
1753         typePath[i]= (short)((pathKind << 8) | argIdx);
1754       }
1755     }
1756     
1757     return typePath;
1758   }
1759
1760   String readAnnotationType (){
1761     int cpIdx = readU2();
1762     String annotationType = (String)cpValue[cpIdx];
1763     return annotationType;
1764   }
1765
1766   void setTypeAnnotation (ClassFileReader reader, Object tag, int annotationIndex) {
1767     int targetType = readUByte();
1768     
1769     switch (targetType){
1770       case CLASS_TYPE_PARAMETER:
1771       case METHOD_TYPE_PARAMETER: {
1772         // type_parameter_target { u1 type_parameter_index; }
1773         int typeParamIdx = readUByte();
1774         reader.setTypeParameterAnnotation( this, tag, annotationIndex, targetType, typeParamIdx, readTypePath(), readAnnotationType());
1775         break;
1776       } 
1777       case CLASS_EXTENDS: {
1778         // supertype_target { u2 supertype_index; }
1779         int superTypeIdx = readU2();
1780         reader.setSuperTypeAnnotation( this, tag, annotationIndex, targetType, superTypeIdx, readTypePath(), readAnnotationType());
1781         break;
1782       }
1783       case CLASS_TYPE_PARAMETER_BOUND:
1784       case METHOD_TYPE_PARAMETER_BOUND: {
1785         // type_parameter_bound_target { u1 type_parameter_index; u1 bound_index; }
1786         int typeParamIdx = readUByte();
1787         int boundIdx = readUByte();
1788         reader.setTypeParameterBoundAnnotation(this, tag, annotationIndex, targetType, typeParamIdx, boundIdx, readTypePath(), readAnnotationType());
1789         break;
1790       }
1791       case METHOD_RETURN:
1792       case METHOD_RECEIVER:
1793       case FIELD:
1794         // empty_target {}
1795         reader.setTypeAnnotation( this, tag, annotationIndex, targetType, readTypePath(), readAnnotationType());
1796         break;
1797         
1798       case METHOD_FORMAL_PARAMETER: {
1799         // method_formal_parameter_target { u1 method_formal_parameter_index; }
1800         int formalParamIdx = readUByte();
1801         reader.setFormalParameterAnnotation( this, tag, annotationIndex, targetType, formalParamIdx, readTypePath(), readAnnotationType());
1802         break;
1803       }
1804       case THROWS: {
1805         // throws_target { u2 throws_type_index; }
1806         int throwsTypeIdx = readU2();
1807         reader.setThrowsAnnotation( this, tag, annotationIndex, targetType, throwsTypeIdx, readTypePath(), readAnnotationType());        
1808         break;
1809       } 
1810       case LOCAL_VARIABLE:
1811       case RESOURCE_VARIABLE: {
1812         // this can't just refer to a LocalVarInfo since those depend on debug compile options
1813         //
1814         //  localvar_target {
1815         //      u2 table_length;  // number of entries, not bytes
1816         //      {
1817         //          u2 start_pc;
1818         //          u2 length; // bytecode offset length
1819         //          u2 index;  // local var idx
1820         //      } table[table_length];
1821         //  }
1822         int tableLength = readU2();
1823         long[] scopeEntries = new long[tableLength];
1824         for (int i=0; i<tableLength; i++){
1825           int startPc = readU2();
1826           int length = readU2();
1827           int slotIdx = readU2();
1828           scopeEntries[i] = ((long)startPc << 32) | ((long)length << 16) | slotIdx;
1829         }
1830         reader.setVariableAnnotation( this, tag, annotationIndex, targetType, scopeEntries, readTypePath(), readAnnotationType());
1831         break;
1832       }
1833       case EXCEPTION_PARAMETER: {
1834         // catch_target { u2 exception_table_index; }
1835         int exceptionIdx = readU2();
1836         reader.setExceptionParameterAnnotation( this, tag, annotationIndex, targetType, exceptionIdx, readTypePath(), readAnnotationType());        
1837         break;
1838       }
1839       case INSTANCEOF:
1840       case METHOD_REFERENCE:
1841       case CONSTRUCTOR_REFERENCE:
1842       case NEW: {
1843         // offset_target { u2 offset; }   // insn offset within bytecode
1844         int offset = readU2();
1845         reader.setBytecodeAnnotation(this, tag, annotationIndex, targetType, offset, readTypePath(), readAnnotationType());
1846         break;
1847       }
1848       case CAST:
1849       case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
1850       case METHOD_INVOCATION_TYPE_ARGUMENT:
1851       case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
1852       case METHOD_REFERENCE_TYPE_ARGUMENT: {
1853         //  type_argument_target {
1854         //      u2 offset;
1855         //      u1 type_argument_index;
1856         //  }
1857         int offset = readU2();
1858         int typeArgIdx = readUByte();
1859         reader.setBytecodeTypeParameterAnnotation(this, tag, annotationIndex, targetType, offset, typeArgIdx, readTypePath(), readAnnotationType());
1860         break;
1861       }
1862       
1863       default:
1864         // <2do - report this to the reader
1865         throw new RuntimeException("unknown type annotation target: 0x" + Integer.toHexString(targetType));
1866     }
1867   }
1868
1869   
1870   void parseTypeAnnotation (ClassFileReader reader, Object tag, int annotationIndex) {
1871    
1872     // this does the respective setXTypeAnnotation() reader callback
1873     //dumpData(pos, 16);
1874     setTypeAnnotation(reader, tag, annotationIndex);
1875     
1876     // now set the annotation value pairs
1877     parseAnnotationValues( reader, tag, annotationIndex);
1878   }
1879   
1880   /*
1881    * Runtime[In]VisibleTypeAnnotations_attribute {
1882    *    u2 attribute_name_index;
1883    *    u4 attribute_length;
1884    *    u2 num_annotations;
1885    *    type_annotation annotations[num_annotations];
1886    * }
1887    */
1888   public void parseTypeAnnotationsAttr (ClassFileReader reader, Object tag) {
1889     int numAnnotations = readU2();
1890     setTypeAnnotationCount(reader, tag, numAnnotations);
1891
1892     for (int i=0; i<numAnnotations; i++){
1893       parseTypeAnnotation(reader, tag, i);
1894     }
1895
1896     setTypeAnnotationsDone(reader, tag);
1897   }
1898   
1899   /*
1900    *   RuntimeInvisibleParameterAnnotations_attribute {
1901    *     u2 attribute_name_index;
1902    *     u4 attribute_length;
1903    *     u1 num_parameters; << pos
1904    *     {
1905    *       u2 num_annotations;
1906    *       annotation annotations[num_annotations];
1907    *     } parameter_annotations[num_parameters];
1908    *   }
1909    */
1910    public void parseParameterAnnotationsAttr(ClassFileReader reader, Object tag){
1911      int numParameters = readUByte();
1912      setParameterCount(reader, tag, numParameters);
1913      for (int i=0; i<numParameters; i++){
1914        int numAnnotations = readU2();
1915
1916        setParameterAnnotationCount(reader, tag, i, numAnnotations);
1917        for (int j=0; j<numAnnotations; j++){
1918          parseAnnotation(reader, tag, j, true);
1919        }
1920        setParameterAnnotationsDone(reader, tag, i);
1921      }
1922      setParametersDone(reader, tag);
1923    }
1924
1925   /**
1926    *  Signature_attribute {
1927    *    u2 attribute_name_index;
1928    *    u4 attr-length;
1929    *    u2 signature-index << pos
1930    *  }
1931    */
1932    public void parseSignatureAttr(ClassFileReader reader, Object tag){
1933      int cpIdx = readU2();
1934      setSignature(reader, tag, utf8At(cpIdx));
1935    }
1936
1937
1938   /**
1939    *    AnnotationDefault_attribute {
1940    *      u2 attribute_name_index;
1941    *      u4 attribute_length;
1942    *      element_value default_value; << pos
1943    *    }
1944    */
1945    public void parseAnnotationDefaultAttr(ClassFileReader reader, Object tag){
1946      parseAnnotationValue(reader, tag, -1, -1, null, -1);
1947    }
1948
1949
1950 //   EnclosingMethod_attribute {
1951 //     u2 attribute_name_index;
1952 //     u4 attribute_length;
1953 //     u2 class_index
1954 //     u2 method_index;
1955 //   }
1956
1957 //   LocalVariableTypeTable_attribute {  // Code attr
1958 //     u2 attribute_name_index;
1959 //     u4 attribute_length;
1960 //     u2 local_variable_type_table_length;
1961 //     {
1962 //       u2 start_pc;
1963 //       u2 length;
1964 //       u2 name_index;
1965 //       u2 signature_index;
1966 //       u2 index;
1967 //     } local_variable_type_table[local_variable_type_table_length];
1968 //   }
1969
1970
1971
1972
1973   public void parseBytecode(JVMByteCodeReader reader, Object tag, int codeLength){
1974     int localVarIndex;
1975     int cpIdx;
1976     int constVal;
1977     int offset;
1978     int defaultOffset;
1979
1980     boolean isWide = false; // modifier for Xload,Xstore,ret and iinc
1981
1982     int startPos = pos;
1983     int endPos = pos+codeLength;
1984     int nextPos;
1985
1986
1987     while (pos < endPos){
1988       pc = pos - startPos;
1989
1990       int opcode = readUByte();
1991       switch (opcode){
1992         case 0: // nop
1993           reader.nop();
1994           break;
1995         case 1:  // aconst_null
1996           reader.aconst_null();
1997           break;
1998         case 2: // iconst_m1
1999           reader.iconst_m1();
2000           break;
2001         case 3: // iconst_0
2002           reader.iconst_0();
2003           break;
2004         case 4: // iconst_1
2005           reader.iconst_1();
2006           break;
2007         case 5: // iconst_2
2008           reader.iconst_2();
2009           break;
2010         case 6: // iconst_3
2011           reader.iconst_3();
2012           break;
2013         case 7: // iconst_4
2014           reader.iconst_4();
2015           break;
2016         case 8: // iconst_5
2017           reader.iconst_5();
2018           break;
2019         case 9: // lconst_0
2020           reader.lconst_0();
2021           break;
2022         case 10: // lconst_1
2023           reader.lconst_1();
2024           break;
2025         case 11: // fconst_0
2026           reader.fconst_0();
2027           break;
2028         case 12: // fconst_1
2029           reader.fconst_1();
2030           break;
2031         case 13: // fconst_2
2032           reader.fconst_2();
2033           break;
2034         case 14: // dconst_0
2035           reader.dconst_0();
2036           break;
2037         case 15: // dconst_1
2038           reader.dconst_1();
2039           break;
2040         case 16: // bipush
2041           constVal = readByte();
2042           reader.bipush(constVal);
2043           break;
2044         case 17: // sipush
2045           constVal = readI2();
2046           reader.sipush(constVal);
2047           break;
2048         case 18: // ldc
2049           cpIdx = readUByte();
2050           reader.ldc_(cpIdx);
2051           break;
2052         case 19: // ldc_w
2053           cpIdx = readU2();
2054           reader.ldc_w_(cpIdx);
2055           break;
2056         case 20: // ldc2_w
2057           cpIdx = readU2();
2058           reader.ldc2_w(cpIdx);
2059           break;
2060         case 21: // iload
2061           localVarIndex = isWide ? readU2() : readUByte();
2062           reader.iload(localVarIndex);
2063           break;
2064         case 22: // lload
2065           localVarIndex = isWide ? readU2() : readUByte();
2066           reader.lload(localVarIndex);
2067           break;
2068         case 23: // fload
2069           localVarIndex = isWide ? readU2() : readUByte();
2070           reader.fload(localVarIndex);
2071           break;
2072         case 24: // dload
2073           localVarIndex = isWide ? readU2() : readUByte();
2074           reader.dload(localVarIndex);
2075           break;
2076         case 25: // aload
2077           localVarIndex = isWide ? readU2() : readUByte();
2078           reader.aload(localVarIndex);
2079           break;
2080         case 26: // iload_0
2081           reader.iload_0();
2082           break;
2083         case 27: // iload_1
2084           reader.iload_1();
2085           break;
2086         case 28: // iload_2
2087           reader.iload_2();
2088           break;
2089         case 29: // iload_3
2090           reader.iload_3();
2091           break;
2092         case 30: // lload_0
2093           reader.lload_0();
2094           break;
2095         case 31: // lload_1
2096           reader.lload_1();
2097           break;
2098         case 32: // lload_2
2099           reader.lload_2();
2100           break;
2101         case 33: // lload_3
2102           reader.lload_3();
2103           break;
2104         case 34: // fload_0
2105           reader.fload_0();
2106           break;
2107         case 35: // fload_1
2108           reader.fload_1();
2109           break;
2110         case 36: // fload_2
2111           reader.fload_2();
2112           break;
2113         case 37: // fload_3
2114           reader.fload_3();
2115           break;
2116         case 38: // dload_0
2117           reader.dload_0();
2118           break;
2119         case 39: // dload_1
2120           reader.dload_1();
2121           break;
2122         case 40: // dload_2
2123           reader.dload_2();
2124           break;
2125         case 41: // dload_3
2126           reader.dload_3();
2127           break;
2128         case 42: // aload_0
2129           reader.aload_0();
2130           break;
2131         case 43: // aload_1
2132           reader.aload_1();
2133           break;
2134         case 44: // aload_2
2135           reader.aload_2();
2136           break;
2137         case 45: // aload_3
2138           reader.aload_3();
2139           break;
2140         case 46: // iaload
2141           reader.iaload();
2142           break;
2143         case 47: // laload
2144           reader.laload();
2145           break;
2146         case 48: // faload
2147           reader.faload();
2148           break;
2149         case 49: // daload
2150           reader.daload();
2151           break;
2152         case 50: // aaload
2153           reader.aaload();
2154           break;
2155         case 51: // baload
2156           reader.baload();
2157           break;
2158         case 52: // caload
2159           reader.caload();
2160           break;
2161         case 53: // saload
2162           reader.saload();
2163           break;
2164         case 54: // istore
2165           localVarIndex = isWide ? readU2() : readUByte();
2166           reader.istore(localVarIndex);
2167           break;
2168         case 55: // lstore
2169           localVarIndex = isWide ? readU2() : readUByte();
2170           reader.lstore(localVarIndex);
2171           break;
2172         case 56: // fstore
2173           localVarIndex = isWide ? readU2() : readUByte();
2174           reader.fstore(localVarIndex);
2175           break;
2176         case 57: // dstore
2177           localVarIndex = isWide ? readU2() : readUByte();
2178           reader.dstore(localVarIndex);
2179           break;
2180         case 58: // astore
2181           localVarIndex = isWide ? readU2() : readUByte();
2182           reader.astore(localVarIndex);
2183           break;
2184         case 59: // istore_0
2185           reader.istore_0();
2186           break;
2187         case 60: // istore_1
2188           reader.istore_1();
2189           break;
2190         case 61: // istore_2
2191           reader.istore_2();
2192           break;
2193         case 62: // istore_3
2194           reader.istore_3();
2195           break;
2196         case 63: // lstore_0
2197           reader.lstore_0();
2198           break;
2199         case 64: // lstore_1
2200           reader.lstore_1();
2201           break;
2202         case 65: // lstore_2
2203           reader.lstore_2();
2204           break;
2205         case 66: // lstore_3
2206           reader.lstore_3();
2207           break;
2208         case 67: // fstore_0
2209           reader.fstore_0();
2210           break;
2211         case 68: // fstore_1
2212           reader.fstore_1();
2213           break;
2214         case 69: // fstore_2
2215           reader.fstore_2();
2216           break;
2217         case 70: // fstore_3
2218           reader.fstore_3();
2219           break;
2220         case 71: //dstore_0
2221           reader.dstore_0();
2222           break;
2223         case 72: //dstore_1
2224           reader.dstore_1();
2225           break;
2226         case 73: //dstore_2
2227           reader.dstore_2();
2228           break;
2229         case 74: //dstore_3
2230           reader.dstore_3();
2231           break;
2232         case 75: // astore_0
2233           reader.astore_0();
2234           break;
2235         case 76: // astore_1
2236           reader.astore_1();
2237           break;
2238         case 77: // astore_2
2239           reader.astore_2();
2240           break;
2241         case 78: // astore_3
2242           reader.astore_3();
2243           break;
2244         case 79: // iastore
2245           reader.iastore();
2246           break;
2247         case 80: // lastore
2248           reader.lastore();
2249           break;
2250         case 81: // fastore
2251           reader.fastore();
2252           break;
2253         case 82: // dastore
2254           reader.dastore();
2255           break;
2256         case 83: // aastore
2257           reader.aastore();
2258           break;
2259         case 84: // bastore
2260           reader.bastore();
2261           break;
2262         case 85: // castore
2263           reader.castore();
2264           break;
2265         case 86: // sastore
2266           reader.sastore();
2267           break;
2268         case 87: // pop
2269           reader.pop();
2270           break;
2271         case 88: // pop2
2272           reader.pop2();
2273           break;
2274         case 89: // dup
2275           reader.dup();
2276           break;
2277         case 90: // dup_x1
2278           reader.dup_x1();
2279           break;
2280         case 91: // dup_x2
2281           reader.dup_x2();
2282           break;
2283         case 92: // dup2
2284           reader.dup2();
2285           break;
2286         case 93: // dup2_x1
2287           reader.dup2_x1();
2288           break;
2289         case 94: // dup2_x2
2290           reader.dup2_x2();
2291           break;
2292         case 95: // swap
2293           reader.swap();
2294           break;
2295         case 96: // iadd
2296           reader.iadd();
2297           break;
2298         case 97: // ladd
2299           reader.ladd();
2300           break;
2301         case 98: // fadd
2302           reader.fadd();
2303           break;
2304         case 99: // dadd
2305           reader.dadd();
2306           break;
2307         case 100: // isub
2308           reader.isub();
2309           break;
2310         case 101: // lsub
2311           reader.lsub();
2312           break;
2313         case 102: // fsub
2314           reader.fsub();
2315           break;
2316         case 103: // dsub
2317           reader.dsub();
2318           break;
2319         case 104: // imul
2320           reader.imul();
2321           break;
2322         case 105: // lmul
2323           reader.lmul();
2324           break;
2325         case 106: // fmul
2326           reader.fmul();
2327           break;
2328         case 107: // dmul
2329           reader.dmul();
2330           break;
2331         case 108: // idiv
2332           reader.idiv();
2333           break;
2334         case 109: // ldiv
2335           reader.ldiv();
2336           break;
2337         case 110: // fdiv
2338           reader.fdiv();
2339           break;
2340         case 111: //ddiv
2341           reader.ddiv();
2342           break;
2343         case 112: // irem
2344           reader.irem();
2345           break;
2346         case 113: // lrem
2347           reader.lrem();
2348           break;
2349         case 114: // frem
2350           reader.frem();
2351           break;
2352         case 115: // drem
2353           reader.drem();
2354           break;
2355         case 116: // ineg
2356           reader.ineg();
2357           break;
2358         case 117: // lneg
2359           reader.lneg();
2360           break;
2361         case 118: // fneg
2362           reader.fneg();
2363           break;
2364         case 119: // dneg
2365           reader.dneg();
2366           break;
2367         case 120: // ishl
2368           reader.ishl();
2369           break;
2370         case 121: // lshl
2371           reader.lshl();
2372           break;
2373         case 122: // ishr
2374           reader.ishr();
2375           break;
2376         case 123: // lshr
2377           reader.lshr();
2378           break;
2379         case 124: // iushr
2380           reader.iushr();
2381           break;
2382         case 125: // lushr
2383           reader.lushr();
2384           break;
2385         case 126: // iand
2386           reader.iand();
2387           break;
2388         case 127: // land
2389           reader.land();
2390           break;
2391         case 128: // ior
2392           reader.ior();
2393           break;
2394         case 129: // lor
2395           reader.lor();
2396           break;
2397         case 130: // ixor
2398           reader.ixor();
2399           break;
2400         case 131: // lxor
2401           reader.lxor();
2402           break;
2403         case 132: // iinc
2404           if (isWide){
2405             localVarIndex = readU2();
2406             constVal = readI2();
2407           } else {
2408             localVarIndex = readUByte();
2409             constVal = readByte();
2410           }
2411           reader.iinc(localVarIndex, constVal);
2412           break;
2413         case 133: // i2l
2414           reader.i2l();
2415           break;
2416         case 134: // i2f
2417           reader.i2f();
2418           break;
2419         case 135: // i2d
2420           reader.i2d();
2421           break;
2422         case 136: // l2i
2423           reader.l2i();
2424           break;
2425         case 137: // l2f
2426           reader.l2f();
2427           break;
2428         case 138: // l2d
2429           reader.l2d();
2430           break;
2431         case 139: // f2i
2432           reader.f2i();
2433           break;
2434         case 140: // f2l
2435           reader.f2l();
2436           break;
2437         case 141: // f2d
2438           reader.f2d();
2439           break;
2440         case 142: // d2i
2441           reader.d2i();
2442           break;
2443         case 143: // d2l
2444           reader.d2l();
2445           break;
2446         case 144: // d2f
2447           reader.d2f();
2448           break;
2449         case 145: // i2b
2450           reader.i2b();
2451           break;
2452         case 146: // i2c
2453           reader.i2c();
2454           break;
2455         case 147: // i2s
2456           reader.i2s();
2457           break;
2458         case 148: // lcmp
2459           reader.lcmp();
2460           break;
2461         case 149: // fcmpl
2462           reader.fcmpl();
2463           break;
2464         case 150: // fcmpg
2465           reader.fcmpg();
2466           break;
2467         case 151: // dcmpl
2468           reader.dcmpl();
2469           break;
2470         case 152: // dcmpg
2471           reader.dcmpg();
2472           break;
2473         case 153: // ifeq
2474           offset = readI2();
2475           reader.ifeq(offset);
2476           break;
2477         case 154: // ifne
2478           offset = readI2();
2479           reader.ifne(offset);
2480           break;
2481         case 155: // iflt
2482           offset = readI2();
2483           reader.iflt(offset);
2484           break;
2485         case 156: // ifge
2486           offset = readI2();
2487           reader.ifge(offset);
2488           break;
2489         case 157: // ifgt
2490           offset = readI2();
2491           reader.ifgt(offset);
2492           break;
2493         case 158: // ifle
2494           offset = readI2();
2495           reader.ifle(offset);
2496           break;
2497         case 159: // if_icmpeq
2498           offset = readI2();
2499           reader.if_icmpeq(offset);
2500           break;
2501         case 160: // if_icmpne
2502           offset = readI2();
2503           reader.if_icmpne(offset);
2504           break;
2505         case 161: // if_icmplt
2506           offset = readI2();
2507           reader.if_icmplt(offset);
2508           break;
2509         case 162: // if_icmpge
2510           offset = readI2();
2511           reader.if_icmpge(offset);
2512           break;
2513         case 163: // if_icmpgt
2514           offset = readI2();
2515           reader.if_icmpgt(offset);
2516           break;
2517         case 164: // if_icmple
2518           offset = readI2();
2519           reader.if_icmple(offset);
2520           break;
2521         case 165: // if_acmpeq
2522           offset = readI2();
2523           reader.if_acmpeq(offset);
2524           break;
2525         case 166: // if_acmpne
2526           offset = readI2();
2527           reader.if_acmpne(offset);
2528           break;
2529         case 167: // goto
2530           offset = readI2();
2531           reader.goto_(offset);
2532           break;
2533         case 168: // jsr
2534           offset = readI2();
2535           reader.jsr(offset);
2536           break;
2537         case 169: // ret
2538           localVarIndex = isWide ? readU2() : readUByte();
2539           reader.ret(localVarIndex);
2540           break;
2541         case 170: // tableswitch
2542           pos = (((pc+4)>>2)<<2)+startPos; // skip over padding
2543
2544           defaultOffset = readI4();
2545           int low = readI4();
2546           int high = readI4();
2547
2548           int len = high-low+1;
2549           nextPos = pos + len*4;
2550           reader.tableswitch(defaultOffset, low, high);
2551           pos = nextPos;
2552           break;
2553         case 171: // lookupswitch
2554           pos = (((pc+4)>>2)<<2)+startPos; // skip over padding
2555
2556           defaultOffset = readI4();
2557           int nPairs = readI4();
2558
2559           nextPos = pos + (nPairs*8);
2560           reader.lookupswitch(defaultOffset, nPairs);
2561           pos = nextPos;
2562           break;
2563         case 172: // ireturn
2564           reader.ireturn();
2565           break;
2566         case 173: // lreturn
2567           reader.lreturn();
2568           break;
2569         case 174: // freturn
2570           reader.freturn();
2571           break;
2572         case 175: // dreturn
2573           reader.dreturn();
2574           break;
2575         case 176: // areturn
2576           reader.areturn();
2577           break;
2578         case 177: // return
2579           reader.return_();
2580           break;
2581         case 178: // getstatic
2582           cpIdx = readU2(); // CP index of fieldRef
2583           reader.getstatic(cpIdx);
2584           break;
2585         case 179: // putstatic
2586           cpIdx = readU2(); // CP index of fieldRef
2587           reader.putstatic(cpIdx);
2588           break;
2589         case 180: // getfield
2590           cpIdx = readU2(); // CP index of fieldRef
2591           reader.getfield(cpIdx);
2592           break;
2593         case 181: // putfield
2594           cpIdx = readU2(); // CP index of fieldRef
2595           reader.putfield(cpIdx);
2596           break;
2597         case 182: // invokevirtual
2598           cpIdx = readU2(); // CP index of methodRef
2599           reader.invokevirtual(cpIdx);
2600           break;
2601         case 183: // invokespecial
2602           cpIdx = readU2(); // CP index of methodRef
2603           reader.invokespecial(cpIdx);
2604           break;
2605         case 184: // invokestatic
2606           cpIdx = readU2(); // CP index of methodRef
2607           reader.invokestatic(cpIdx);
2608           break;
2609         case 185: // invokeinterface
2610           cpIdx = readU2(); // CP index of methodRef
2611           int count = readUByte();
2612           int zero = readUByte(); // must be 0
2613           reader.invokeinterface(cpIdx, count, zero);
2614           break;
2615         case 186: // invokedynamic
2616           cpIdx = readU2(); // CP index of bootstrap method
2617           readUByte();  // 0
2618           readUByte(); //  0
2619           reader.invokedynamic(cpIdx);
2620           break;
2621         case 187: // new
2622           cpIdx = readU2();
2623           reader.new_(cpIdx);
2624           break;
2625         case 188: // newarray
2626           int aType = readUByte();
2627           reader.newarray(aType);
2628           break;
2629         case 189: // anewarray
2630           cpIdx = readU2(); // CP index of component type
2631           reader.anewarray(cpIdx);
2632           break;
2633         case 190: // arraylength
2634           reader.arraylength();
2635           break;
2636         case 191: // athrow
2637           reader.athrow();
2638           break;
2639         case 192: // checkcast
2640           cpIdx = readU2(); // cast type cp index
2641           reader.checkcast(cpIdx);
2642           break;
2643         case 193: // instanceof
2644           cpIdx = readU2(); // check type cp index
2645           reader.instanceof_(cpIdx);
2646           break;
2647         case 194: // monitorenter
2648           reader.monitorenter();
2649           break;
2650         case 195: // monitorexit
2651           reader.monitorexit();
2652           break;
2653         case 196: // wide
2654           isWide = true;
2655           // affects immediate operand width if next bytecode is:
2656           //  iload,fload,aload,lload,dload,
2657           //  istore,fstore,astore,lstore,dstore
2658           //  ret
2659           reader.wide();
2660           continue;
2661         case 197: // multianewarray
2662           cpIdx = readU2();
2663           int dimensions = readUByte();
2664           reader.multianewarray(cpIdx, dimensions);
2665           break;
2666         case 198: // ifnull
2667           offset = readI2();
2668           reader.ifnull(offset);
2669           break;
2670         case 199: // ifnonnull
2671           offset = readI2();
2672           reader.ifnonnull(offset);
2673           break;
2674         case 200: // goto_w
2675           offset = readI4();
2676           reader.goto_w(offset);
2677           break;
2678         case 201: // jsr_w
2679           offset = readI4();
2680           reader.jsr_w(offset);
2681           break;
2682           
2683           
2684         default:
2685           reader.unknown(opcode);
2686       }
2687
2688       isWide = false; // reset wide modifier
2689     }
2690
2691   }
2692
2693   //--- those can only be called from within a JVMByteCodeReader.tableswitch() notification
2694   public void parseTableSwitchEntries(JVMByteCodeReader reader, int low, int high){
2695     for (int val=low; val<=high; val++){
2696       int offset = readI4();
2697       reader.tableswitchEntry(val, offset);
2698     }
2699   }
2700   public int getTableSwitchOffset(int low, int high, int defaultOffset, int val){
2701     if (val < low || val > high){
2702       return defaultOffset;
2703     }
2704
2705     int n = Math.abs(val - low);
2706     pos += n*4;
2707     int pcOffset = readI4();
2708
2709     return pcOffset;
2710   }
2711
2712   //--- those can only be called from within a JVMByteCodeReader.lookupswitch() notification
2713   public void parseLookupSwitchEntries(JVMByteCodeReader reader, int nEntries){
2714     for (int i=0; i<nEntries; i++){
2715       int value = readI4();
2716       int offset = readI4();
2717       reader.lookupswitchEntry(i, value, offset);
2718     }
2719   }
2720   public int getLookupSwitchOffset(int nEntries, int defaultOffset, int val){
2721     for (int i=0; i<nEntries; i++){
2722       int match = readI4();
2723       if (val > match){
2724         pos +=4;
2725       } else if (val == match) {
2726         int offset = readI4();
2727         return offset;
2728       } else {
2729         break;
2730       }
2731     }
2732     return defaultOffset;
2733   }
2734
2735 }