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