git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@114 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
@@ -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> |
@@ -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) |
@@ -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 |
@@ -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)) |
@@ -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, |
@@ -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; | |||
} | |||
@@ -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()); | |||
} | |||
} |
@@ -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 |
@@ -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. | |||
*/ | |||
@@ -114,16 +126,46 @@ public class LocalVariableAttribute extends AttributeInfo { | |||
return ByteArray.readU16bit(info, i * 10 + 8); | |||
} | |||
/** | |||
* 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) { | |||
return getConstPool().getUtf8Info(descriptorIndex(i)); | |||
} | |||
/** | |||
* 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. |
@@ -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 |
@@ -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()); | |||
} | |||
} |
@@ -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. |
@@ -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> | |||