You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Max Kammerer (JIRA)" <ji...@apache.org> on 2016/09/03 10:22:20 UTC
[jira] [Created] (BCEL-280) MethodGen.setMaxLocals() should take in
account local variables defined in Local Variable table
Max Kammerer created BCEL-280:
---------------------------------
Summary: MethodGen.setMaxLocals() should take in account local variables defined in Local Variable table
Key: BCEL-280
URL: https://issues.apache.org/jira/browse/BCEL-280
Project: Commons BCEL
Issue Type: Bug
Components: Main
Affects Versions: 6.0
Environment: Ubuntu 14.04, Bcel 6.0
Reporter: Max Kammerer
Kotlin compiler generates additional fake local variables that are not used in method code, after processing such methods with BCEL fake variables are kept in local variable table but maxLocals value decreased to number of locals used in method bytecode.
As result "java.lang.ClassFormatError: Invalid index 6 in LocalVariableTable in class file test/Bug2" exception is thrown at runtime on attemt to load newly generated class.
Sample code:
{code:title=bug.kt|borderStyle=solid}
package bug
import org.apache.bcel.classfile.ClassParser
import org.apache.bcel.generic.ClassGen
import org.apache.bcel.generic.MethodGen
class Bug {
fun test() {
val list = arrayListOf(1, 2, 3)
list.forEach {
println(it)
}
//here additional variable are generated - see bytecode below
}
}
fun main(args: Array<String>) {
val parser = ClassParser(ClassLoader.getSystemClassLoader().getResourceAsStream("bug/Bug.class"), "Bug.class");
val javaClass = parser.parse();
val classGen = ClassGen(javaClass)
classGen.className = "test.Bug2"
val originalMethod = classGen.methods.filter { it.name == "test" }.single()
classGen.removeMethod(originalMethod)
val newMethodGen = MethodGen(originalMethod, classGen.className, classGen.constantPool)
newMethodGen.setMaxLocals()
val newMethod = newMethodGen.method
classGen.addMethod(newMethod)
val bug2Class = classGen.javaClass
// Exception in thread "main" java.lang.ClassFormatError: Invalid index 6 in LocalVariableTable in class file test/Bug2
// at java.lang.ClassLoader.defineClass1(Native Method)
// at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
// at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
// at bug.BugKt$main$1.findClass(bug.kt:53)
// at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
// at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
// at bug.BugKt.main(bug.kt:58)
object : ClassLoader(ClassLoader.getSystemClassLoader()) {
@Throws(ClassNotFoundException::class)
protected override fun findClass(name: String): Class<*> {
if (name == "test.Bug2") {
val bytes = bug2Class.bytes
return defineClass(name, bytes, 0, bytes.size)
}
return super.findClass(name)
}
}.loadClass("test.Bug2").newInstance()
//8 != 6
assert(originalMethod.code.maxLocals == newMethod.code.maxLocals)
}
{code}
{code:title=Bug.test.bytecode|borderStyle=solid}
// access flags 0x11
public final test()V
L0
LINENUMBER 9 L0
ICONST_3
ANEWARRAY java/lang/Integer
DUP
ICONST_0
ICONST_1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
DUP
ICONST_1
ICONST_2
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
DUP
ICONST_2
ICONST_3
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
INVOKESTATIC kotlin/collections/CollectionsKt.arrayListOf ([Ljava/lang/Object;)Ljava/util/ArrayList;
ASTORE 1
L1
LINENUMBER 10 L1
ALOAD 1
CHECKCAST java/lang/Iterable
ASTORE 2
NOP
L2
LINENUMBER 56 L2
ALOAD 2
INVOKEINTERFACE java/lang/Iterable.iterator ()Ljava/util/Iterator;
ASTORE 3
L3
ALOAD 3
INVOKEINTERFACE java/util/Iterator.hasNext ()Z
IFEQ L4
ALOAD 3
INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
ASTORE 4
L5
ALOAD 4
CHECKCAST java/lang/Number
INVOKEVIRTUAL java/lang/Number.intValue ()I
ISTORE 5
L6
LINENUMBER 11 L6
NOP
L7
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 5
INVOKEVIRTUAL java/io/PrintStream.println (I)V
L8
L9
LINENUMBER 11 L9
L10
LINENUMBER 12 L10
L11
NOP
L12
GOTO L3
L4
LINENUMBER 57 L4
L13
L14
LINENUMBER 14 L14
RETURN
L15
LOCALVARIABLE it I L6 L11 5
LOCALVARIABLE $i$a$1$forEach I L6 L11 6
LOCALVARIABLE element$iv Ljava/lang/Object; L5 L12 4
LOCALVARIABLE $receiver$iv Ljava/lang/Iterable; L2 L13 2
LOCALVARIABLE $i$f$forEach I L2 L13 7
LOCALVARIABLE list Ljava/util/ArrayList; L1 L15 1
LOCALVARIABLE this Lbug/Bug; L0 L15 0
MAXSTACK = 4
MAXLOCALS =
{code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)