You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2016/09/06 06:38:18 UTC

svn commit: r1759364 - in /commons/proper/bcel/trunk/src: changes/ main/java/org/apache/bcel/generic/ test/java/org/apache/bcel/ test/java/org/apache/bcel/data/

Author: britter
Date: Tue Sep  6 06:38:18 2016
New Revision: 1759364

URL: http://svn.apache.org/viewvc?rev=1759364&view=rev
Log:
BCEL-276: LocalVariableTypeTable is not updated. Thanks to Sam Yoon. This also fixes #10 from GitHub.

Added:
    commons/proper/bcel/trunk/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java
    commons/proper/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java
Modified:
    commons/proper/bcel/trunk/src/changes/changes.xml
    commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java

Modified: commons/proper/bcel/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/changes/changes.xml?rev=1759364&r1=1759363&r2=1759364&view=diff
==============================================================================
--- commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] Tue Sep  6 06:38:18 2016
@@ -21,7 +21,7 @@
 This file is also used by the maven-changes-plugin to generate the release notes.
 Useful ways of finding items to add to this file are:
 
-1.  Add items when you fix a bug or add a feature (this makes the 
+1.  Add items when you fix a bug or add a feature (this makes the
 release process easy :-).
 
 2.  Do a JIRA search for tickets closed since the previous release.
@@ -33,7 +33,7 @@ To generate the release notes from this
 
 mvn changes:announcement-generate -Prelease-notes [-Dchanges.version=nnn]
 
-then tweak the formatting if necessary 
+then tweak the formatting if necessary
 and commit
 
 The <action> type attribute can be add,update,fix,remove.
@@ -45,16 +45,16 @@ The <action> type attribute can be add,u
     <author email="dev@commons.apache.org">Apache Commons developers</author>
   </properties>
 
-  <!-- NOTE: 
+  <!-- NOTE:
   The description below is specially formatted so as to improve the layout of the generated release notes:
   The parsing process removes all line feeds, replacing them with a single space.
   The Velocity template in resources/templates has been enhanced to replace pairs of adjacent spaces
   with a new-line in the release notes. (These spaces are ignored when displaying HTML).
   If the output is not quite correct, check for invisible trailing spaces!
-  
+
   N.B. The release notes template groups actions by type, and only extracts data for the current release.
   The changes report outputs actions in the order they appear in this file.
-  
+
   To regenerate the release notes:
   mvn changes:announcement-generate -Prelease-notes [-Dchanges.version=nnn]
 
@@ -63,6 +63,7 @@ The <action> type attribute can be add,u
 
   <body>
     <release version="6.1" date="tba" description="tba">
+      <action issue="BCEL-276" type="fix" dev="britter" due-to="Sam Yoon">LocalVariableTypeTable is not updated.</action>
       <action issue="BCEL-277" type="fix" dev="britter" due-to="Sam Yoon">Resolving the String representation of a constant throws NoSuchElementException in case of CONSTANT_NameAndType constant.</action>
     </release>
 
@@ -72,7 +73,7 @@ The <action> type attribute can be add,u
 
  It requires Java 7 or higher to run.
 
-   
+
 COMPATIBILITY with 5.2
  ======================
 
@@ -111,7 +112,7 @@ Source compatible - Yes, sort of;
 For full information about API changes please see the extended Clirr report:
 
     http://commons.apache.org/bcel/clirr-report.html">
-      <action issue="BCEL-262" type="update" dev="britter" due-to="Mark Roberts">InvokeInstruction.getClassName(ConstantPoolGen) 
+      <action issue="BCEL-262" type="update" dev="britter" due-to="Mark Roberts">InvokeInstruction.getClassName(ConstantPoolGen)
                                           should not throw an exception when it detects an array.</action>
       <action issue="BCEL-237" type="fix" dev="sebb">non-empty final arrays should be private as they are mutable.</action>
       <action issue="BCEL-230" type="update" dev="britter">Document the Java platform requirement clearly and early.</action>

Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java?rev=1759364&r1=1759363&r2=1759364&view=diff
==============================================================================
--- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java (original)
+++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java Tue Sep  6 06:38:18 2016
@@ -35,6 +35,7 @@ import org.apache.bcel.classfile.LineNum
 import org.apache.bcel.classfile.LineNumberTable;
 import org.apache.bcel.classfile.LocalVariable;
 import org.apache.bcel.classfile.LocalVariableTable;
+import org.apache.bcel.classfile.LocalVariableTypeTable;
 import org.apache.bcel.classfile.Method;
 import org.apache.bcel.classfile.ParameterAnnotationEntry;
 import org.apache.bcel.classfile.ParameterAnnotations;
@@ -42,7 +43,7 @@ import org.apache.bcel.classfile.Runtime
 import org.apache.bcel.classfile.Utility;
 import org.apache.bcel.util.BCELComparator;
 
-/** 
+/**
  * Template class for building up a method. This is done by defining exception
  * handlers, adding thrown exceptions, local variables and attributes, whereas
  * the `LocalVariableTable' and `LineNumberTable' attributes will be set
@@ -65,6 +66,8 @@ public class MethodGen extends FieldGenO
     private int max_stack;
     private InstructionList il;
     private boolean strip_attributes;
+    private LocalVariableTable local_variable_table = null;
+    private LocalVariableTypeTable local_variable_type_table = null;
     private final List<LocalVariableGen> variable_vec = new ArrayList<>();
     private final List<LineNumberGen> line_number_vec = new ArrayList<>();
     private final List<CodeExceptionGen> exception_vec = new ArrayList<>();
@@ -222,21 +225,10 @@ public class MethodGen extends FieldGenO
                             }
                         }
                     } else if (a instanceof LocalVariableTable) {
-                        final LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable();
-                        removeLocalVariables();
-                        for (final LocalVariable l : lv) {
-                            InstructionHandle start = il.findHandle(l.getStartPC());
-                            InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
-                            // Repair malformed handles
-                            if (null == start) {
-                                start = il.getStart();
-                            }
-                            if (null == end) {
-                                end = il.getEnd();
-                            }
-                            addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
-                                    .getIndex(), start, end);
-                        }
+                        this.local_variable_table = (LocalVariableTable) a;
+                        updateLocalVariableTable(this.local_variable_table);
+                    } else if (a instanceof LocalVariableTypeTable) {
+                        this.local_variable_type_table = (LocalVariableTypeTable) a;
                     } else {
                         addCodeAttribute(a);
                     }
@@ -258,7 +250,6 @@ public class MethodGen extends FieldGenO
         }
     }
 
-
     /**
      * Adds a local variable to this method.
      *
@@ -292,7 +283,6 @@ public class MethodGen extends FieldGenO
                 + " as type for local variable");
     }
 
-
     /**
      * Adds a local variable to this method and assigns an index automatically.
      *
@@ -629,8 +619,18 @@ public class MethodGen extends FieldGenO
         /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.)
          */
         if ((variable_vec.size() > 0) && !strip_attributes) {
+            if (local_variable_table != null) {
+                updateLocalVariableTable(local_variable_table);
+            }
             addCodeAttribute(lvt = getLocalVariableTable(_cp));
         }
+        if (local_variable_type_table != null) {
+            // LocalVariable length in LocalVariableTypeTable is not updated automatically. It's a difference with LocalVariableTable.
+            if (lvt != null) {
+                adjustLocalVariableLength(lvt);
+            }
+            addCodeAttribute(local_variable_type_table);
+        }
         if ((line_number_vec.size() > 0) && !strip_attributes) {
             addCodeAttribute(lnt = getLineNumberTable(_cp));
         }
@@ -683,6 +683,38 @@ public class MethodGen extends FieldGenO
         return m;
     }
 
