Bug 45217 - MethodGen: LocalVariableTableGen issues
Summary: MethodGen: LocalVariableTableGen issues
Status: NEW
Alias: None
Product: BCEL - Now in Jira
Classification: Unclassified
Component: Main (show other bugs)
Version: unspecified
Hardware: PC Linux
: P2 normal
Target Milestone: ---
Assignee: issues@commons.apache.org
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-06-16 13:14 UTC by Matthew Wilson
Modified: 2008-06-16 13:22 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Wilson 2008-06-16 13:14:00 UTC
 
Comment 1 Matthew Wilson 2008-06-16 13:15:52 UTC
MethodGen mistakenly fills in LocalVariableTableGen from both LocalVariableTable and LocalVariableTypeTable.  In parsing LocalVariableTypeTable, it incorrectly reads the signatures with generics.  As a result, the LocalVariableTable is corrupted.

Here is an example:

public class VariableTableBug
{

   public String getFirstItem( final List< String > list )
   {
      int index = 0;
      String result = list.get( index );
      return result;
   }

   public static void main( final String[] args ) throws Exception
   {
      // find the resource that is our class
      Class< VariableTableBug > clazz = VariableTableBug.class;
      String resource = clazz.getName().replace( '.', '/' ) + ".class";
      
      // load it using BCEL
      JavaClass javaClass = new ClassParser( clazz.getClassLoader().getResourceAsStream( resource ),
                                             resource ).parse();
      
      // convert everything to a ClassGen
      ClassGen classGen = new ClassGen( javaClass );
      
      // find them getFirstItem method
      Method getFirstItemMethod = null;
      for ( Method method : classGen.getMethods() )
      {
         if ( method.getName().equals( "getFirstItem" ) )
         {
            getFirstItemMethod = method;
            break;
         }
      }
      
      // dump the LocalVariableTable attribute
      System.out.println( "LocalVariableTable of original" );
      System.out.println( "------------------------------" );
      for ( LocalVariable localVariable : getFirstItemMethod.getLocalVariableTable().getLocalVariableTable() )
      {
         System.out.println( localVariable.getName() + "\t" + localVariable.getIndex() + "\t" + localVariable.getSignature() );
      }
      System.out.println();

      // dump the LocalVariableTypeTable attribute
      for ( Attribute attribute : getFirstItemMethod.getCode().getAttributes() )
      {
         if ( attribute instanceof LocalVariableTypeTable )
         {
            System.out.println( "LocalVariableTypeTable of original" );
            System.out.println( "----------------------------------" );
            for ( LocalVariable localVariable : ( (LocalVariableTypeTable) attribute ).getLocalVariableTypeTable() )
            {
               System.out.println( localVariable.getName() + "\t" + localVariable.getIndex() + "\t" + localVariable.getSignature() );
            }
         }
      }
      System.out.println();
      
      // now convert to a MethodGen
      MethodGen methodGen = new MethodGen( getFirstItemMethod,
                                           classGen.getClassName(),
                                           classGen.getConstantPool() );
      
      // dump the LocalVariableTable
      System.out.println( "LocalVariableTable of MethodGen" );
      System.out.println( "-------------------------------" );
      for ( LocalVariableGen localVariableGen : methodGen.getLocalVariables() )
      {
         System.out.println( localVariableGen.getName() + "\t" + localVariableGen.getIndex() + "\t" + localVariableGen.getType() );
      }
   }
   
}
Comment 2 Matthew Wilson 2008-06-16 13:22:09 UTC
The issue is here, AFAICT, in the constructor of MethodGen:


...
                    } else if (a instanceof LocalVariableTable) {
                        LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable();
                        removeLocalVariables();
                        // [snip]
                    } else if (a instanceof LocalVariableTypeTable) {
                        LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
                        removeLocalVariables();
...

It fills in the local variables from the LocalVariableTypeTable as well, but removes the variables declared in LocalVariableTable.  Since the LocalVariableTypeTable only includes variables with generics (or so it seems that Eclipse's compiler does that), the other variables are removed.  It should be fairly safe to remove that 'removeLocalVariables()' call.

The other part of the issue is Type.getType(String) not parsing the generic types correctly.  I'm not sure what the best thing to do is there, though.