aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-05-12 14:45:10 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-05-12 14:45:10 +0000
commitc2d6bdf673d0fde9b947ae23094cd76493d5ca88 (patch)
treec0f5dbd5cbb7acf859f51b14ee7e08b4358e8aed
parent4958b9a45ab284be8d5927d8cc96df14c64d02c1 (diff)
downloadjavassist-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.java8
-rw-r--r--src/main/javassist/compiler/CodeGen.java13
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java86
-rw-r--r--tutorial/tutorial.html2
-rw-r--r--tutorial/tutorial3.html65
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&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>