src/main/java/org/plumelib/bcelutil/StackMapUtils.java
protected final void fix_local_variable_table(MethodGen mgen) {
    InstructionList il = mgen.getInstructionList();
    if (il == null) {
      // no code so nothing to do
      first_local_index = 0;
      return;
    }

    // Get the current local variables (includes 'this' and parameters)
    LocalVariableGen[] locals = mgen.getLocalVariables();
    LocalVariableGen l;
    LocalVariableGen new_lvg;

    // We need a deep copy
    for (int ii = 0; ii < locals.length; ii++) {
      locals[ii] = (LocalVariableGen) (locals[ii].clone());
    }

    // The arg types are correct and include all parameters.
    Type[] arg_types = mgen.getArgumentTypes();

    // Initial offset into the stack frame
    int offset = 0;

    // Index into locals of the first parameter
    int loc_index = 0;

    // Rarely, the java compiler gets the max locals count wrong (too big).
    // This would cause problems for us later, so we need to recalculate
    // the highest local used based on looking at code offsets.
    mgen.setMaxLocals();
    int max_locals = mgen.getMaxLocals();
    // Remove the existing locals
    mgen.removeLocalVariables();
    // Reset MaxLocals to 0 and let code below rebuild it.
    mgen.setMaxLocals(0);

    // Determine the first 'true' local index into the local variables.
    // The object 'this' pointer and the parameters form the first n
    // entries in the list.
    first_local_index = arg_types.length;

    if (!mgen.isStatic()) {
      // Add the 'this' pointer back in.
      l = locals[0];
      new_lvg = mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), null, null);
      debug_instrument.log(
          "Added <this> %s%n",
          new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
      loc_index = 1;
      offset = 1;
      first_local_index++;
    }

    // Loop through each parameter
    for (int ii = 0; ii < arg_types.length; ii++) {

      // If this parameter doesn't have a matching local
      if ((loc_index >= locals.length) || (offset != locals[loc_index].getIndex())) {

        // Create a local variable to describe the missing parameter
        new_lvg = mgen.addLocalVariable("$hidden$" + offset, arg_types[ii], offset, null, null);
      } else {
        l = locals[loc_index];
        new_lvg = mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), null, null);
        loc_index++;
      }
      debug_instrument.log(
          "Added param  %s%n",
          new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
      offset += arg_types[ii].getSize();
    }

    // At this point the LocalVaraibles contain:
    //   the 'this' pointer (if present)
    //   the parameters to the method
    // This will be used to construct the initial state of the
    // StackMapTypes.
    LocalVariableGen[] initial_locals = mgen.getLocalVariables();
    initial_locals_count = initial_locals.length;
    initial_type_list = new StackMapType[initial_locals_count];
    for (int ii = 0; ii < initial_locals_count; ii++) {
      initial_type_list[ii] = generate_StackMapType_from_Type(initial_locals[ii].getType());
    }

    // Add back the true locals
    //
    // NOTE that the Java compiler uses unnamed local temps for:
    //   saving the exception in a finally clause
    //   the lock for a synchronized block
    //   iterators
    //   (others?)
    // We will create a 'fake' local for these cases.

    for (int ii = first_local_index; ii < locals.length; ii++) {
      l = locals[ii];
      if (l.getIndex() > offset) {
        // A gap in index values indicates a compiler allocated temp.
        // (if offset is 0, probably a lock object)
        // there is at least one hidden compiler temp before the next local
        offset = gen_temp_locals(mgen, offset);
        ii--; // need to revisit same local
      } else {
        new_lvg =
            mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), l.getStart(), l.getEnd());
        debug_instrument.log(
            "Added local  %s%n",
            new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
        offset = new_lvg.getIndex() + (new_lvg.getType()).getSize();
      }
    }

    // check for hidden temps after last declared local.
    while (offset < max_locals) {
      offset = gen_temp_locals(mgen, offset);
    }

    // Recalculate the highest local used based on looking at code offsets.
    mgen.setMaxLocals();
  }
