<h1>Javassist version 2</h1>
-<h3>in May, 2003.
+<h3>in July, 2003.
<br>Copyright (C) 2000-2003 by Shigeru Chiba, All rights reserved.</h3>
<p><br></p>
<h2>Changes</h2>
+<p>- version 2.6 in July, 2003.
+
+<ul>
+ <li>CtConstructor.setBody() now works for class initializers.
+ <li>CtNewMethod.delegator() now works for static methods.
+</ul>
+
<p>- version 2.5.1 in May, 2003.
<br>Simple changes for integration with JBoss AOP
<ul>
<h2>Acknowledgments</h2>
<p>The development of this software is sponsored in part by the PRESTO
-programs of <a href="http://www.jst.go.jp/">Japan
+and CREST programs of <a href="http://www.jst.go.jp/">Japan
Science and Technology Corporation</a>.
<p>I'd like to thank Michiaki Tatsubori, Johan Cloetens,
Fabian Crabus, Bo Norregaard Jorgensen, Bob Lee, Bill Burke,
Remy Sanlaville, Muga Nishizawa, Alexey Loubyansky, Saori Oki,
Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos,
-Denis Taye, and Colin Sampaleanu
+Denis Taye, Colin Sampaleanu, and Robert Bialek
for their contributions.
<p><br>
Specification-Title: Javassist\r
Created-By: Shigeru Chiba, Tokyo Institute of Technology\r
Specification-Vendor: Shigeru Chiba, Tokyo Institute of Technology\r
-Specification-Version: 2.5.1\r
+Specification-Version: 2.6\r
Name: javassist/\r
\r
public interface ClassPath {
/**
* Opens a class file.
+ * This method may be called just to examine whether the class file
+ * exists as well as to read the contents of the file.
*
* <p>This method can return null if the specified class file is not
* found. If null is returned, the next search path is examined.
* so that the search is terminated.
*
* <p>This method should not modify the contents of the class file.
+ * Use <code>javassist.Translator</code> for modification.
*
* @param classname a fully-qualified class name
* @return the input stream for reading a class file
+ * @see javassist.Translator
*/
InputStream openClassfile(String classname) throws NotFoundException;
{
return (CtClass)classes.get(classname);
}
+
/**
* Creates a class pool.
*
/**
* The version number of this release.
*/
- public static final String version = "2.5.1";
+ public static final String version = "2.6";
static final String javaLangObject = "java.lang.Object";
/**
* Obtains the class object representing the superclass of the
* class.
- * It returns null if the class is <code>java.lang.Object</code>.
+ * It returns null if this object represents the
+ * <code>java.lang.Object</code> class and thus it does not have
+ * the super class.
*/
public CtClass getSuperclass() throws NotFoundException {
return null;
*/
public void setBody(String src) throws CannotCompileException {
if (src == null)
- src = "super();";
+ if (isClassInitializer())
+ src = ";";
+ else
+ src = "super();";
super.setBody(src);
}
CtClass[] params = delegate.getParameterTypes();
int s;
if (isStatic) {
- s = code.addLoadParameters(params);
+ s = code.addLoadParameters(params, 0);
code.addInvokestatic(deleClass, methodName, desc);
}
else {
code.addLoad(0, deleClass);
- s = code.addLoadParameters(params);
+ s = code.addLoadParameters(params, 1);
code.addInvokespecial(deleClass, methodName, desc);
}
code.addInvokespecial(superclazz, "<init>", "()V");
}
else if (howToCallSuper == PASS_PARAMS) {
- stacksize = code.addLoadParameters(parameters) + 1;
+ stacksize = code.addLoadParameters(parameters, 1) + 1;
code.addInvokespecial(superclazz, "<init>",
Descriptor.ofConstructor(parameters));
}
/**
* Appends instructions for loading all the parameters onto the
* operand stack.
+ *
+ * @param offset the index of the first parameter. It is 0
+ * if the method is static. Otherwise, it is 1.
*/
- public int addLoadParameters(CtClass[] params) {
+ public int addLoadParameters(CtClass[] params, int offset) {
int stacksize = 0;
if (params != null) {
int n = params.length;
for (int i = 0; i < n; ++i)
- stacksize += addLoad(stacksize + 1, params[i]);
+ stacksize += addLoad(stacksize + offset, params[i]);
}
return stacksize;
public int getTag() { return tag; }
public void renameClass(ConstPool cp, String oldName, String newName) {
- if (cp.getUtf8Info(name).equals(oldName))
+ String nameStr = cp.getUtf8Info(name);
+ if (nameStr.equals(oldName))
name = cp.addUtf8Info(newName);
+ else if (nameStr.charAt(0) == '[') {
+ String nameStr2 = Descriptor.rename(nameStr, oldName, newName);
+ if (nameStr != nameStr2)
+ name = cp.addUtf8Info(nameStr2);
+ }
}
public void renameClass(ConstPool cp, Map map) {
String oldName = cp.getUtf8Info(name);
- String newName = (String)map.get(oldName);
- if (newName != null && !newName.equals(oldName))
- name = cp.addUtf8Info(newName);
+ if (oldName.charAt(0) == '[') {
+ String newName = Descriptor.rename(oldName, map);
+ if (oldName != newName)
+ name = cp.addUtf8Info(newName);
+ }
+ else {
+ String newName = (String)map.get(oldName);
+ if (newName != null && !newName.equals(oldName))
+ name = cp.addUtf8Info(newName);
+ }
}
public int copy(ConstPool src, ConstPool dest, Map map) {
method.getReturn().getType() == VOID);
}
+ /**
+ * @param isCons true if super() must be called.
+ * false if the method is a class initializer.
+ */
public void atMethodBody(Stmnt s, boolean isCons, boolean isVoid)
throws CompileError
{
Parser p = new Parser(new Lex(src));
SymbolTable stb = new SymbolTable(stable);
Stmnt s = p.parseStatement(stb);
- gen.atMethodBody(s, method instanceof CtConstructor, isVoid);
+ boolean callSuper = false;
+ if (method instanceof CtConstructor)
+ callSuper = !((CtConstructor)method).isClassInitializer();
+
+ gen.atMethodBody(s, callSuper, isVoid);
}
return bytecode;
version of class loader but they can also use a class loader provided
by Javassist.
+<p>Using a class loader is not easy. Especially if you are a beginner,
+you should separate your program into an application program and an
+instrumentation program and each of the two programs should be loaded
+by a single class loader. You should
+avoid loading part of the application program with the default class loader
+and the rest of the program with a user-defined class loader.
+
<p><br>
<h3>4.1 Using <code>javassist.Loader</code></h3>
<code>L1</code> whereas the type of <code>this</code> is the class
<code>Point</code> loaded by <code>L2</code>.
+<p><code>javassist.Loader</code> searches for classes in a different
+order from <code>java.lang.ClassLoader</code>.
+<code>ClassLoader</code> first delegates the loading operations to
+the parent class loader and then attempts to load the classes
+only if the parent class loader cannot find them.
+On the other hand,
+<code>javassist.Loader</code> attempts
+to load the classes before delegating to the parent class loader.
+It delegates only if:
+
+<ul><li>the classes are not found by using the <code>ClassPool</code>
+object, or
+
+<p><li>the classes have been specified by using
+<code>delegateLoadingOf()</code>
+to be loaded by the parent class loader.
+</ul>
+
+<p>This search order allows loading modified classes by Javassist into
+the JVM. However, it delegates to the parent class loader if it fails
+to find modified classes for some reason. Once a class is loaded by
+the parent class loader, the other classes used by that class will be
+also loaded without modification by the parent class loader. <em>If your
+program fails to load a modified class,</em> you should make sure whether
+all the classes using that class have been loaded by
+<code>javassist.Loader</code>.
+
<p><br>
<h3>4.2 Writing a class loader</h3>