diff options
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | src/main/javassist/CtClassType.java | 8 | ||||
-rw-r--r-- | src/main/javassist/bytecode/AccessFlag.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/AttributeInfo.java | 10 | ||||
-rw-r--r-- | src/main/javassist/bytecode/CodeAttribute.java | 8 | ||||
-rw-r--r-- | src/main/javassist/bytecode/CodeIterator.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/EnclosingMethodAttribute.java | 111 | ||||
-rw-r--r-- | src/main/javassist/bytecode/FieldInfo.java | 2 | ||||
-rw-r--r-- | src/main/javassist/bytecode/LocalVariableAttribute.java | 50 | ||||
-rw-r--r-- | src/main/javassist/bytecode/MethodInfo.java | 2 | ||||
-rw-r--r-- | src/main/javassist/bytecode/SignatureAttribute.java | 70 | ||||
-rw-r--r-- | tutorial/tutorial.html | 19 | ||||
-rw-r--r-- | tutorial/tutorial3.html | 8 |
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> |