protected final void fix_local_variable_table(MethodGen mgen) {
    InstructionList il = mgen.getInstructionList();
    if (il == null) {
      // no code so nothing to do
      first_local_index = 0;
      return;
    }

    // Get the current local variables (includes 'this' and parameters)
    LocalVariableGen[] locals = mgen.getLocalVariables();
    LocalVariableGen l;
    LocalVariableGen new_lvg;

    // We need a deep copy
    for (int ii = 0; ii < locals.length; ii++) {
      locals[ii] = (LocalVariableGen) (locals[ii].clone());
    }

    // The arg types are correct and include all parameters.
    Type[] arg_types = mgen.getArgumentTypes();

    // Initial offset into the stack frame
    int offset = 0;

    // Index into locals of the first parameter
    int loc_index = 0;

    // Rarely, the java compiler gets the max locals count wrong (too big).
    // This would cause problems for us later, so we need to recalculate
    // the highest local used based on looking at code offsets.
    mgen.setMaxLocals();
    int max_locals = mgen.getMaxLocals();
    // Remove the existing locals
    mgen.removeLocalVariables();
    // Reset MaxLocals to 0 and let code below rebuild it.
    mgen.setMaxLocals(0);

    // Determine the first 'true' local index into the local variables.
    // The object 'this' pointer and the parameters form the first n
    // entries in the list.
    first_local_index = arg_types.length;

    if (!mgen.isStatic()) {
      // Add the 'this' pointer back in.
      l = locals[0];
      new_lvg = mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), null, null);
      debug_instrument.log(
          "Added <this> %s%n",
          new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
      loc_index = 1;
      offset = 1;
      first_local_index++;
    }

    // Loop through each parameter
    for (int ii = 0; ii < arg_types.length; ii++) {

      // If this parameter doesn't have a matching local
      if ((loc_index >= locals.length) || (offset != locals[loc_index].getIndex())) {

        // Create a local variable to describe the missing parameter
        new_lvg = mgen.addLocalVariable("$hidden$" + offset, arg_types[ii], offset, null, null);
      } else {
        l = locals[loc_index];
        new_lvg = mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), null, null);
        loc_index++;
      }
      debug_instrument.log(
          "Added param  %s%n",
          new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
      offset += arg_types[ii].getSize();
    }

    // At this point the LocalVaraibles contain:
    //   the 'this' pointer (if present)
    //   the parameters to the method
    // This will be used to construct the initial state of the
    // StackMapTypes.
    LocalVariableGen[] initial_locals = mgen.getLocalVariables();
    initial_locals_count = initial_locals.length;
    initial_type_list = new StackMapType[initial_locals_count];
    for (int ii = 0; ii < initial_locals_count; ii++) {
      initial_type_list[ii] = generate_StackMapType_from_Type(initial_locals[ii].getType());
    }

    // Add back the true locals
    //
    // NOTE that the Java compiler uses unnamed local temps for:
    //   saving the exception in a finally clause
    //   the lock for a synchronized block
    //   iterators
    //   (others?)
    // We will create a 'fake' local for these cases.

    for (int ii = first_local_index; ii < locals.length; ii++) {
      l = locals[ii];
      if (l.getIndex() > offset) {
        // A gap in index values indicates a compiler allocated temp.
        // (if offset is 0, probably a lock object)
        // there is at least one hidden compiler temp before the next local
        offset = gen_temp_locals(mgen, offset);
        ii--; // need to revisit same local
      } else {
        new_lvg =
            mgen.addLocalVariable(l.getName(), l.getType(), l.getIndex(), l.getStart(), l.getEnd());
        debug_instrument.log(
            "Added local  %s%n",
            new_lvg.getIndex() + ": " + new_lvg.getName() + ", " + new_lvg.getType());
        offset = new_lvg.getIndex() + (new_lvg.getType()).getSize();
      }
    }

    // check for hidden temps after last declared local.
    while (offset < max_locals) {
      offset = gen_temp_locals(mgen, offset);
    }

    // Recalculate the highest local used based on looking at code offsets.
    mgen.setMaxLocals();
  }
