I generate bytecodes using the ASM library, and the "Max stack size" for the method is left to calculate automatically. At runtime, I found that this value (maximum stack size) is incorrect.
My source code:
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
....
MethodType initType = MethodType.methodType(void.class, clsList);
mv = cw.visitMethod(ACC_PUBLIC, "<init>", initType.toMethodDescriptorString(), null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/invoke/BaseTemplate", "<init>", "()V", false);
for(int i=0; i< list.size(); i++){
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1+i);
mv.visitFieldInsn(PUTFIELD, className, list.get(i).name(), Utils.getFieldDesc(list.get(i).type()));
}
mv.visitInsn(RETURN);
mv.visitEnd();
....
PrintWriter pw = new PrintWriter(System.out);
CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), true, pw);
Class<?> expClass =defineClass(..);
Above code generates bytecodes:
Classfile /C:/temp/TGWD.class
Last modified Mar 11, 2015; size 403 bytes
MD5 checksum f58b96ad4cb0bc9e62f2ae5e11e63e90
public class TGWD extends java.lang.invoke.BaseTemplate
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
{
final java.lang.invoke.MethodHandle guard;
flags: ACC_FINAL
final java.lang.invoke.MethodHandle trueTarget;
flags: ACC_FINAL
final java.lang.invoke.MethodHandle falseTarget;
flags: ACC_FINAL
public TGWD(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
flags: ACC_PUBLIC
Code:
stack=0, locals=4, args_size=4
0: aload_0
1: invokespecial #13 // Method java/lang/invoke/BaseTemplate."<init>":()V
4: aload_0
5: aload_1
6: putfield #15 // Field guard:Ljava/lang/invoke/MethodHandle;
9: aload_0
10: aload_2
11: putfield #17 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
14: aload_0
15: aload_3
16: putfield #19 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
19: return
public void eval();
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
}
The bytecode reports an error:
org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 0: Insufficient maximum stack size.
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source)
at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
because the build method: stack = 0, locals = 4, args_size = 4
The correct stack size is 2.
There is another ASM stream (from ObjectWeb) that does not calculate MaxStack correctly even if ClassWriter (COMPUTE_MAX + COMPUTE_STACK) is set , indicating that the maximum stack size may be incorrectly calculated if the bytecode in another place is invalid.
So for me the following questions: