<p>-version 3.16
<ul>
- <li>JIRA JASSIST-126, 127, 144, 145, 146, 147, 149.
+ <li>JIRA JASSIST-126, 127, 144, 145, 146, 147, 149, 150, 153, 155.
<li><code>javassist.bytecode.analysis.ControlFlow</code> was added.
</ul>
<target name="runtest" depends="test-compile">
<junit fork="true" printsummary="true" dir="${test.run.dir}">
+ <jvmarg value="-XX:-FailOverToOldVerifier" />
<classpath refid="test.classpath"/>
<formatter type="xml" extension=".xml"/>
<test name="javassist.JvstTest" outfile="TestLog" />
public abstract String getLongName();
/**
- * Returns the MethodInfo representing this method/constructor in the
+ * Returns the <code>MethodInfo</code> representing this method/constructor in the
* class file.
+ *
+ * <p>If you modify the bytecode through the returned
+ * <code>MethodInfo</code> object, you might have to explicitly
+ * rebuild a stack map table. Javassist does not automatically
+ * rebuild it for avoiding unnecessary rebuilding.
+ *
+ * @see javassist.bytecode.MethodInfo#rebuildStackMap(ClassPool)
*/
public MethodInfo getMethodInfo() {
declaringClass.checkModify();
}
/**
- * Returns the MethodInfo representing the method/constructor in the
+ * Returns the <code>MethodInfo</code> representing the method/constructor in the
* class file (read only).
* Normal applications do not need calling this method. Use
* <code>getMethodInfo()</code>.
public abstract class CtClass {
protected String qualifiedName;
+ /**
+ * If the value of this field is not null, then all class
+ * files modified by Javassist are saved under the directory
+ * specified by this variable. For example, if the value is
+ * <code>"./debug"</code>, then all class files are saved
+ * there. The directory name must not end with a directory
+ * separator such as <code>/</code>.
+ *
+ * <p>The default value is null.
+ *
+ * @see #debugWriteFile(String)
+ * @since 3.16
+ */
+ public static String debugDump = null;
+
/**
* The version number of this release.
*/
*/
public static void main(String[] args) {
System.out.println("Javassist version " + CtClass.version);
- System.out.println("Copyright (C) 1999-2011 Shigeru Chiba."
+ System.out.println("Copyright (C) 1999-2012 Shigeru Chiba."
+ " All Rights Reserved.");
}
public void writeFile(String directoryName)
throws CannotCompileException, IOException
{
+ DataOutputStream out = makeFileOutput(directoryName);
+ try {
+ toBytecode(out);
+ }
+ finally {
+ out.close();
+ }
+ }
+
+ protected DataOutputStream makeFileOutput(String directoryName) {
String classname = getName();
String filename = directoryName + File.separatorChar
+ classname.replace('.', File.separatorChar) + ".class";
new File(dir).mkdirs();
}
- DataOutputStream out
- = new DataOutputStream(new BufferedOutputStream(
- new DelayedFileOutputStream(filename)));
- try {
- toBytecode(out);
- }
- finally {
- out.close();
- }
+ return new DataOutputStream(new BufferedOutputStream(
+ new DelayedFileOutputStream(filename)));
}
/**
modifyClassConstructor(cf);
modifyConstructors(cf);
+ if (debugDump != null)
+ dumpClassFile(cf);
+
cf.write(out);
out.flush();
fieldInitializers = null;
}
}
+ private void dumpClassFile(ClassFile cf) throws IOException {
+ DataOutputStream dump = makeFileOutput(debugDump);
+ try {
+ cf.write(dump);
+ }
+ finally {
+ dump.close();
+ }
+ }
+
/* See also checkModified()
*/
private void checkPruned(String method) {
int acc = body.getAccessFlags();
body.setAccessFlags(AccessFlag.setPrivate(acc));
body.addAttribute(new SyntheticAttribute(classfile.getConstPool()));
- // a stack map is copied. rebuilding it is not needed.
+ // a stack map is copied. rebuilding it is not needed.
classfile.addMethod(body);
bodies.put(src, bodyname);
CtMember.Cache cache = clazz.hasMemberCache();
/**
* The major version number of class files created
- * from scratch. The default value is 47 (JDK 1.3)
- * or 49 (JDK 1.5) if the JVM supports <code>java.lang.StringBuilder</code>.
+ * from scratch. The default value is 47 (JDK 1.3).
+ * It is 49 (JDK 1.5)
+ * if the JVM supports <code>java.lang.StringBuilder</code>.
+ * It is 50 (JDK 1.6)
+ * if the JVM supports <code>java.util.zip.DeflaterInputStream</code>.
*/
public static int MAJOR_VERSION = JAVA_3;
try {
Class.forName("java.lang.StringBuilder");
MAJOR_VERSION = JAVA_5;
+ Class.forName("java.util.zip.DeflaterInputStream");
+ MAJOR_VERSION = JAVA_6;
}
catch (Throwable t) {}
}
}
/**
- * Writes a class file represened by this object into an output stream.
+ * Writes a class file represented by this object into an output stream.
*/
public void write(DataOutputStream out) throws IOException {
int i, n;
package javassist.tools.reflect;
+import java.util.Iterator;
import javassist.*;
import javassist.CtMethod.ConstParameter;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.MethodInfo;
/**
* The class implementing the behavioral reflection mechanism.
= "javassist.tools.reflect.Sample is not found or broken.";
try {
CtClass c = classPool.get("javassist.tools.reflect.Sample");
+ rebuildClassFile(c.getClassFile());
trapMethod = c.getDeclaredMethod("trap");
trapStaticMethod = c.getDeclaredMethod("trapStatic");
trapRead = c.getDeclaredMethod("trapRead");
}
catch (NotFoundException e) {
throw new RuntimeException(msg);
+ } catch (BadBytecode e) {
+ throw new RuntimeException(msg);
}
}
}
}
}
+
+ public void rebuildClassFile(ClassFile cf) throws BadBytecode {
+ if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_6)
+ return;
+
+ Iterator methods = cf.getMethods().iterator();
+ while (methods.hasNext()) {
+ MethodInfo mi = (MethodInfo)methods.next();
+ mi.rebuildStackMap(classPool);
+ }
+ }
}
CtMethod m1 = cc.getDeclaredMethod("run");
m1.getMethodInfo().getCodeAttribute().insertLocalVar(2, 20);
+ m1.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile());
CtMethod m2 = cc.getDeclaredMethod("run2");
m2.getMethodInfo().getCodeAttribute().insertLocalVar(2, 0x101);
+ m2.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile());
cc.writeFile();
Object obj = make(cc.getName());
}
}
});
+ // m3.getMethodInfo2().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
cc.writeFile();
Object obj = make(cc.getName());
<br>6. <a href="tutorial3.html#generics">Generics</a>
<br>7. <a href="tutorial3.html#varargs">Varargs</a>
<br>8. <a href="tutorial3.html#j2me">J2ME</a>
+<br>9. <a href="tutorial3.html#debug">Debug</a>
</ul>
<p><br>
<hr>
Java(TM) is a trademark of Sun Microsystems, Inc.<br>
-Copyright (C) 2000-2010 by Shigeru Chiba, All rights reserved.
+Copyright (C) 2000-2012 by Shigeru Chiba, All rights reserved.
</body>
</html>
<p><a href="#j2me">8. J2ME</a>
+<p><a href="#debug">9. Debug</a>
+
<p><br>
<a name="intro">
<p><br>
+<h2><a name="debug">9. Debug</h2>
+
+<p>Set <code>CtClass.debugDump</code> to a directory name.
+Then all class files modified and generated by Javassist are saved in that
+directory. To stop this, set <code>CtClass.debugDump</code> to null.
+The default value is null.
+
+<p>For example,
+
+<ul><pre>
+CtClass.debugDump = "./dump";
+</pre></ul>
+
+<p>All modified class files are saved in <code>./dump</code>.
+
+<p><br>
+
<a href="tutorial2.html">Previous page</a>
<hr>
Java(TM) is a trademark of Sun Microsystems, Inc.<br>
-Copyright (C) 2000-2010 by Shigeru Chiba, All rights reserved.
+Copyright (C) 2000-2012 by Shigeru Chiba, All rights reserved.
</body>
</html>