protected final void fix_local_variable_table ( MethodGen mgen ) { InstructionList il = mgen . getInstructionList ( ) ; if ( il == null ) { // no code so nothing to do first_local_index = 0 ; return ; } // Get the current local variables (includes 'this' and parameters) LocalVariableGen [ ] locals = mgen . getLocalVariables ( ) ; LocalVariableGen l ; LocalVariableGen new_lvg ; // We need a deep copy for ( int ii = 0 ; ii < locals . length ; ii ++ ) { locals [ ii ] = ( LocalVariableGen ) ( locals [ ii ] . clone ( ) ) ; } // The arg types are correct and include all parameters. Type [ ] arg_types = mgen . getArgumentTypes ( ) ; // Initial offset into the stack frame int offset = 0 ; // Index into locals of the first parameter int loc_index = 0 ; // Rarely, the java compiler gets the max locals count wrong (too big). // This would cause problems for us later, so we need to recalculate // the highest local used based on looking at code offsets. mgen . setMaxLocals ( ) ; int max_locals = mgen . getMaxLocals ( ) ; // Remove the existing locals mgen . removeLocalVariables ( ) ; // Reset MaxLocals to 0 and let code below rebuild it. mgen . setMaxLocals ( 0 ) ; // Determine the first 'true' local index into the local variables. // The object 'this' pointer and the parameters form the first n // entries in the list. first_local_index = arg_types . length ; if ( ! mgen . isStatic ( ) ) { // Add the 'this' pointer back in. l = locals [ 0 ] ; new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , null , null ) ; debug_instrument . log ( "Added <this> %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; loc_index = 1 ; offset = 1 ; first_local_index ++ ; } // Loop through each parameter for ( int ii = 0 ; ii < arg_types . length ; ii ++ ) { // If this parameter doesn't have a matching local if ( ( loc_index >= locals . length ) || ( offset != locals [ loc_index ] . getIndex ( ) ) ) { // Create a local variable to describe the missing parameter new_lvg = mgen . addLocalVariable ( "$hidden$" + offset , arg_types [ ii ] , offset , null , null ) ; } else { l = locals [ loc_index ] ; new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , null , null ) ; loc_index ++ ; } debug_instrument . log ( "Added param  %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; offset += arg_types [ ii ] . getSize ( ) ; } // At this point the LocalVaraibles contain: //   the 'this' pointer (if present) //   the parameters to the method // This will be used to construct the initial state of the // StackMapTypes. LocalVariableGen [ ] initial_locals = mgen . getLocalVariables ( ) ; initial_locals_count = initial_locals . length ; initial_type_list = new StackMapType [ initial_locals_count ] ; for ( int ii = 0 ; ii < initial_locals_count ; ii ++ ) { initial_type_list [ ii ] = generate_StackMapType_from_Type ( initial_locals [ ii ] . getType ( ) ) ; } // Add back the true locals // // NOTE that the Java compiler uses unnamed local temps for: //   saving the exception in a finally clause //   the lock for a synchronized block //   iterators //   (others?) // We will create a 'fake' local for these cases. for ( int ii = first_local_index ; ii < locals . length ; ii ++ ) { l = locals [ ii ] ; if ( l . getIndex ( ) > offset ) { // A gap in index values indicates a compiler allocated temp. // (if offset is 0, probably a lock object) // there is at least one hidden compiler temp before the next local offset = gen_temp_locals ( mgen , offset ) ; ii -- ; // need to revisit same local } else { new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , l . getStart ( ) , l . getEnd ( ) ) ; debug_instrument . log ( "Added local  %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; offset = new_lvg . getIndex ( ) + ( new_lvg . getType ( ) ) . getSize ( ) ; } } // check for hidden temps after last declared local. while ( offset < max_locals ) { offset = gen_temp_locals ( mgen , offset ) ; } // Recalculate the highest local used based on looking at code offsets. mgen . setMaxLocals ( ) ; }
Under some circumstances, there may be problems with the local variable table. These problems
occur when the Java compiler adds unnamed entries. There may be unnamed parameters and/or
unnamed local variables. These items appear as gaps in the LocalVariable table. This routine
creates LocalVariable entries for these missing items.

<ol>
<li>The java Compiler allocates a hidden parameter for the constructor of an inner class.
These items are given the name $hidden$ appended with their offset.
<li>The Java compiler allocates unnamed local temps for:
<ul>
<li>saving the exception in a finally clause
<li>the lock for a synchronized block
<li>interators
<li>(others?)
</ul>
These items are given the name DaIkOnTeMp appended with their offset.
</ol>

@param mgen MethodGen to be modified
Under some circumstances there may be problems with the local variable table . These problems occur when the Java compiler adds unnamed entries . There may be unnamed parameters and / or unnamed local variables . These items appear as gaps in the LocalVariable table . This routine creates LocalVariable entries for these missing items .