title: java.lang.VerifyError: Bad local variable type after bytecode instrumentation
body: <p>I instrumented some Java bytecode. What I try to do is this:</p>
  
  <pre><code>InstrumentStackElem[] stack;
  int stackpointer;
  void foo(){
      stackpointer = (stackpointer + 1) % stack.length;
      InstrumentStackElem localref = stack[stackpointer];
      localref.init();
  
      //before each return
      localref.clear();
      stackpointer = (stackpointer -1 +stack.length) % stack.length;
  </code></pre>
  
  <p>So at the beginning of each method I increment the stackpointer and grab a local reference to the array element. Before each return, I call a clear method on the element and decrease the counter again.</p>
  
  <p>When I try to access the field for the call of localref.clear() I always get a java.lang.VerifyError.</p>
  
  <p>Example method:</p>
  
  <pre><code>public static boolean isValidName(final String s) {
          if (!s.matches("[_a-zA-Z][_a-zA-Z0-9]*")) {
              return false;
          }
  
          if (s.toCharArray()[0] == '_') { // this check should not be -&gt; this is
                                              // a bug
              return false;
          }
  
          return true;
      }
  </code></pre>
  
  <p>Corresponding instrumented bytecode</p>
  
  <pre><code> public static boolean isValidName(java.lang.String);
      Code:
         0: getstatic     #38                 // Field instrumentation_static_stackpointer:I
         3: iconst_1
         4: iadd
         5: bipush        16
         7: irem
         8: putstatic     #38                 // Field instrumentation_static_stackpointer:I
        11: getstatic     #40                 // Field instrumentation_static_stack:[Lme/instrumentor/InstrumentStackElem;
        14: getstatic     #38                 // Field instrumentation_static_stackpointer:I
        17: aaload
        18: astore_2
        19: aload_2
        20: bipush        -1
        22: ldc           #113                // String isValidName_Ljava_lang_String__Z
        24: invokevirtual #48                 // Method me/instrumentor/InstrumentStackElem.init:(ILjava/lang/String;)V
        27: aload_0
        28: ldc           #115                // String [_a-zA-Z][_a-zA-Z0-9]*
        30: invokevirtual #118                // Method java/lang/String.matches:(Ljava/lang/String;)Z
        33: ifne          56
        36: iconst_0
        37: aload_2
        38: invokevirtual #110                // Method me/instrumentor/InstrumentStackElem.clear:()V
        41: getstatic     #38                 // Field instrumentation_static_stackpointer:I
        44: iconst_1
        45: isub
        46: bipush        16
        48: iadd
        49: bipush        16
        51: irem
        52: putstatic     #38                 // Field instrumentation_static_stackpointer:I
        55: ireturn
        56: aload_0
        57: invokevirtual #122                // Method java/lang/String.toCharArray:()[C
        60: iconst_0
        61: caload
        62: bipush        95
        64: if_icmpne     87
        67: iconst_0
        68: aload_2
        69: invokevirtual #110                // Method me/instrumentor/InstrumentStackElem.clear:()V
        72: getstatic     #38                 // Field instrumentation_static_stackpointer:I
        75: iconst_1
        76: isub
        77: bipush        16
        79: iadd
        80: bipush        16
        82: irem
        83: putstatic     #38                 // Field instrumentation_static_stackpointer:I
        86: ireturn
        87: iconst_1
        88: aload_2
        89: invokevirtual #110                // Method me/instrumentor/InstrumentStackElem.clear:()V
        92: getstatic     #38                 // Field instrumentation_static_stackpointer:I
        95: iconst_1
        96: isub
        97: bipush        16
        99: iadd
       100: bipush        16
       102: irem
       103: putstatic     #38                 // Field instrumentation_static_stackpointer:I
       106: ireturn
  </code></pre>
  
  <p>This is the exact error thrown:</p>
  
  <pre><code>  Unexpected error: Lexer: java.lang.VerifyError: Bad local variable type
  Exception Details:
    Location:
      lexer/Lexer.isValidName(Ljava/lang/String;)Z @68: aload_2
    Reason:
      Type top (current frame, locals[2]) is not assignable to reference type
    Current Frame:
      bci: @68
      flags: { }
      locals: { 'java/lang/String' }
      stack: { integer }
    Bytecode:
      0000000: b200 2604 6010 1070 b300 26b2 0028 b200
      0000010: 2632 4d2c 10ff 1271 b600 302a 1273 b600
      0000020: 769a 0017 032c b600 6eb2 0026 0464 1010
      0000030: 6010 1070 b300 26ac 2ab6 007a 0334 105f
      0000040: a000 1703 2cb6 006e b200 2604 6410 1060
      0000050: 1010 70b3 0026 ac04 2cb6 006e b200 2604
      0000060: 6410 1060 1010 70b3 0026 ac            
    Stackmap Table:
      same_frame(@56)
      same_frame(@87)
  </code></pre>
  
  <p>I use the asm library to instrument the methods and used <code>this.method.visitLocalVariable("localstackref", "[Lme/instrumentor/InstrumentStackElem;",null, bl, el,this.stackelementindex);</code> to add the local variable. <code>stackelementindex</code> in this case was 2.</p>
  
  <p>Anybody can help me?</p>