</HEAD>
<body>
-<h1>Javassist version 2</h1>
+<h1>Javassist version 3</h1>
<h3>Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.</h3>
<h2>Changes</h2>
-<p>- version 3.0 RC1
+<p>- version 3.0 beta in May 18th, 2004.
<ul>
<li>The ClassPool framework has been redesigned.
<li>CtClass.getURL() and javassist.ClassPath.find() has been added.
<li>CtBehavior.insertAt() has been added.
<li>CtClass.detach() has been added.
+ <li>CodeAttribute.computeMaxStack() has been added.
</ul>
<p>- version 2.6 in August, 2003.
Remy Sanlaville, Muga Nishizawa, Alexey Loubyansky, Saori Oki,
Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos,
Denis Taye, Colin Sampaleanu, Robert Bialek, Asato Shimotaki,
-Howard Lewis Ship, Richard Jones, and Marjan Sterjev
+Howard Lewis Ship, Richard Jones, Marjan Sterjev,
+Bruce McDonald, and Mark Brennan
for their contributions.
<p><br>
/**
* The version number of this release.
*/
- public static final String version = "3.0 beta";
+ public static final String version = "3.0 beta 3";
/**
* Prints the version number and the copyright notice.
addLdc(constPool.addIntegerInfo(n));
}
+ /**
+ * Appends an instruction for pushing zero or null on the stack.
+ * If the type is void, this method does not append any instruction.
+ *
+ * @param type the type of the zero value (or null).
+ */
+ public void addConstZero(CtClass type) {
+ if (type.isPrimitive()) {
+ if (type == CtClass.longType)
+ addOpcode(LCONST_0);
+ else if (type == CtClass.floatType)
+ addOpcode(FCONST_0);
+ else if (type == CtClass.doubleType)
+ addOpcode(DCONST_0);
+ else if (type == CtClass.voidType)
+ throw new RuntimeException("void type?");
+ else
+ addOpcode(ICONST_0);
+ }
+ else
+ addOpcode(ACONST_NULL);
+ }
+
/**
* Appends ILOAD or (WIDE) ILOAD_<n>
*
addLstore(n);
return 2;
}
- else if(type == CtClass.floatType)
+ else if (type == CtClass.floatType)
addFstore(n);
- else if(type == CtClass.doubleType) {
+ else if (type == CtClass.doubleType) {
addDstore(n);
return 2;
}
return classname.replace('/', '.');
}
- /**
- * Converts to a classname from a descriptor
- */
- public static String fromDescriptor(String descriptor)
- {
- String newname = toJavaName(descriptor).substring(1);
- return newname.substring(0, newname.length() - 1);
- }
-
- /**
- * Converts to a descriptor from a classname
- */
- public static String toDescriptor(String classname)
- {
- return "L" + toJvmName(classname) + ";";
- }
+ /**
+ * Converts to a classname from a descriptor
+ */
+ public static String fromDescriptor(String descriptor) {
+ String newname = toJavaName(descriptor).substring(1);
+ return newname.substring(0, newname.length() - 1);
+ }
+
+ /**
+ * Converts to a descriptor from a classname
+ */
+ public static String toDescriptor(String classname) {
+ return "L" + toJvmName(classname) + ";";
+ }
/**
* Returns the internal representation of the class name in the
return sbuf.toString();
}
-
-
private static void toDescriptor(StringBuffer desc, CtClass type) {
if (type.isArray()) {
desc.append('[');
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
jc.recordLocalVariables(ca, pos);
+
+ bytecode.addConstZero(retType);
+ bytecode.addStore(retVar, retType); // initialize $_
+
jc.compileStmnt(statement);
bytecode.addLoad(retVar, retType);
/* Is $_ included in the source code?
*/
boolean included = checkResultValue(retType, statement);
+ if (read)
+ included = true;
int retVar = jc.recordReturnType(retType, included);
if (read)
Bytecode bytecode = jc.getBytecode();
storeStack(params, isStatic(), paramVar, bytecode);
jc.recordLocalVariables(ca, pos);
+
+ if (included)
+ if (retType == CtClass.voidType) {
+ bytecode.addOpcode(ACONST_NULL);
+ bytecode.addAstore(retVar);
+ }
+ else {
+ bytecode.addConstZero(retType);
+ bytecode.addStore(retVar, retType); // initialize $_
+ }
+
jc.compileStmnt(statement);
if (read)
bytecode.addLoad(retVar, retType);
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
jc.recordLocalVariables(ca, pos);
+
+ bytecode.addConstZero(retType);
+ bytecode.addStore(retVar, retType); // initialize $_
+
jc.compileStmnt(statement);
bytecode.addLoad(retVar, retType);
Bytecode bytecode = jc.getBytecode();
storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
jc.recordLocalVariables(ca, pos);
+
+ if (retType != CtClass.voidType) {
+ bytecode.addConstZero(retType);
+ bytecode.addStore(retVar, retType); // initialize $_
+ }
+
jc.compileStmnt(statement);
if (retType != CtClass.voidType)
bytecode.addLoad(retVar, retType);
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
jc.recordLocalVariables(ca, pos);
+
+ bytecode.addConstZero(newType);
+ bytecode.addStore(retVar, newType); // initialize $_
+
jc.compileStmnt(statement);
bytecode.addAload(retVar);
<p>The default <code>ClassPool</code> returned
by a static method <code>ClassPool.getDefault()</code>
searches the same path that the underlying JVM (Java virtual machine) has.
-The users can expand this class search path if needed.
+<em>If a program is running on a web application server such as JBoss and Tomcat,
+the <code>ClassPool</code> object may not be able to find user classes</em>
+since such a web application server uses multiple class loaders as well as
+the system class loader. In that case, an additional class path must be
+registered to the <code>ClassPool</code>. Suppose that <code>pool</code>
+refers to a <code>ClassPool</code> object:
+
+<ul><pre>
+pool.insertClassPath(new ClassClassPath(this.getClass()));
+</pre></ul>
+
+<p>
+This statement registers the class path that was used for loading
+the class of the object that <code>this</code> referes to.
+You can use any <code>Class</code> object as an argument instead of
+<code>this.getClass()</code>. The class path used for loading the
+class represented by that <code>Class</code> object is registered.
+
+
+<p>
+You can register a directory name as the class search path.
For example, the following code adds a directory
<code>/usr/local/javalib</code>
to the search path: