aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Readme.html2
-rw-r--r--src/main/javassist/CtClassType.java8
-rw-r--r--src/main/javassist/bytecode/AccessFlag.java6
-rw-r--r--src/main/javassist/bytecode/AttributeInfo.java10
-rw-r--r--src/main/javassist/bytecode/CodeAttribute.java8
-rw-r--r--src/main/javassist/bytecode/CodeIterator.java6
-rw-r--r--src/main/javassist/bytecode/EnclosingMethodAttribute.java111
-rw-r--r--src/main/javassist/bytecode/FieldInfo.java2
-rw-r--r--src/main/javassist/bytecode/LocalVariableAttribute.java50
-rw-r--r--src/main/javassist/bytecode/MethodInfo.java2
-rw-r--r--src/main/javassist/bytecode/SignatureAttribute.java70
-rw-r--r--tutorial/tutorial.html19
-rw-r--r--tutorial/tutorial3.html8
13 files changed, 284 insertions, 18 deletions
diff --git a/Readme.html b/Readme.html
index 59b76998..1d89d316 100644
--- a/Readme.html
+++ b/Readme.html
@@ -556,7 +556,7 @@ Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos,
Denis Taye, Colin Sampaleanu, Robert Bialek, Asato Shimotaki,
Howard Lewis Ship, Richard Jones, Marjan Sterjev,
Bruce McDonald, Mark Brennan, Vlad Skarzhevskyy,
-and Brett Randall
+Brett Randall, and Tsuyoshi Murakami
for their contributions.
<p><br>
diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java
index 4834ae8a..2949bcba 100644
--- a/src/main/javassist/CtClassType.java
+++ b/src/main/javassist/CtClassType.java
@@ -830,6 +830,7 @@ class CtClassType extends CtClass {
modifyConstructors(cf);
cf.write(out);
out.flush();
+ fieldInitializers = null;
}
else
classPool.writeClassfile(getName(), out);
@@ -844,9 +845,12 @@ class CtClassType extends CtClass {
}
}
- protected void modifyClassConstructor(ClassFile cf)
+ private void modifyClassConstructor(ClassFile cf)
throws CannotCompileException, NotFoundException
{
+ if (fieldInitializers == null)
+ return;
+
Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
Javac jv = new Javac(code, this);
int stacksize = 0;
@@ -903,7 +907,7 @@ class CtClassType extends CtClass {
}
}
- protected void modifyConstructors(ClassFile cf)
+ private void modifyConstructors(ClassFile cf)
throws CannotCompileException, NotFoundException
{
if (fieldInitializers == null)
diff --git a/src/main/javassist/bytecode/AccessFlag.java b/src/main/javassist/bytecode/AccessFlag.java
index 79e75cdf..6f18e096 100644
--- a/src/main/javassist/bytecode/AccessFlag.java
+++ b/src/main/javassist/bytecode/AccessFlag.java
@@ -27,11 +27,17 @@ public class AccessFlag {
public static final int FINAL = 0x0010;
public static final int SYNCHRONIZED = 0x0020;
public static final int VOLATILE = 0x0040;
+ public static final int BRIDGE = 0x0040; // for method_info
public static final int TRANSIENT = 0x0080;
+ public static final int VARARGS = 0x0080; // for method_info
public static final int NATIVE = 0x0100;
public static final int INTERFACE = 0x0200;
public static final int ABSTRACT = 0x0400;
public static final int STRICT = 0x0800;
+ public static final int SYNTHETIC = 0x1000;
+ public static final int ANNOTATION = 0x2000;
+ public static final int ENUM = 0x4000;
+
public static final int SUPER = 0x0020;
// Note: 0x0020 is assigned to both ACC_SUPER and ACC_SYNCHRONIZED
diff --git a/src/main/javassist/bytecode/AttributeInfo.java b/src/main/javassist/bytecode/AttributeInfo.java
index 12ac5c75..28b01846 100644
--- a/src/main/javassist/bytecode/AttributeInfo.java
+++ b/src/main/javassist/bytecode/AttributeInfo.java
@@ -67,7 +67,8 @@ public class AttributeInfo {
}
static AttributeInfo read(ConstPool cp, DataInputStream in)
- throws IOException {
+ throws IOException
+ {
int name = in.readUnsignedShort();
String nameStr = cp.getUtf8Info(name);
if (nameStr.charAt(0) < 'L') {
@@ -77,6 +78,8 @@ public class AttributeInfo {
return new ConstantAttribute(cp, name, in);
else if (nameStr.equals(DeprecatedAttribute.tag))
return new DeprecatedAttribute(cp, name, in);
+ else if (nameStr.equals(EnclosingMethodAttribute.tag))
+ return new EnclosingMethodAttribute(cp, name, in);
else if (nameStr.equals(ExceptionsAttribute.tag))
return new ExceptionsAttribute(cp, name, in);
else if (nameStr.equals(InnerClassesAttribute.tag))
@@ -87,7 +90,8 @@ public class AttributeInfo {
*/
if (nameStr.equals(LineNumberAttribute.tag))
return new LineNumberAttribute(cp, name, in);
- else if (nameStr.equals(LocalVariableAttribute.tag))
+ else if (nameStr.equals(LocalVariableAttribute.tag)
+ || nameStr.equals(LocalVariableAttribute.typeTag))
return new LocalVariableAttribute(cp, name, in);
else if (nameStr.equals(AnnotationsAttribute.visibleTag)
|| nameStr.equals(AnnotationsAttribute.invisibleTag))
@@ -95,6 +99,8 @@ public class AttributeInfo {
else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag)
|| nameStr.equals(ParameterAnnotationsAttribute.invisibleTag))
return new ParameterAnnotationsAttribute(cp, name, in);
+ else if (nameStr.equals(SignatureAttribute.tag))
+ return new SignatureAttribute(cp, name, in);
else if (nameStr.equals(SourceFileAttribute.tag))
return new SourceFileAttribute(cp, name, in);
else if (nameStr.equals(SyntheticAttribute.tag))
diff --git a/src/main/javassist/bytecode/CodeAttribute.java b/src/main/javassist/bytecode/CodeAttribute.java
index ec1f9a58..4c7e27bb 100644
--- a/src/main/javassist/bytecode/CodeAttribute.java
+++ b/src/main/javassist/bytecode/CodeAttribute.java
@@ -81,7 +81,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
maxStack = src.getMaxStack();
maxLocals = src.getMaxLocals();
exceptions = src.getExceptionTable().copy(cp, classnames);
- info = src.copyCode(cp, classnames, exceptions);
+ info = src.copyCode(cp, classnames, exceptions, this);
attributes = new LinkedList();
/* Since an index into the source constant pool table may not
@@ -279,6 +279,8 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
/**
* Returns <code>attributes[]</code>.
* It returns a list of <code>AttributeInfo</code>.
+ * A new element can be added to the returned list
+ * and an existing element can be removed from the list.
*
* @see AttributeInfo
*/
@@ -299,7 +301,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
* Copies code.
*/
private byte[] copyCode(ConstPool destCp, Map classnames,
- ExceptionTable etable)
+ ExceptionTable etable, CodeAttribute destCa)
throws BadBytecode
{
int len = getCodeLength();
@@ -307,7 +309,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
newCode, destCp, classnames);
- return LdcEntry.doit(newCode, ldc, etable, this);
+ return LdcEntry.doit(newCode, ldc, etable, destCa);
}
private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
diff --git a/src/main/javassist/bytecode/CodeIterator.java b/src/main/javassist/bytecode/CodeIterator.java
index 90c2308b..03da568e 100644
--- a/src/main/javassist/bytecode/CodeIterator.java
+++ b/src/main/javassist/bytecode/CodeIterator.java
@@ -638,6 +638,12 @@ public class CodeIterator implements Opcode {
if (va != null)
va.shiftPc(where, gapLength, exclusive);
+ LocalVariableAttribute vta
+ = (LocalVariableAttribute)ca.getAttribute(
+ LocalVariableAttribute.typeTag);
+ if (vta != null)
+ vta.shiftPc(where, gapLength, exclusive);
+
return newcode;
}
diff --git a/src/main/javassist/bytecode/EnclosingMethodAttribute.java b/src/main/javassist/bytecode/EnclosingMethodAttribute.java
new file mode 100644
index 00000000..5ad92862
--- /dev/null
+++ b/src/main/javassist/bytecode/EnclosingMethodAttribute.java
@@ -0,0 +1,111 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.bytecode;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <code>EnclosingMethod_attribute</code>.
+ */
+public class EnclosingMethodAttribute extends AttributeInfo {
+ /**
+ * The name of this attribute <code>"EnclosingMethod"</code>.
+ */
+ public static final String tag = "EnclosingMethod";
+
+ EnclosingMethodAttribute(ConstPool cp, int n, DataInputStream in)
+ throws IOException
+ {
+ super(cp, n, in);
+ }
+
+ /**
+ * Constructs an EnclosingMethod attribute.
+ *
+ * @param cp a constant pool table.
+ * @param className the name of the innermost enclosing class.
+ * @param methodName the name of the enclosing method.
+ * @param methodDesc the descriptor of the enclosing method.
+ */
+ public EnclosingMethodAttribute(ConstPool cp, String className,
+ String methodName, String methodDesc) {
+ super(cp, tag);
+ int ci = cp.addClassInfo(className);
+ int ni = cp.addNameAndTypeInfo(methodName, methodDesc);
+ byte[] bvalue = new byte[4];
+ bvalue[0] = (byte)(ci >>> 8);
+ bvalue[1] = (byte)ci;
+ bvalue[2] = (byte)(ni >>> 8);
+ bvalue[3] = (byte)ni;
+ set(bvalue);
+ }
+
+ /**
+ * Returns the value of <code>class_index</code>.
+ */
+ public int classIndex() {
+ return ByteArray.readU16bit(get(), 0);
+ }
+
+ /**
+ * Returns the value of <code>method_index</code>.
+ */
+ public int methodIndex() {
+ return ByteArray.readU16bit(get(), 2);
+ }
+
+ /**
+ * Returns the name of the class specified by <code>class_index</code>.
+ */
+ public String className() {
+ return getConstPool().getClassInfo(classIndex());
+ }
+
+ /**
+ * Returns the method name specified by <code>method_index</code>.
+ */
+ public String methodName() {
+ ConstPool cp = getConstPool();
+ int mi = methodIndex();
+ int ni = cp.getNameAndTypeName(mi);
+ return cp.getUtf8Info(ni);
+ }
+
+ /**
+ * Returns the method descriptor specified by <code>method_index</code>.
+ */
+ public String methodDescriptor() {
+ ConstPool cp = getConstPool();
+ int mi = methodIndex();
+ int ti = cp.getNameAndTypeDescriptor(mi);
+ return cp.getUtf8Info(ti);
+ }
+
+ /**
+ * Makes a copy. Class names are replaced according to the
+ * given <code>Map</code> object.
+ *
+ * @param newCp the constant pool table used by the new copy.
+ * @param classnames pairs of replaced and substituted
+ * class names.
+ */
+ public AttributeInfo copy(ConstPool newCp, Map classnames) {
+ return new EnclosingMethodAttribute(newCp, className(),
+ methodName(), methodDescriptor());
+ }
+}
diff --git a/src/main/javassist/bytecode/FieldInfo.java b/src/main/javassist/bytecode/FieldInfo.java
index ba267fc9..8cdb1ae3 100644
--- a/src/main/javassist/bytecode/FieldInfo.java
+++ b/src/main/javassist/bytecode/FieldInfo.java
@@ -120,6 +120,8 @@ public final class FieldInfo {
/**
* Returns all the attributes.
+ * A new element can be added to the returned list
+ * and an existing element can be removed from the list.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
diff --git a/src/main/javassist/bytecode/LocalVariableAttribute.java b/src/main/javassist/bytecode/LocalVariableAttribute.java
index 735d609f..a88dfac7 100644
--- a/src/main/javassist/bytecode/LocalVariableAttribute.java
+++ b/src/main/javassist/bytecode/LocalVariableAttribute.java
@@ -20,7 +20,8 @@ import java.io.IOException;
import java.util.Map;
/**
- * <code>LocalVariableTable_attribute</code>.
+ * <code>LocalVariableTable_attribute</code> or
+ * <code>LocalVariableTypeTable_attribute</code>.
*/
public class LocalVariableAttribute extends AttributeInfo {
/**
@@ -28,6 +29,11 @@ public class LocalVariableAttribute extends AttributeInfo {
*/
public static final String tag = "LocalVariableTable";
+ /**
+ * The name of the attribute <code>"LocalVariableTypeTable"</code>.
+ */
+ public static final String typeTag = "LocalVariableTypeTable";
+
LocalVariableAttribute(ConstPool cp, int n, DataInputStream in)
throws IOException
{
@@ -85,7 +91,7 @@ public class LocalVariableAttribute extends AttributeInfo {
}
/**
- * Returns <code>local_variable_table[i].name_index</code>.
+ * Returns the value of <code>local_variable_table[i].name_index</code>.
* This represents the name of the local variable.
*
* @param i the i-th entry.
@@ -105,8 +111,14 @@ public class LocalVariableAttribute extends AttributeInfo {
}
/**
- * Returns <code>local_variable_table[i].descriptor_index</code>.
+ * Returns the value of
+ * <code>local_variable_table[i].descriptor_index</code>.
* This represents the type descriptor of the local variable.
+ * <p>
+ * If this attribute represents a LocalVariableTypeTable attribute,
+ * this method returns the value of
+ * <code>local_variable_type_table[i].signature_index</code>.
+ * It represents the type of the local variable.
*
* @param i the i-th entry.
*/
@@ -115,9 +127,26 @@ public class LocalVariableAttribute extends AttributeInfo {
}
/**
+ * This method is equivalent to <code>descriptorIndex()</code>.
+ * If this attribute represents a LocalVariableTypeTable attribute,
+ * this method should be used instead of <code>descriptorIndex()</code>
+ * since the method name is more appropriate.
+ *
+ * @param i the i-th entry.
+ * @see #descriptorIndex(int)
+ */
+ public int signatureIndex(int i) {
+ return descriptorIndex(i);
+ }
+
+ /**
* Returns the type descriptor of the local variable
* specified by <code>local_variable_table[i].descriptor_index</code>.
- *
+ * <p>
+ * If this attribute represents a LocalVariableTypeTable attribute,
+ * this method returns the type signature of the local variable
+ * specified by <code>local_variable_type_table[i].signature_index</code>.
+ *
* @param i the i-th entry.
*/
public String descriptor(int i) {
@@ -125,6 +154,19 @@ public class LocalVariableAttribute extends AttributeInfo {
}
/**
+ * This method is equivalent to <code>descriptor()</code>.
+ * If this attribute represents a LocalVariableTypeTable attribute,
+ * this method should be used instead of <code>descriptor()</code>
+ * since the method name is more appropriate.
+ *
+ * @param i the i-th entry.
+ * @see #descriptor(int)
+ */
+ public String signature(int i) {
+ return descriptor(i);
+ }
+
+ /**
* Returns <code>local_variable_table[i].index</code>.
* This represents the index of the local variable.
*
diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java
index 6b265073..b3d33213 100644
--- a/src/main/javassist/bytecode/MethodInfo.java
+++ b/src/main/javassist/bytecode/MethodInfo.java
@@ -178,6 +178,8 @@ public final class MethodInfo {
/**
* Returns all the attributes.
+ * A new element can be added to the returned list
+ * and an existing element can be removed from the list.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
diff --git a/src/main/javassist/bytecode/SignatureAttribute.java b/src/main/javassist/bytecode/SignatureAttribute.java
new file mode 100644
index 00000000..b6518ebf
--- /dev/null
+++ b/src/main/javassist/bytecode/SignatureAttribute.java
@@ -0,0 +1,70 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.bytecode;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <code>Signature_attribute</code>.
+ */
+public class SignatureAttribute extends AttributeInfo {
+ /**
+ * The name of this attribute <code>"Signature"</code>.
+ */
+ public static final String tag = "Signature";
+
+ SignatureAttribute(ConstPool cp, int n, DataInputStream in)
+ throws IOException
+ {
+ super(cp, n, in);
+ }
+
+ /**
+ * Constructs a Signature attribute.
+ *
+ * @param cp a constant pool table.
+ * @param signature the signature represented by this attribute.
+ */
+ public SignatureAttribute(ConstPool cp, String signature) {
+ super(cp, tag);
+ int index = cp.addUtf8Info(signature);
+ byte[] bvalue = new byte[2];
+ bvalue[0] = (byte)(index >>> 8);
+ bvalue[1] = (byte)index;
+ set(bvalue);
+ }
+
+ /**
+ * Returns the signature indicated by <code>signature_index</code>.
+ */
+ public String getSignature() {
+ return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
+ }
+
+ /**
+ * Makes a copy. Class names are replaced according to the
+ * given <code>Map</code> object.
+ *
+ * @param newCp the constant pool table used by the new copy.
+ * @param classnames pairs of replaced and substituted
+ * class names.
+ */
+ public AttributeInfo copy(ConstPool newCp, Map classnames) {
+ return new SignatureAttribute(newCp, getSignature());
+ }
+}
diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html
index 0598f60b..52a68e1c 100644
--- a/tutorial/tutorial.html
+++ b/tutorial/tutorial.html
@@ -400,6 +400,15 @@ program by a user-defined class loader. The latter one, as well as
the program of the user-defined class loader, should be loaded by the
system class loader.
+<ul>
+<b>Note:</b> The JVM does not allow dynamically reloading a class.
+Once a class loader loads a class, it cannot reload a modified
+version of that class during runtime. Thus, you cannot alter
+the definition of a class after the JVM loads it.
+However, the JPDA (Java Platform Debugger Architecture) provides
+limited ability for reloading a class. See "HotSwap" of JPDA for details.
+</ul>
+
<p><br>
<h3>4.1 Class loading in Java</h3>
@@ -589,15 +598,15 @@ The event-listener class must implement the following interface:
<ul><pre>public interface Translator {
public void start(ClassPool pool)
throws NotFoundException, CannotCompileException;
- public void onWrite(ClassPool pool, String classname)
+ public void onLoad(ClassPool pool, String classname)
throws NotFoundException, CannotCompileException;
}</pre></ul>
<p>The method <code>start()</code> is called when this event listener
is added to a <code>javassist.Loader</code> object by
<code>addTranslator()</code> in <code>javassist.Loader</code>. The
-method <code>onWrite()</code> is called before
-<code>javassist.Loader</code> loads a class. <code>onWrite()</code>
+method <code>onLoad()</code> is called before
+<code>javassist.Loader</code> loads a class. <code>onLoad()</code>
can modify the definition of the loaded class.
<p>For example, the following event listener changes all classes
@@ -606,7 +615,7 @@ to public classes just before they are loaded.
<ul><pre>public class MyTranslator implements Translator {
void start(ClassPool pool)
throws NotFoundException, CannotCompileException {}
- void onWrite(ClassPool pool, String classname)
+ void onLoad(ClassPool pool, String classname)
throws NotFoundException, CannotCompileException
{
CtClass cc = pool.get(classname);
@@ -614,7 +623,7 @@ to public classes just before they are loaded.
}
}</pre></ul>
-<p>Note that <code>onWrite()</code> does not have to call
+<p>Note that <code>onLoad()</code> does not have to call
<code>toBytecode()</code> or <code>writeFile()</code> since
<code>javassist.Loader</code> calls these methods to obtain a class
file.
diff --git a/tutorial/tutorial3.html b/tutorial/tutorial3.html
index 4b732978..c965a64c 100644
--- a/tutorial/tutorial3.html
+++ b/tutorial/tutorial3.html
@@ -84,10 +84,16 @@ In other words, a <code>FieldInfo</code> (or <code>MethodInfo</code> etc.) objec
must not be shared among different <code>ClassFile</code> objects.
<p>
-To remove a field or a method, you must first obtain a <code>java.util.List</code>
+To remove a field or a method,
+you must first obtain a <code>java.util.List</code>
object containing all the fields of the class. <code>getFields()</code>
and <code>getMethods()</code> return the lists. A field or a method can
be removed by calling <code>remove()</code> on the <code>List</code> object.
+An attribute can be removed in a similar way.
+Call <code>getAttributes()</code> in <code>FieldInfo</code> or
+<code>MethodInfo</code> to obtain the list of attributes,
+and remove one from the list.
+
<p><br>