diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-05-12 14:45:10 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-05-12 14:45:10 +0000 |
commit | c2d6bdf673d0fde9b947ae23094cd76493d5ca88 (patch) | |
tree | c0f5dbd5cbb7acf859f51b14ee7e08b4358e8aed | |
parent | 4958b9a45ab284be8d5927d8cc96df14c64d02c1 (diff) | |
download | javassist-c2d6bdf673d0fde9b947ae23094cd76493d5ca88.tar.gz javassist-c2d6bdf673d0fde9b947ae23094cd76493d5ca88.zip |
changed the implementation of try statements so that jsr/ret will not be used anymore.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@371 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
-rw-r--r-- | src/main/javassist/bytecode/ClassFile.java | 8 | ||||
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 13 | ||||
-rw-r--r-- | src/main/javassist/compiler/MemberCodeGen.java | 86 | ||||
-rw-r--r-- | tutorial/tutorial.html | 2 | ||||
-rw-r--r-- | tutorial/tutorial3.html | 65 |
5 files changed, 138 insertions, 36 deletions
diff --git a/src/main/javassist/bytecode/ClassFile.java b/src/main/javassist/bytecode/ClassFile.java index 50b6cacd..e28e6c63 100644 --- a/src/main/javassist/bytecode/ClassFile.java +++ b/src/main/javassist/bytecode/ClassFile.java @@ -46,6 +46,12 @@ public final class ClassFile { 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. */ public ClassFile(DataInputStream in) throws IOException { @@ -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(); diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java index c69005f9..dfcddc4e 100644 --- a/src/main/javassist/compiler/CodeGen.java +++ b/src/main/javassist/compiler/CodeGen.java @@ -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) diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java index 9446f42b..225844f9 100644 --- a/src/main/javassist/compiler/MemberCodeGen.java +++ b/src/main/javassist/compiler/MemberCodeGen.java @@ -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 diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html index 8776d8f8..8fe123cc 100644 --- a/tutorial/tutorial.html +++ b/tutorial/tutorial.html @@ -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> diff --git a/tutorial/tutorial3.html b/tutorial/tutorial3.html index 657e629b..1c4afe73 100644 --- a/tutorial/tutorial3.html +++ b/tutorial/tutorial3.html @@ -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<String></code>: + +<ul><pre> +Vector<String> v = new Vector<String>(); + : +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<T> { + T value; + public Wrapper(T t) { value = t; } +} +</pre></ul> + +<p>and want to add an interface <code>Getter<T></code> to the +class <code>Wrapper<T></code>: + +<ul><pre> +public interface Getter<T> { + T get(); +} +</pre></ul> + +<p>Then the interface you really have to add is <code>Getter</code> +(the type parameters <code><T><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> |