]> source.dussan.org Git - javassist.git/commitdiff
changed the implementation of try statements so that jsr/ret will not be used anymore.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 12 May 2007 14:45:10 +0000 (14:45 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 12 May 2007 14:45:10 +0000 (14:45 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@371 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/bytecode/ClassFile.java
src/main/javassist/compiler/CodeGen.java
src/main/javassist/compiler/MemberCodeGen.java
tutorial/tutorial.html
tutorial/tutorial3.html

index 50b6cacdd9cf50ecae72a62bd4c21c447e5c4564..e28e6c63167a289dc717592bf74569fb501d14c3 100644 (file)
@@ -45,6 +45,12 @@ public final class ClassFile {
     String[] cachedInterfaces;
     String cachedSuperclass;
 
+    /**
+     * The major version number of class files created
+     * from scratch.  The value is 45 (JDK 1.1).
+     */
+    public static final int MAJOR_VERSION = 45;
+
     /**
      * Constructs a class file from a byte stream.
      */
@@ -63,7 +69,7 @@ public final class ClassFile {
      *            a fully-qualified super class name
      */
     public ClassFile(boolean isInterface, String classname, String superclass) {
-        major = 45;
+        major = MAJOR_VERSION;
         minor = 3; // JDK 1.1 or later
         constPool = new ConstPool(classname);
         thisClass = constPool.getThisClassInfo();
index c69005f96dcd56d04a89081aba3383a8beed6fb7..dfcddc4eb0873e750cb3756598d321ec9ba4171e 100644 (file)
@@ -1547,6 +1547,15 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
             cname = MemberResolver.jvmToJavaName(cname);
         }
 
+        atClassObject2(cname);
+        exprType = CLASS;
+        arrayDim = 0;
+        className = "java/lang/Class";
+    }
+
+    /* MemberCodeGen overrides this method.
+     */
+    protected void atClassObject2(String cname) throws CompileError {
         int start = bytecode.currentPc();
         bytecode.addLdc(cname);
         bytecode.addInvokestatic("java.lang.Class", "forName",
@@ -1581,10 +1590,6 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
                                  + "Ljava/lang/NoClassDefFoundError;");
         bytecode.addOpcode(ATHROW);
         bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
-
-        exprType = CLASS;
-        arrayDim = 0;
-        className = "java/lang/Class";
     }
 
     public void atArrayRead(ASTree array, ASTree index)
index 9446f42b7056d00c61521e67d82f231428ee6c75..225844f96c066e69ef9af2af574e1474cd958bb7 100644 (file)
@@ -24,9 +24,13 @@ import java.util.ArrayList;
 /* Code generator methods depending on javassist.* classes.
  */
 public class MemberCodeGen extends CodeGen {
+    public static final int JAVA5_VER = 49;
+    public static final int JAVA6_VER = 50;
+
     protected MemberResolver resolver;
     protected CtClass   thisClass;
     protected MethodInfo thisMethod;
+    protected int version;      // the major version of a class file.
 
     protected boolean resultStatic;
 
@@ -35,6 +39,11 @@ public class MemberCodeGen extends CodeGen {
         resolver = new MemberResolver(cp);
         thisClass = cc;
         thisMethod = null;
+        ClassFile cf = cc.getClassFile2();
+        if (cf == null)
+            version = 0;
+        else
+            version = cf.getMajorVersion();
     }
 
     /**
@@ -71,17 +80,27 @@ public class MemberCodeGen extends CodeGen {
 
     static class JsrHook extends ReturnHook {
         ArrayList jsrList;
+        CodeGen cgen;
         int var;
 
         JsrHook(CodeGen gen) {
             super(gen);
             jsrList = new ArrayList();
-            var = gen.getMaxLocals();
-            gen.incMaxLocals(1);
+            cgen = gen;
+            var = -1;
+        }
+
+        private int getVar(int size) {
+            if (var < 0) {
+                var = cgen.getMaxLocals();
+                cgen.incMaxLocals(size);
+            }
+
+            return var;
         }
 
         private void jsrJmp(Bytecode b) {
-            b.addOpcode(JSR);
+            b.addOpcode(Opcode.GOTO);
             jsrList.add(new Integer(b.currentPc()));
             b.addIndex(0);
         }
@@ -92,27 +111,27 @@ public class MemberCodeGen extends CodeGen {
                 jsrJmp(b);
                 break;
             case ARETURN :
-                b.addAstore(var);
+                b.addAstore(getVar(1));
                 jsrJmp(b);
                 b.addAload(var);
                 break;
             case IRETURN :
-                b.addIstore(var);
+                b.addIstore(getVar(1));
                 jsrJmp(b);
                 b.addIload(var);
                 break;
             case LRETURN :
-                b.addLstore(var);
+                b.addLstore(getVar(2));
                 jsrJmp(b);
                 b.addLload(var);
                 break;
             case DRETURN :
-                b.addDstore(var);
+                b.addDstore(getVar(2));
                 jsrJmp(b);
                 b.addDload(var);
                 break;
             case FRETURN :
-                b.addFstore(var);
+                b.addFstore(getVar(1));
                 jsrJmp(b);
                 b.addFload(var);
                 break;
@@ -177,7 +196,6 @@ public class MemberCodeGen extends CodeGen {
             }
         }
 
-        int pcFinally = -1;
         if (finallyBlock != null) {
             jsrHook.remove(this);
             // catch (any) clause
@@ -185,38 +203,42 @@ public class MemberCodeGen extends CodeGen {
             bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0);
             bc.growStack(1);
             bc.addAstore(var);
-            bc.addOpcode(JSR);
-            int pcJsrIndex = bc.currentPc();
-            bc.addIndex(0);       // correct later
-            bc.addAload(var);
-            bc.addOpcode(ATHROW);
-
-            // finally clause
-            pcFinally = bc.currentPc();
-            bc.write16bit(pcJsrIndex, pcFinally - pcJsrIndex + 1);
-            int retAddr = getMaxLocals();
-            incMaxLocals(1);
-            bc.growStack(1);    // return address
-            bc.addAstore(retAddr);
             hasReturned = false;
             finallyBlock.accept(this);
             if (!hasReturned) {
-                bc.addOpcode(RET);
-                bc.add(retAddr);
+                bc.addAload(var);
+                bc.addOpcode(ATHROW);
             }
+
+            addFinally(jsrHook.jsrList, finallyBlock);
         }
 
         int pcEnd = bc.currentPc();
         patchGoto(gotoList, pcEnd);
+        hasReturned = !tryNotReturn;
         if (finallyBlock != null) {
-            patchGoto(jsrHook.jsrList, pcFinally);
-            if (tryNotReturn) {
-                bc.addOpcode(JSR);
-                bc.addIndex(pcFinally - pcEnd);
-            }
+            if (tryNotReturn)
+                finallyBlock.accept(this);
         }
+    }
 
-        hasReturned = !tryNotReturn;
+    /**
+     * Adds a finally clause for earch return statement.
+     */
+    private void addFinally(ArrayList returnList, Stmnt finallyBlock)
+        throws CompileError
+    {
+        Bytecode bc = bytecode;
+        int n = returnList.size();
+        for (int i = 0; i < n; ++i) {
+            int pc = ((Integer)returnList.get(i)).intValue();
+            bc.write16bit(pc, bc.currentPc() - pc + 1);
+            finallyBlock.accept(this);
+            if (!hasReturned) {
+                bc.addOpcode(Opcode.GOTO);
+                bc.addIndex(pc + 3 - bc.currentPc());
+            }
+        }
     }
 
     public void atNewExpr(NewExpr expr) throws CompileError {
@@ -895,6 +917,10 @@ public class MemberCodeGen extends CodeGen {
         return cp.addFieldrefInfo(ci, name, type);
     }
 
+    protected void atClassObject2(String cname) throws CompileError {
+        super.atClassObject2(cname);
+    }
+
     protected void atFieldPlusPlus(int token, boolean isPost,
                                    ASTree oprand, Expr expr, boolean doDup)
         throws CompileError
index 8776d8f89ae3c1e7d16489b3fcb81d18fe65048c..8fe123cca890c6786f5fa1ea3a8359e19150154b 100644 (file)
@@ -23,7 +23,7 @@ Shigeru Chiba
 <br>3. <a href="#load">Class loader</a>
 <br>4. <a href="tutorial2.html#intro">Introspection and customization</a>
 <br>5. <a href="tutorial3.html#intro">Bytecode level API</a>
-
+<br>6. <a href="tutorial3.html#generics">Generics</a>
 </ul>
 
 <p><br>
index 657e629b52da819b42c89d4184522984ece285af..1c4afe7374b70d6bf610bccea883473023ee2d55 100644 (file)
@@ -22,6 +22,7 @@
 
 </ul>
 
+<p><a href="#generics">6. Generics</a>
 
 <p><br>
 
@@ -217,6 +218,70 @@ on those objects.  For more details, see the javadoc manual
 of <code>javassist.bytecode.AnnotationsAttribute</code> class
 and the <code>javassist.bytecode.annotation</code> package.
 
+<p>Javassist also let you access annotations by the higher-level
+API.
+If you want to access annotations through <code>CtClass</code>,
+call <code>getAnnotations()</code> in <code>CtClass</code> or
+<code>CtBehavior</code>.
+
+<p><br>
+
+<h2><a name="generics">6. Generics</a></h2>
+
+<p>The lower-level API of Javassist fully supports generics
+introduced by Java 5.  On the other hand, the higher-level
+API such as <code>CtClass</code> does not directly support
+generics.  However, this is not a serious problem for bytecode
+transformation.
+
+<p>The generics of Java is implemented by the erasure technique.
+After compilation, all type parameters are dropped off.  For
+example, suppose that your source code declare a parameterized
+type <code>Vector&lt;String&gt;</code>:
+
+<ul><pre>
+Vector&lt;String&gt; v = new Vector&lt;String&gt();
+  :
+String s = v.get(0);
+</pre></ul>
+
+<p>The compiled bytecode is equivalent to the following code:
+
+<ul><pre>
+Vector v = new Vector();
+  :
+String s = (String)v.get(0);
+</pre></ul>
+
+<p>So when you write a bytecode transformer, you can just drop
+off all type parameters.  For example, if you have a class:
+
+<ul><pre>
+public class Wrapper&lt;T&gt; {
+  T value;
+  public Wrapper(T t) { value = t; }
+}
+</pre></ul>
+
+<p>and want to add an interface <code>Getter&lt;T&gt;</code> to the
+class <code>Wrapper&lt;T&gt;</code>:
+
+<ul><pre>
+public interface Getter&lt;T&gt; {
+  T get();
+}
+</pre></ul>
+
+<p>Then the interface you really have to add is <code>Getter</code>
+(the type parameters <code>&lt;T&gt;<code> drops off)
+and the method you also have to add to the <code>Wrapper</code>
+class is this simple one:
+
+<ul><pre>
+public Object get() { return value; }
+</pre></ul>
+
+<p>Note that no type parameters are necessary.
 
 <p><br>