]> source.dussan.org Git - javassist.git/commitdiff
fixed bugs related to stack map tables.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 2 Jun 2007 14:12:36 +0000 (14:12 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 2 Jun 2007 14:12:36 +0000 (14:12 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@378 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

12 files changed:
src/main/javassist/CtBehavior.java
src/main/javassist/CtClassType.java
src/main/javassist/CtConstructor.java
src/main/javassist/CtMethod.java
src/main/javassist/CtNewConstructor.java
src/main/javassist/CtNewWrappedMethod.java
src/main/javassist/bytecode/ClassFile.java
src/main/javassist/bytecode/MethodInfo.java
src/main/javassist/compiler/CodeGen.java
src/main/javassist/compiler/Javac.java
src/main/javassist/compiler/MemberCodeGen.java
src/main/javassist/expr/ExprEditor.java

index 249c0eaec65e3ab47b4bcf62cc6195fc01d29f04..f5e27ff4cbae2b30fe32528f6be06ce9647d066f 100644 (file)
@@ -62,6 +62,7 @@ public abstract class CtBehavior extends CtMember {
                         map.put(srcSuperName, destSuperName);
             }
 
+            // a stack map table is copied from srcInfo.
             methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
             if (isCons && patch)
                 methodInfo.setSuperclass(destSuperName);
@@ -349,9 +350,10 @@ public abstract class CtBehavior extends CtMember {
                         String delegateObj, String delegateMethod)
         throws CannotCompileException
     {
-        declaringClass.checkModify();
+        CtClass cc = declaringClass;
+        cc.checkModify();
         try {
-            Javac jv = new Javac(declaringClass);
+            Javac jv = new Javac(cc);
             if (delegateMethod != null)
                 jv.recordProceed(delegateObj, delegateMethod);
 
@@ -359,9 +361,12 @@ public abstract class CtBehavior extends CtMember {
             methodInfo.setCodeAttribute(b.toCodeAttribute());
             methodInfo.setAccessFlags(methodInfo.getAccessFlags()
                                       & ~AccessFlag.ABSTRACT);
+            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
         }
         catch (CompileError e) {
             throw new CannotCompileException(e);
+        } catch (BadBytecode e) {
+            throw new CannotCompileException(e);
         }
     }
 
@@ -380,6 +385,7 @@ public abstract class CtBehavior extends CtMember {
                 ConstPool cp = destInfo.getConstPool();
                 CodeAttribute ca = (CodeAttribute)cattr.copy(cp, map);
                 destInfo.setCodeAttribute(ca);
+                // a stack map table is copied to destInfo.
             }
         }
         catch (CodeAttribute.RuntimeCopyException e) {
@@ -466,7 +472,7 @@ public abstract class CtBehavior extends CtMember {
             CtField field = new CtField(type, fname, cc);
             field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
             cc.addField(field, CtField.Initializer.byNew(type));
-            insertBefore(fname + ".enter();");
+            insertBefore(fname + ".enter();", false);
             String src = fname + ".exit();";
             insertAfter(src, true);
         }
@@ -561,13 +567,20 @@ public abstract class CtBehavior extends CtMember {
      * @see CtConstructor#insertBeforeBody(String)
      */
     public void insertBefore(String src) throws CannotCompileException {
-        declaringClass.checkModify();
+        insertBefore(src, true);
+    }
+
+    private void insertBefore(String src, boolean rebuild)
+        throws CannotCompileException
+    {
+        CtClass cc = declaringClass;
+        cc.checkModify();
         CodeAttribute ca = methodInfo.getCodeAttribute();
         if (ca == null)
             throw new CannotCompileException("no method body");
 
         CodeIterator iterator = ca.iterator();
-        Javac jv = new Javac(declaringClass);
+        Javac jv = new Javac(cc);
         try {
             int nvars = jv.recordParams(getParameterTypes(),
                                         Modifier.isStatic(getModifiers()));
@@ -586,6 +599,8 @@ public abstract class CtBehavior extends CtMember {
 
             int pos = iterator.insertEx(b.get());
             iterator.insert(b.getExceptionTable(), pos);
+            if (rebuild)
+                methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
         }
         catch (NotFoundException e) {
             throw new CannotCompileException(e);
@@ -627,7 +642,8 @@ public abstract class CtBehavior extends CtMember {
     public void insertAfter(String src, boolean asFinally)
         throws CannotCompileException
     {
-        declaringClass.checkModify();
+        CtClass cc = declaringClass;
+        cc.checkModify();
         ConstPool pool = methodInfo.getConstPool();
         CodeAttribute ca = methodInfo.getCodeAttribute();
         if (ca == null)
@@ -637,7 +653,7 @@ public abstract class CtBehavior extends CtMember {
         int retAddr = ca.getMaxLocals();
         Bytecode b = new Bytecode(pool, 0, retAddr + 1);
         b.setStackDepth(ca.getMaxStack() + 1);
-        Javac jv = new Javac(b, declaringClass);
+        Javac jv = new Javac(b, cc);
         try {
             int nvars = jv.recordParams(getParameterTypes(),
                                         Modifier.isStatic(getModifiers()));
@@ -677,6 +693,8 @@ public abstract class CtBehavior extends CtMember {
                     subr = iterator.getCodeLength() - gapLen;
                 }
             }
+
+            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
         }
         catch (NotFoundException e) {
             throw new CannotCompileException(e);
@@ -855,13 +873,14 @@ public abstract class CtBehavior extends CtMember {
                          String exceptionName)
         throws CannotCompileException
     {
-        declaringClass.checkModify();
+        CtClass cc = declaringClass;
+        cc.checkModify();
         ConstPool cp = methodInfo.getConstPool();
         CodeAttribute ca = methodInfo.getCodeAttribute();
         CodeIterator iterator = ca.iterator();
         Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals());
         b.setStackDepth(1);
-        Javac jv = new Javac(b, declaringClass);
+        Javac jv = new Javac(b, cc);
         try {
             jv.recordParams(getParameterTypes(),
                             Modifier.isStatic(getModifiers()));
@@ -883,12 +902,15 @@ public abstract class CtBehavior extends CtMember {
             ca.getExceptionTable().add(getStartPosOfBody(ca), len, len,
                                        cp.addClassInfo(exceptionType));
             iterator.append(b.getExceptionTable(), pos);
+            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
         }
         catch (NotFoundException e) {
             throw new CannotCompileException(e);
         }
         catch (CompileError e) {
             throw new CannotCompileException(e);
+        } catch (BadBytecode e) {
+            throw new CannotCompileException(e);
         }
     }
 
@@ -961,9 +983,10 @@ public abstract class CtBehavior extends CtMember {
         if (!modify)
             return lineNum;
 
-        declaringClass.checkModify();
+        CtClass cc = declaringClass;
+        cc.checkModify();
         CodeIterator iterator = ca.iterator();
-        Javac jv = new Javac(declaringClass);
+        Javac jv = new Javac(cc);
         try {
             jv.recordLocalVariables(ca, index);
             jv.recordParams(getParameterTypes(),
@@ -983,6 +1006,7 @@ public abstract class CtBehavior extends CtMember {
 
             iterator.insert(index, b.get());
             iterator.insert(b.getExceptionTable(), index);
+            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
             return lineNum;
         }
         catch (NotFoundException e) {
index d9146d0aa0a08d45312a0feee1c333d287db7545..ce20578f5428917dc04e33a6c798f139618f3882 100644 (file)
@@ -1350,6 +1350,13 @@ class CtClassType extends CtClass {
                 throw new CannotCompileException(e);
             }
         }
+
+        try {
+            m.rebuildStackMapIf6(classPool, cf);
+        }
+        catch (BadBytecode e) {
+            throw new CannotCompileException(e);
+        }
     }
 
     private void modifyConstructors(ClassFile cf)
@@ -1375,6 +1382,7 @@ class CtClassType extends CtClass {
                                                 classPool);
                         int stacksize = makeFieldInitializer(init, params);
                         insertAuxInitializer(codeAttr, init, stacksize);
+                        minfo.rebuildStackMapIf6(classPool, cf);
                     }
                     catch (BadBytecode e) {
                         throw new CannotCompileException(e);
index a2868fc72c8742025c70d4b1676d2aafe2281c41..4a14bc6015fa55f24991b31cb229096e0d478357 100644 (file)
@@ -44,7 +44,7 @@ public final class CtConstructor extends CtBehavior {
      * must be added to a class with <code>CtClass.addConstructor()</code>.
      *
      * <p>The created constructor does not include a constructor body,
-     * must be specified with <code>setBody()</code>.
+     * which must be specified with <code>setBody()</code>.
      *
      * @param declaring         the class to which the created method is added.
      * @param parameters        a list of the parameter types
@@ -244,7 +244,8 @@ public final class CtConstructor extends CtBehavior {
      *                  It must be a single statement or block.
      */
     public void insertBeforeBody(String src) throws CannotCompileException {
-        declaringClass.checkModify();
+        CtClass cc = declaringClass;
+        cc.checkModify();
         if (isClassInitializer())
             throw new CannotCompileException("class initializer");
 
@@ -253,7 +254,7 @@ public final class CtConstructor extends CtBehavior {
         Bytecode b = new Bytecode(methodInfo.getConstPool(),
                                   ca.getMaxStack(), ca.getMaxLocals());
         b.setStackDepth(ca.getMaxStack());
-        Javac jv = new Javac(b, declaringClass);
+        Javac jv = new Javac(b, cc);
         try {
             jv.recordParams(getParameterTypes(), false);
             jv.compileStmnt(src);
@@ -262,6 +263,7 @@ public final class CtConstructor extends CtBehavior {
             iterator.skipConstructor();
             int pos = iterator.insertEx(b.get());
             iterator.insert(b.getExceptionTable(), pos);
+            methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
         }
         catch (NotFoundException e) {
             throw new CannotCompileException(e);
@@ -346,8 +348,16 @@ public final class CtConstructor extends CtBehavior {
         if (isConstructor()) {
             MethodInfo minfo = method.getMethodInfo2();
             CodeAttribute ca = minfo.getCodeAttribute();
-            if (ca != null)
+            if (ca != null) {
                 removeConsCall(ca);
+                try {
+                    methodInfo.rebuildStackMapIf6(declaring.getClassPool(),
+                                                  declaring.getClassFile2());
+                }
+                catch (BadBytecode e) {
+                    throw new CannotCompileException(e);
+                }
+            }
         }
 
         method.setName(name);
index a22866457653a93d396a4caefc498bac9e6aab09..a6015dbafe2b2678533d9ff494023a5bc7b58581 100644 (file)
@@ -262,6 +262,7 @@ public final class CtMethod extends CtBehavior {
         methodInfo.setCodeAttribute(cattr);
         methodInfo.setAccessFlags(methodInfo.getAccessFlags()
                                   & ~AccessFlag.ABSTRACT);
+        // rebuilding a stack map table is not needed.
     }
 
     // inner classes
index ac3d12b28419b9ee8d5827c34a606f13668d65a6..2ac2f7caf70b46002550f7862a9c2a988f5446a7 100644 (file)
@@ -67,8 +67,10 @@ public class CtNewConstructor {
         Javac compiler = new Javac(declaring);
         try {
             CtMember obj = compiler.compile(src);
-            if (obj instanceof CtConstructor)
+            if (obj instanceof CtConstructor) {
+                // a stack map table has been already created.
                 return (CtConstructor)obj;
+            }
         }
         catch (CompileError e) {
             throw new CannotCompileException(e);
@@ -145,6 +147,7 @@ public class CtNewConstructor {
 
         code.add(Bytecode.RETURN);
 
+        // no need to construct a stack map table.
         cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
         return cons;
     }
index 88e680ebd773b6832f7154d28f86d19b02c6f69b..5e48749d820e4eba309ebc2b14747fe56e81b3d3 100644 (file)
@@ -63,6 +63,9 @@ class CtNewWrappedMethod {
         return code;
     }
 
+    /* The generated method body does not need a stack map table
+     * because it does not contain a branch instruction.
+     */
     protected static int makeBody0(CtClass clazz, ClassFile classfile,
                                    CtMethod wrappedBody,
                                    boolean isStatic, CtClass[] parameters,
@@ -146,6 +149,7 @@ class CtNewWrappedMethod {
                                              map);
             int acc = body.getAccessFlags();
             body.setAccessFlags(AccessFlag.setPrivate(acc));
+            // a stack map is copied.  rebuilding it is not needed. 
             classfile.addMethod(body);
             bodies.put(src, bodyname);
         }
index 3d743d7b6609cc511429aeda51163d358bb8dd33..73cdc6ec5add579007091a80628947531601ae7c 100644 (file)
@@ -45,11 +45,29 @@ public final class ClassFile {
     String[] cachedInterfaces;
     String cachedSuperclass;
 
+    /**
+     * The major version number of class files
+     * for JDK 1.3.
+     */
+    public static final int JAVA_3 = 47;
+
+    /**
+     * The major version number of class files
+     * for JDK 1.5.
+     */
+    public static final int JAVA_5 = 49;
+
+    /**
+     * The major version number of class files
+     * for JDK 1.6.
+     */
+    public static final int JAVA_6 = 50;
+
     /**
      * The major version number of class files created
      * from scratch.  The value is 47 (JDK 1.3).
      */
-    public static final int MAJOR_VERSION = 47;
+    public static final int MAJOR_VERSION = JAVA_3;
 
     /**
      * Constructs a class file from a byte stream.
@@ -540,6 +558,8 @@ public final class ClassFile {
 
     /**
      * Appends a method to the class.
+     * If there is a bridge method with the same name and signature,
+     * then the bridge method is removed before a new method is added.
      *
      * @throws DuplicateMemberException         when the method is already included.
      */
@@ -558,20 +578,38 @@ public final class ClassFile {
         String name = newMinfo.getName();
         String descriptor = newMinfo.getDescriptor();
         ListIterator it = methods.listIterator(0);
-        while (it.hasNext()) {
-            MethodInfo minfo = (MethodInfo)it.next();
-            if (minfo.getName().equals(name)
-                    && notBridgeMethod(minfo) && notBridgeMethod(newMinfo)
-                    && Descriptor.eqParamTypes(minfo.getDescriptor(),
-                                               descriptor))
+        while (it.hasNext())
+            if (isDuplicated(newMinfo, name, descriptor, (MethodInfo)it.next(), it))
                 throw new DuplicateMemberException("duplicate method: " + name
-                                                 + " in " + this.getName());
+                                                   + " in " + this.getName());
+    }
+
+    private static boolean isDuplicated(MethodInfo newMethod, String newName,
+                                        String newDesc, MethodInfo minfo,
+                                        ListIterator it)
+    {
+        if (!minfo.getName().equals(newName))
+            return false;
+
+        String desc = minfo.getDescriptor();
+        if (!Descriptor.eqParamTypes(desc, newDesc))
+           return false;
+
+        if (desc.equals(newDesc)) {
+            if (notBridgeMethod(minfo))
+                return true;
+            else {
+                it.remove();
+                return false;
+            }
         }
+        else
+           return notBridgeMethod(minfo) && notBridgeMethod(newMethod);
     }
 
     /* For a bridge method, see Sec. 15.12.4.5 of JLS 3rd Ed.
      */
-    private boolean notBridgeMethod(MethodInfo minfo) {
+    private static boolean notBridgeMethod(MethodInfo minfo) {
         return (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0;
     }
 
index 8d0cce10320fba1c0562346d604309c1b8a74856..6e945570ba11a5b6d097b3bd48c1ec96341b361f 100644 (file)
@@ -21,6 +21,8 @@ import java.io.IOException;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import javassist.ClassPool;
+import javassist.bytecode.stackmap.MapMaker;
 
 /**
  * <code>method_info</code> structure.
@@ -370,6 +372,40 @@ public final class MethodInfo {
         attribute.add(cattr);
     }
 
+    /**
+     * Rebuilds a stack map table if the class file is for Java 6
+     * or later.  Java 5 or older Java VMs do not recognize a stack
+     * map table. 
+     *
+     * @param pool          used for making type hierarchy.
+     * @param cf            rebuild if this class file is for Java 6 or later.
+     * @see #rebuildStackMap(ClassPool)
+     * @since 3.6
+     */
+    public void rebuildStackMapIf6(ClassPool pool, ClassFile cf)
+        throws BadBytecode
+    {
+        if (cf.getMajorVersion() >= ClassFile.JAVA_6)
+            rebuildStackMap(pool);
+    }
+
+    /**
+     * Rebuilds a stack map table.  If no stack map table is included,
+     * a new one is created.  If this <code>MethodInfo</code> does not
+     * include a code attribute, nothing happens.
+     *
+     * @param pool          used for making type hierarchy.
+     * @see StackMapTable
+     * @since 3.6
+     */
+    public void rebuildStackMap(ClassPool pool) throws BadBytecode {
+        CodeAttribute ca = getCodeAttribute();
+        if (ca != null) {
+            StackMapTable smt = MapMaker.make(pool, this);
+            ca.setAttribute(smt);
+        }
+    }
+
     /**
      * Returns the line number of the source line corresponding to the specified
      * bytecode contained in this method.
index dfcddc4eb0873e750cb3756598d321ec9ba4171e..0712d906443562b9a68aa32f6ddd1da99aeb3651 100644 (file)
@@ -53,7 +53,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
      */
     protected static abstract class ReturnHook {
         ReturnHook next;
-        protected abstract void doit(Bytecode b, int opcode);
+
+        /**
+         * Returns true if the generated code ends with return,
+         * throw, or goto. 
+         */
+        protected abstract boolean doit(Bytecode b, int opcode);
+
         protected ReturnHook(CodeGen gen) {
             next = gen.returnHooks;
             gen.returnHooks = this;
@@ -607,7 +613,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
         }
 
         for (ReturnHook har = returnHooks; har != null; har = har.next)
-            har.doit(bytecode, op);
+            if (har.doit(bytecode, op)) {
+                hasReturned = true;
+                return;
+            }
 
         bytecode.addOpcode(op);
         hasReturned = true;
@@ -645,9 +654,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
         bc.addOpcode(MONITORENTER);
 
         ReturnHook rh = new ReturnHook(this) {
-            protected void doit(Bytecode b, int opcode) {
+            protected boolean doit(Bytecode b, int opcode) {
                 b.addAload(var);
                 b.addOpcode(MONITOREXIT);
+                return false;
             }
         };
 
@@ -665,10 +675,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
             bc.addIndex(0);
         }
 
-        int pc4 = bc.currentPc();
-        rh.doit(bc, 0);         // the 2nd arg is ignored.
-        bc.addOpcode(ATHROW);
-        bc.addExceptionHandler(pc, pc2, pc4, 0);
+        if (pc < pc2) {         // if the body is not empty
+            int pc4 = bc.currentPc();
+            rh.doit(bc, 0);         // the 2nd arg is ignored.
+            bc.addOpcode(ATHROW);
+            bc.addExceptionHandler(pc, pc2, pc4, 0);
+        }
+
         if (!hasReturned)
             bc.write16bit(pc3, bc.currentPc() - pc3 + 1);
 
index d32fddcfbcd5090a7400c3322d1dba73b6d6419c..b3d275b3f3679094fc95a6392bdb47dba8288b44 100644 (file)
@@ -27,6 +27,7 @@ import javassist.Modifier;
 import javassist.bytecode.Bytecode;
 import javassist.bytecode.CodeAttribute;
 import javassist.bytecode.LocalVariableAttribute;
+import javassist.bytecode.BadBytecode;
 import javassist.bytecode.Opcode;
 import javassist.NotFoundException;
 
@@ -89,8 +90,17 @@ public class Javac {
         try {
             if (mem instanceof FieldDecl)
                 return compileField((FieldDecl)mem);
-            else
-                return compileMethod(p, (MethodDecl)mem);
+            else {
+                CtBehavior cb = compileMethod(p, (MethodDecl)mem);
+                CtClass decl = cb.getDeclaringClass();
+                cb.getMethodInfo2()
+                  .rebuildStackMapIf6(decl.getClassPool(),
+                                      decl.getClassFile2());
+                return cb;
+            }
+        }
+        catch (BadBytecode bb) {
+            throw new CompileError(bb.getMessage());
         }
         catch (CannotCompileException e) {
             throw new CompileError(e.getMessage());
@@ -128,7 +138,7 @@ public class Javac {
         return f;
     }
 
-    private CtMember compileMethod(Parser p, MethodDecl md)
+    private CtBehavior compileMethod(Parser p, MethodDecl md)
         throws CompileError
     {
         int mod = MemberResolver.getModifiers(md.getModifiers());
index 3d7ed3737e817653602eb5f5a9db0d32cd2ccaf7..71849957f16dc858b1903e129f14204587763dc6 100644 (file)
@@ -24,8 +24,6 @@ import java.util.ArrayList;
 /* Code generator methods depending on javassist.* classes.
  */
 public class MemberCodeGen extends CodeGen {
-    public static final int JAVA5_VER = 49;
-
     protected MemberResolver resolver;
     protected CtClass   thisClass;
     protected MethodInfo thisMethod;
@@ -106,11 +104,11 @@ public class MemberCodeGen extends CodeGen {
 
         private void jsrJmp(Bytecode b) {
             b.addOpcode(Opcode.GOTO);
-            jsrList.add(new Integer(b.currentPc()));
+            jsrList.add(new int[] {b.currentPc(), var});
             b.addIndex(0);
         }
 
-        protected void doit(Bytecode b, int opcode) {
+        protected boolean doit(Bytecode b, int opcode) {
             switch (opcode) {
             case Opcode.RETURN :
                 jsrJmp(b);
@@ -143,6 +141,47 @@ public class MemberCodeGen extends CodeGen {
             default :
                 throw new RuntimeException("fatal");
             }
+
+            return false;
+        }
+    }
+
+    static class JsrHook2 extends ReturnHook {
+        int var;
+        int target;
+
+        JsrHook2(CodeGen gen, int[] retTarget) {
+            super(gen);
+            target = retTarget[0];
+            var = retTarget[1];
+        }
+
+        protected boolean doit(Bytecode b, int opcode) {
+            switch (opcode) {
+            case Opcode.RETURN :
+                break;
+            case ARETURN :
+                b.addAstore(var);
+                break;
+            case IRETURN :
+                b.addIstore(var);
+                break;
+            case LRETURN :
+                b.addLstore(var);
+                break;
+            case DRETURN :
+                b.addDstore(var);
+                break;
+            case FRETURN :
+                b.addFstore(var);
+                break;
+            default :
+                throw new RuntimeException("fatal");
+            }
+
+            b.addOpcode(Opcode.GOTO);
+            b.addIndex(target - b.currentPc() + 3);
+            return true;
         }
     }
 
@@ -236,9 +275,12 @@ public class MemberCodeGen extends CodeGen {
         Bytecode bc = bytecode;
         int n = returnList.size();
         for (int i = 0; i < n; ++i) {
-            int pc = ((Integer)returnList.get(i)).intValue();
+            final int[] ret = (int[])returnList.get(i);
+            int pc = ret[0];
             bc.write16bit(pc, bc.currentPc() - pc + 1);
+            ReturnHook hook = new JsrHook2(this, ret);
             finallyBlock.accept(this);
+            hook.remove(this);
             if (!hasReturned) {
                 bc.addOpcode(Opcode.GOTO);
                 bc.addIndex(pc + 3 - bc.currentPc());
@@ -923,7 +965,7 @@ public class MemberCodeGen extends CodeGen {
     }
 
     protected void atClassObject2(String cname) throws CompileError {
-        if (getMajorVersion() < JAVA5_VER)
+        if (getMajorVersion() < ClassFile.JAVA_5)
             super.atClassObject2(cname);
         else
             bytecode.addLdc(bytecode.getConstPool().addClassInfo(cname));
index 9bba13b755e0f484d5201a4b58126d9a590ef819..db9cb437ce39de3e8575947fc64118a233784bfc 100644 (file)
@@ -101,12 +101,21 @@ public class ExprEditor {
             }
         }
 
-        // codeAttr might be modified by other partys
+        // codeAttr might be modified by other partiess
         // so I check the current value of max-locals.
         if (codeAttr.getMaxLocals() < context.maxLocals)
             codeAttr.setMaxLocals(context.maxLocals);
 
         codeAttr.setMaxStack(codeAttr.getMaxStack() + context.maxStack);
+        try {
+            if (edited)
+                minfo.rebuildStackMapIf6(clazz.getClassPool(),
+                                         clazz.getClassFile2());
+        }
+        catch (BadBytecode b) {
+            throw new CannotCompileException(b.getMessage(), b);
+        }
+
         return edited;
     }