+    private void updateLocalVariableTable(LocalVariableTable a) {
+        final LocalVariable[] lv = a.getLocalVariableTable();
+        removeLocalVariables();
+        for (final LocalVariable l : lv) {
+            InstructionHandle start = il.findHandle(l.getStartPC());
+            InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
+            // Repair malformed handles
+            if (null == start) {
+                start = il.getStart();
+            }
+            if (null == end) {
+                end = il.getEnd();
+            }
+            addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
+                    .getIndex(), start, end);
+        }
+    }
+
+    private void adjustLocalVariableLength(LocalVariableTable lvt) {
+        LocalVariable[] lv = lvt.getLocalVariableTable();
+        LocalVariable[] lvg = local_variable_type_table.getLocalVariableTypeTable();
+
+        for (int i = 0, length = lvg.length; i < length; i++) {
+            for (LocalVariable l : lv) {
+                if (lvg[i].getName().equals(l.getName()) && lvg[i].getIndex() == l.getIndex()) {
+                    lvg[i].setLength(l.getLength());
+                    break;
+                }
+            }
+        }
+    }
+
 
     /**
      * Remove all NOPs from the instruction list (if possible) and update every
@@ -1167,7 +1199,7 @@ public class MethodGen extends FieldGenO
             l.add(annotation);
             param_annotations[parameterIndex] = l;
         }
-    }          
+    }
 
 
 
@@ -1192,7 +1224,7 @@ public class MethodGen extends FieldGenO
      * Return value as defined by given BCELComparator strategy.
      * By default two MethodGen objects are said to be equal when
      * their names and signatures are equal.
-     * 
+     *
      * @see java.lang.Object#equals(java.lang.Object)
      */
     @Override
@@ -1204,7 +1236,7 @@ public class MethodGen extends FieldGenO
     /**
      * Return value as defined by given BCELComparator strategy.
      * By default return the hashcode of the method's name XOR signature.
-     * 
+     *
      * @see java.lang.Object#hashCode()
      */
     @Override

Added: commons/proper/bcel/trunk/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java?rev=1759364&view=auto
==============================================================================
--- commons/proper/bcel/trunk/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java (added)
+++ commons/proper/bcel/trunk/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java Tue Sep  6 06:38:18 2016
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.bcel;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ACONST_NULL;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.GETSTATIC;
+import org.apache.bcel.generic.INVOKEVIRTUAL;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.LocalVariableGen;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.Type;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.LinkedList;
+import java.util.List;
+
+public class LocalVariableTypeTableTestCase extends AbstractTestCase {
+    public class TestClassLoader extends ClassLoader {
+        public TestClassLoader(ClassLoader parent) {
+            super(parent);
+        }
+
+        public Class<?> findClass(String name, byte[] bytes) {
+            return defineClass(name, bytes, 0, bytes.length);
+        }
+    }
+
+    @Test
+    public void testWithGenericArguement() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
+        String targetClass = PACKAGE_BASE_NAME + ".data.SimpleClassHasMethodIncludeGenericArgument";
+        TestClassLoader loader = new TestClassLoader(getClass().getClassLoader());
+        Class cls = loader.findClass(targetClass, getBytesFromClass(targetClass));
+
+        java.lang.reflect.Method method = cls.getDeclaredMethod("a", String.class, List.class);
+        method.invoke(null, "a1", new LinkedList<String>());
+        method = cls.getDeclaredMethod("b", String.class, List.class);
+        method.invoke(null, "b1", new LinkedList<String>());
+        method = cls.getDeclaredMethod("c", String.class, String.class);
+        method.invoke(null, "c1", "c2");
+        method = cls.getDeclaredMethod("d", List.class, String.class);
+        method.invoke(null, new LinkedList<String>(), "d2");
+    }
+
+    private byte[] getBytesFromClass(String className) throws ClassNotFoundException, IOException {
+        JavaClass clazz = getTestClass(className);
+        ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
+
+        Method[] methods = clazz.getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            Method method = methods[i];
+            if (!method.isNative() && !method.isAbstract())
+                methods[i] = injection(clazz, method, cp, findFirstStringLocalVariableOffset(method));
+        }
+
+        clazz.setConstantPool(cp.getFinalConstantPool());
+
+        return clazz.getBytes();
+    }
+
+    public Method injection(JavaClass clazz, Method method, ConstantPoolGen cp, int firstStringOffset) {
+        MethodGen methodGen = new MethodGen(method, clazz.getClassName(), cp);
+
+        InstructionList instructionList = methodGen.getInstructionList();
+        instructionList.insert(instructionList.getStart(), makeWillBeAddedInstructionList(methodGen, firstStringOffset));
+
+        methodGen.setMaxStack();
+        methodGen.setMaxLocals();
+
+        method = methodGen.getMethod();
+        instructionList.dispose();
+
+        return method;
+    }
+
+    public InstructionList makeWillBeAddedInstructionList(MethodGen methodGen, int firstStringOffset) {
+        if (firstStringOffset == -1)
+            return new InstructionList();
+
+        LocalVariableGen localVariableGen = methodGen.getLocalVariables()[firstStringOffset];
+        Instruction instruction;
+
+        if (localVariableGen != null)
+            instruction = new ALOAD(localVariableGen.getIndex());
+        else
+            instruction = new ACONST_NULL();
+
+        return createPrintln(methodGen.getConstantPool(), instruction);
+    }
+
+    public InstructionList createPrintln(ConstantPoolGen cp, Instruction instruction) {
+        final InstructionList il = new InstructionList();
+
+        final int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
+        final int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
+        il.append(new GETSTATIC(out));
+        il.append(instruction);
+        il.append(new INVOKEVIRTUAL(println));
+
+        return il;
+    }
+
+    public int findFirstStringLocalVariableOffset(Method method) {
+        Type[] argumentTypes = method.getArgumentTypes();
+        int offset = -1;
+
+        for (int i = 0, count = argumentTypes.length; i < count; i++) {
+            if (Type.STRING.getSignature().equals(argumentTypes[i].getSignature())) {
+                if (method.isStatic())
+                    offset = i;
+                else
+                    offset = i + 1;
+
+                break;
+            }
+        }
+
+        return offset;
+    }
+}

Added: commons/proper/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java?rev=1759364&view=auto
==============================================================================
--- commons/proper/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java (added)
+++ commons/proper/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java Tue Sep  6 06:38:18 2016
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.bcel.data;
+
+import java.util.List;
+
+public class SimpleClassHasMethodIncludeGenericArgument {
+    public static void a(String a1, List<String> a2) {
+    }
+
+    public static void b(String b1, List b2) {
+    }
+
+    public static void c(String c1, String c2) {
+    }
+
+    public static void d(List<String> d1, String d2) {
+    }
+}