Browse Source

fixed JASSIST-240. support for Runtime[In]VisibleTypeAnnotations

tags/rel_3_19_0_ga
chibash 9 years ago
parent
commit
ec3afdfb5d

+ 1
- 1
Readme.html View File

@@ -284,7 +284,7 @@ see javassist.Dump.
<p>-version 3.19
<ul>
<li>JIRA JASSIST-158, 205, 206, 207, 208, 209, 211, 212, 216, 220, 223, 224,
227, 230, 234, 235, 236, 237.
227, 230, 234, 235, 236, 237, 238, 240.
</ul>
</p>


BIN
javassist.jar View File


+ 31
- 1
src/main/javassist/bytecode/AnnotationsAttribute.java View File

@@ -350,15 +350,24 @@ public class AnnotationsAttribute extends AttributeInfo {
return pos;
}

/**
* {@code element_value_paris}
*/
final int memberValuePair(int pos) throws Exception {
int nameIndex = ByteArray.readU16bit(info, pos);
return memberValuePair(pos + 2, nameIndex);
}

/**
* {@code element_value_paris[]}
*/
int memberValuePair(int pos, int nameIndex) throws Exception {
return memberValue(pos);
}

/**
* {@code element_value}
*/
final int memberValue(int pos) throws Exception {
int tag = info[pos] & 0xff;
if (tag == 'e') {
@@ -385,18 +394,33 @@ public class AnnotationsAttribute extends AttributeInfo {
}
}

/**
* {@code const_value_index}
*/
void constValueMember(int tag, int index) throws Exception {}

/**
* {@code enum_const_value}
*/
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
throws Exception {
}

/**
* {@code class_info_index}
*/
void classMemberValue(int pos, int index) throws Exception {}

/**
* {@code annotation_value}
*/
int annotationMemberValue(int pos) throws Exception {
return annotation(pos);
}

/**
* {@code array_value}
*/
int arrayMemberValue(int pos, int num) throws Exception {
for (int i = 0; i < num; ++i) {
pos = memberValue(pos);
@@ -470,9 +494,15 @@ public class AnnotationsAttribute extends AttributeInfo {
* It can be null.
*/
Copier(byte[] info, ConstPool src, ConstPool dest, Map map) {
this(info, src, dest, map, true);
}

Copier(byte[] info, ConstPool src, ConstPool dest, Map map, boolean makeWriter) {
super(info);
output = new ByteArrayOutputStream();
writer = new AnnotationsWriter(output, dest);
if (makeWriter)
writer = new AnnotationsWriter(output, dest);

srcPool = src;
destPool = dest;
classnames = map;

+ 56
- 44
src/main/javassist/bytecode/AttributeInfo.java View File

@@ -74,53 +74,65 @@ public class AttributeInfo {
{
int name = in.readUnsignedShort();
String nameStr = cp.getUtf8Info(name);
if (nameStr.charAt(0) < 'L') {
if (nameStr.equals(AnnotationDefaultAttribute.tag))
return new AnnotationDefaultAttribute(cp, name, in);
else if (nameStr.equals(BootstrapMethodsAttribute.tag))
return new BootstrapMethodsAttribute(cp, name, in);
else if (nameStr.equals(CodeAttribute.tag))
return new CodeAttribute(cp, name, in);
else if (nameStr.equals(ConstantAttribute.tag))
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))
return new InnerClassesAttribute(cp, name, in);
char first = nameStr.charAt(0);
if (first < 'M') {
if (first < 'E') {
if (nameStr.equals(AnnotationDefaultAttribute.tag))
return new AnnotationDefaultAttribute(cp, name, in);
else if (nameStr.equals(BootstrapMethodsAttribute.tag))
return new BootstrapMethodsAttribute(cp, name, in);
else if (nameStr.equals(CodeAttribute.tag))
return new CodeAttribute(cp, name, in);
else if (nameStr.equals(ConstantAttribute.tag))
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))
return new InnerClassesAttribute(cp, name, in);
else if (nameStr.equals(LineNumberAttribute.tag))
return new LineNumberAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableAttribute.tag))
return new LocalVariableAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableTypeAttribute.tag))
return new LocalVariableTypeAttribute(cp, name, in);
}
}
else {
/* Note that the names of Annotations attributes begin with 'R'.
*/
if (nameStr.equals(LineNumberAttribute.tag))
return new LineNumberAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableAttribute.tag))
return new LocalVariableAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableTypeAttribute.tag))
return new LocalVariableTypeAttribute(cp, name, in);
else if (nameStr.equals(MethodParametersAttribute.tag))
return new MethodParametersAttribute(cp, name, in);
else if (nameStr.equals(AnnotationsAttribute.visibleTag)
|| nameStr.equals(AnnotationsAttribute.invisibleTag)) {
// RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
return new AnnotationsAttribute(cp, name, in);
if (first < 'S') {
/* Note that the names of Annotations attributes begin with 'R'.
*/
if (nameStr.equals(MethodParametersAttribute.tag))
return new MethodParametersAttribute(cp, name, in);
else if (nameStr.equals(AnnotationsAttribute.visibleTag)
|| nameStr.equals(AnnotationsAttribute.invisibleTag)) {
// RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
return new AnnotationsAttribute(cp, name, in);
}
else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag)
|| nameStr.equals(ParameterAnnotationsAttribute.invisibleTag))
return new ParameterAnnotationsAttribute(cp, name, in);
else if (nameStr.equals(TypeAnnotationsAttribute.visibleTag)
|| nameStr.equals(TypeAnnotationsAttribute.invisibleTag))
return new TypeAnnotationsAttribute(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))
return new SyntheticAttribute(cp, name, in);
else if (nameStr.equals(StackMap.tag))
return new StackMap(cp, name, in);
else if (nameStr.equals(StackMapTable.tag))
return new StackMapTable(cp, name, in);
}
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))
return new SyntheticAttribute(cp, name, in);
else if (nameStr.equals(StackMap.tag))
return new StackMap(cp, name, in);
else if (nameStr.equals(StackMapTable.tag))
return new StackMapTable(cp, name, in);
}

return new AttributeInfo(cp, name, in);

+ 358
- 0
src/main/javassist/bytecode/TypeAnnotationsAttribute.java View File

@@ -0,0 +1,358 @@
package javassist.bytecode;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javassist.bytecode.annotation.TypeAnnotationsWriter;

/**
* A class representing
* {@code RuntimeVisibleTypeAnnotations} attribute and
* {@code RuntimeInvisibleTypeAnnotations} attribute.
*/
public class TypeAnnotationsAttribute extends AttributeInfo {
/**
* The name of the {@code RuntimeVisibleTypeAnnotations} attribute.
*/
public static final String visibleTag = "RuntimeVisibleTypeAnnotations";

/**
* The name of the {@code RuntimeInvisibleTypeAnnotations} attribute.
*/
public static final String invisibleTag = "RuntimeInvisibleTypeAnnotations";

/**
* Constructs a <code>Runtime(In)VisibleTypeAnnotations_attribute</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @param info the contents of this attribute. It does not
* include <code>attribute_name_index</code> or
* <code>attribute_length</code>.
*/
public TypeAnnotationsAttribute(ConstPool cp, String attrname, byte[] info) {
super(cp, attrname, info);
}

/**
* @param n the attribute name.
*/
TypeAnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}

/**
* Returns <code>num_annotations</code>.
*/
public int numAnnotations() {
return ByteArray.readU16bit(info, 0);
}

/**
* Copies this attribute and returns a new copy.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
Copier copier = new Copier(info, constPool, newCp, classnames);
try {
copier.annotationArray();
return new TypeAnnotationsAttribute(newCp, getName(), copier.close());
}
catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* @param oldname a JVM class name.
* @param newname a JVM class name.
*/
void renameClass(String oldname, String newname) {
HashMap map = new HashMap();
map.put(oldname, newname);
renameClass(map);
}

void renameClass(Map classnames) {
Renamer renamer = new Renamer(info, getConstPool(), classnames);
try {
renamer.annotationArray();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

void getRefClasses(Map classnames) { renameClass(classnames); }

/**
* To visit each elements of the type annotation attribute,
* call {@code annotationArray()}.
*
* @see #annotationArray()
*/
static class TAWalker extends AnnotationsAttribute.Walker {
SubWalker subWalker;

TAWalker(byte[] attrInfo) {
super(attrInfo);
subWalker = new SubWalker(attrInfo);
}

int annotationArray(int pos, int num) throws Exception {
for (int i = 0; i < num; i++) {
int targetType = info[pos] & 0xff;
pos = subWalker.targetInfo(pos + 1, targetType);
pos = subWalker.typePath(pos);
pos = annotation(pos);
}

return pos;
}
}

static class SubWalker {
byte[] info;

SubWalker(byte[] attrInfo) {
info = attrInfo;
}

final int targetInfo(int pos, int type) throws Exception {
switch (type) {
case 0x00:
case 0x01: {
int index = info[pos] & 0xff;
typeParameterTarget(pos, type, index);
return pos + 1; }
case 0x10: {
int index = ByteArray.readU16bit(info, pos);
supertypeTarget(pos, index);
return pos + 2; }
case 0x11:
case 0x12: {
int param = info[pos] & 0xff;
int bound = info[pos + 1] & 0xff;
typeParameterBoundTarget(pos, type, param, bound);
return pos + 2; }
case 0x13:
case 0x14:
case 0x15:
emptyTarget(pos, type);
return pos;
case 0x16: {
int index = info[pos] & 0xff;
formalParameterTarget(pos, index);
return pos + 1; }
case 0x17: {
int index = ByteArray.readU16bit(info, pos);
throwsTarget(pos, index);
return pos + 2; }
case 0x40:
case 0x41: {
int len = ByteArray.readU16bit(info, pos);
return localvarTarget(pos + 2, type, len); }
case 0x42: {
int index = ByteArray.readU16bit(info, pos);
catchTarget(pos, index);
return pos + 2; }
case 0x43:
case 0x44:
case 0x45:
case 0x46: {
int offset = ByteArray.readU16bit(info, pos);
offsetTarget(pos, type, offset);
return pos + 2; }
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b: {
int offset = ByteArray.readU16bit(info, pos);
int index = info[pos + 2] & 0xff;
typeArgumentTarget(pos, type, offset, index);
return pos + 3; }
default:
throw new RuntimeException("invalid target type: " + type);
}
}

void typeParameterTarget(int pos, int targetType, int typeParameterIndex)
throws Exception {}

void supertypeTarget(int pos, int superTypeIndex) throws Exception {}

void typeParameterBoundTarget(int pos, int targetType, int typeParameterIndex,
int boundIndex) throws Exception {}

void emptyTarget(int pos, int targetType) throws Exception {}

void formalParameterTarget(int pos, int formalParameterIndex) throws Exception {}

void throwsTarget(int pos, int throwsTypeIndex) throws Exception {}

int localvarTarget(int pos, int targetType, int tableLength) throws Exception {
for (int i = 0; i < tableLength; i++) {
int start = ByteArray.readU16bit(info, pos);
int length = ByteArray.readU16bit(info, pos + 2);
int index = ByteArray.readU16bit(info, pos + 4);
localvarTarget(pos, targetType, start, length, index);
pos += 6;
}

return pos;
}

void localvarTarget(int pos, int targetType, int startPc, int length, int index)
throws Exception {}

void catchTarget(int pos, int exceptionTableIndex) throws Exception {}

void offsetTarget(int pos, int targetType, int offset) throws Exception {}

void typeArgumentTarget(int pos, int targetType, int offset, int typeArgumentIndex)
throws Exception {}

final int typePath(int pos) throws Exception {
int len = info[pos++] & 0xff;
return typePath(pos, len);
}

int typePath(int pos, int pathLength) throws Exception {
for (int i = 0; i < pathLength; i++) {
int kind = info[pos] & 0xff;
int index = info[pos + 1] & 0xff;
typePath(pos, kind, index);
pos += 2;
}

return pos;
}

void typePath(int pos, int typePathKind, int typeArgumentIndex) throws Exception {}
}

static class Renamer extends AnnotationsAttribute.Renamer {
SubWalker sub;

Renamer(byte[] attrInfo, ConstPool cp, Map map) {
super(attrInfo, cp, map);
sub = new SubWalker(attrInfo);
}

int annotationArray(int pos, int num) throws Exception {
for (int i = 0; i < num; i++) {
int targetType = info[pos] & 0xff;
pos = sub.targetInfo(pos + 1, targetType);
pos = sub.typePath(pos);
pos = annotation(pos);
}

return pos;
}
}

static class Copier extends AnnotationsAttribute.Copier {
SubCopier sub;

Copier(byte[] attrInfo, ConstPool src, ConstPool dest, Map map) {
super(attrInfo, src, dest, map, false);
TypeAnnotationsWriter w = new TypeAnnotationsWriter(output, dest);
writer = w;
sub = new SubCopier(attrInfo, src, dest, map, w);
}

int annotationArray(int pos, int num) throws Exception {
writer.numAnnotations(num);
for (int i = 0; i < num; i++) {
int targetType = info[pos] & 0xff;
pos = sub.targetInfo(pos + 1, targetType);
pos = sub.typePath(pos);
pos = annotation(pos);
}

return pos;
}
}

static class SubCopier extends SubWalker {
ConstPool srcPool, destPool;
Map classnames;
TypeAnnotationsWriter writer;

SubCopier(byte[] attrInfo, ConstPool src, ConstPool dest, Map map,
TypeAnnotationsWriter w)
{
super(attrInfo);
srcPool = src;
destPool = dest;
classnames = map;
writer = w;
}

void typeParameterTarget(int pos, int targetType, int typeParameterIndex)
throws Exception
{
writer.typeParameterTarget(targetType, typeParameterIndex);
}

void supertypeTarget(int pos, int superTypeIndex) throws Exception {
writer.supertypeTarget(superTypeIndex);
}

void typeParameterBoundTarget(int pos, int targetType, int typeParameterIndex,
int boundIndex)
throws Exception
{
writer.typeParameterBoundTarget(targetType, typeParameterIndex, boundIndex);
}

void emptyTarget(int pos, int targetType) throws Exception {
writer.emptyTarget(targetType);
}

void formalParameterTarget(int pos, int formalParameterIndex) throws Exception {
writer.formalParameterTarget(formalParameterIndex);
}

void throwsTarget(int pos, int throwsTypeIndex) throws Exception {
writer.throwsTarget(throwsTypeIndex);
}

int localvarTarget(int pos, int targetType, int tableLength) throws Exception {
writer.localVarTarget(targetType, tableLength);
return super.localvarTarget(pos, targetType, tableLength);
}

void localvarTarget(int pos, int targetType, int startPc, int length, int index)
throws Exception
{
writer.localVarTargetTable(startPc, length, index);
}

void catchTarget(int pos, int exceptionTableIndex) throws Exception {
writer.catchTarget(exceptionTableIndex);
}

void offsetTarget(int pos, int targetType, int offset) throws Exception {
writer.offsetTarget(targetType, offset);
}

void typeArgumentTarget(int pos, int targetType, int offset, int typeArgumentIndex)
throws Exception
{
writer.typeArgumentTarget(targetType, offset, typeArgumentIndex);
}

int typePath(int pos, int pathLength) throws Exception {
writer.typePath(pathLength);
return super.typePath(pos, pathLength);
}

void typePath(int pos, int typePathKind, int typeArgumentIndex) throws Exception {
writer.typePathPath(typePathKind, typeArgumentIndex);
}
}
}

+ 31
- 31
src/main/javassist/bytecode/annotation/AnnotationsWriter.java View File

@@ -35,9 +35,9 @@ import javassist.bytecode.ConstPool;
*
* writer.numAnnotations(1);
* writer.annotation("Author", 2);
* writer.memberValuePair("name");
* writer.memberValuePair("name"); // element_value_pair
* writer.constValueIndex("chiba");
* writer.memberValuePair("address");
* writer.memberValuePair("address"); // element_value_pair
* writer.constValueIndex("tokyo");
*
* writer.close();
@@ -58,7 +58,7 @@ import javassist.bytecode.ConstPool;
* @see javassist.bytecode.ParameterAnnotationsAttribute
*/
public class AnnotationsWriter {
private OutputStream output;
protected OutputStream output;
private ConstPool pool;

/**
@@ -113,7 +113,7 @@ public class AnnotationsWriter {
* calls to <code>memberValuePair()</code>.
*
* @param type the annotation interface name.
* @param numMemberValuePairs <code>num_member_value_pairs</code>
* @param numMemberValuePairs <code>num_element_value_pairs</code>
* in <code>annotation</code>.
*/
public void annotation(String type, int numMemberValuePairs)
@@ -128,7 +128,7 @@ public class AnnotationsWriter {
* calls to <code>memberValuePair()</code>.
*
* @param typeIndex <code>type_index</code> in <code>annotation</code>.
* @param numMemberValuePairs <code>num_member_value_pairs</code>
* @param numMemberValuePairs <code>num_element_value_pairs</code>
* in <code>annotation</code>.
*/
public void annotation(int typeIndex, int numMemberValuePairs)
@@ -139,27 +139,27 @@ public class AnnotationsWriter {
}

/**
* Writes an element of a <code>member_value_pairs</code> array
* Writes an element of a <code>element_value_pairs</code> array
* in <code>annotation</code>.
* This method must be followed by a
* call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
*
* @param memberName the name of the annotation type member.
* @param memberName the element name.
*/
public void memberValuePair(String memberName) throws IOException {
memberValuePair(pool.addUtf8Info(memberName));
}

/**
* Writes an element of a <code>member_value_pairs</code> array
* Writes an element of a <code>element_value_pairs</code> array
* in <code>annotation</code>.
* This method must be followed by a
* call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
*
* @param memberNameIndex <code>member_name_index</code>
* in <code>member_value_pairs</code> array.
* @param memberNameIndex <code>element_name_index</code>
* in <code>element_value_pairs</code> array.
*/
public void memberValuePair(int memberNameIndex) throws IOException {
write16bit(memberNameIndex);
@@ -167,7 +167,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -177,7 +177,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -187,7 +187,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -197,7 +197,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -207,7 +207,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -217,7 +217,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -227,7 +227,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -237,7 +237,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -247,7 +247,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param value the constant value.
*/
@@ -257,11 +257,11 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param tag <code>tag</code> in <code>member_value</code>.
* @param tag <code>tag</code> in <code>element_value</code>.
* @param index <code>const_value_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*/
public void constValueIndex(int tag, int index)
throws IOException
@@ -272,7 +272,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>enum_const_value</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param typeName the type name of the enum constant.
* @param constName the simple name of the enum constant.
@@ -286,12 +286,12 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>enum_const_value</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param typeNameIndex <code>type_name_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
* @param constNameIndex <code>const_name_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*/
public void enumConstValue(int typeNameIndex, int constNameIndex)
throws IOException
@@ -303,7 +303,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>class_info_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param name the class name.
*/
@@ -313,7 +313,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>class_info_index</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
*
* @param index <code>class_info_index</code>
*/
@@ -324,7 +324,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>annotation_value</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
* This method must be followed by a call to <code>annotation()</code>.
*/
public void annotationValue() throws IOException {
@@ -333,7 +333,7 @@ public class AnnotationsWriter {

/**
* Writes <code>tag</code> and <code>array_value</code>
* in <code>member_value</code>.
* in <code>element_value</code>.
* This method must be followed by <code>numValues</code> calls
* to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
@@ -346,7 +346,7 @@ public class AnnotationsWriter {
write16bit(numValues);
}

private void write16bit(int value) throws IOException {
protected void write16bit(int value) throws IOException {
byte[] buf = new byte[2];
ByteArray.write16bit(value, buf, 0);
output.write(buf);

+ 172
- 0
src/main/javassist/bytecode/annotation/TypeAnnotationsWriter.java View File

@@ -0,0 +1,172 @@
package javassist.bytecode.annotation;

import java.io.IOException;
import java.io.OutputStream;

import javassist.bytecode.ConstPool;

/**
* A convenience class for constructing a
* {@code ..TypeAnnotations_attribute}.
* See the source code of the {@link javassist.bytecode.TypeAnnotationsAttribute} class.
*/
public class TypeAnnotationsWriter extends AnnotationsWriter {
/**
* Constructs with the given output stream.
*
* @param os the output stream.
* @param cp the constant pool.
*/
public TypeAnnotationsWriter(OutputStream os, ConstPool cp) {
super(os, cp);
}

/**
* Writes {@code num_annotations} in
* {@code Runtime(In)VisibleTypeAnnotations_attribute}.
* It must be followed by {@code num} instances of {@code type_annotation}.
*/
public void numAnnotations(int num) throws IOException {
super.numAnnotations(num);
}

/**
* Writes {@code target_type} and {@code type_parameter_target}
* of {@code target_info} union.
*/
public void typeParameterTarget(int targetType, int typeParameterIndex)
throws IOException
{
output.write(targetType);
output.write(typeParameterIndex);
}

/**
* Writes {@code target_type} and {@code supertype_target}
* of {@code target_info} union.
*/
public void supertypeTarget(int supertypeIndex)
throws IOException
{
output.write(0x10);
write16bit(supertypeIndex);
}

/**
* Writes {@code target_type} and {@code type_parameter_bound_target}
* of {@code target_info} union.
*/
public void typeParameterBoundTarget(int targetType, int typeParameterIndex, int boundIndex)
throws IOException
{
output.write(targetType);
output.write(typeParameterIndex);
output.write(boundIndex);
}

/**
* Writes {@code target_type} and {@code empty_target}
* of {@code target_info} union.
*/
public void emptyTarget(int targetType) throws IOException {
output.write(targetType);
}

/**
* Writes {@code target_type} and {@code type_parameter_target}
* of {@code target_info} union.
*/
public void formalParameterTarget(int formalParameterIndex)
throws IOException
{
output.write(0x16);
output.write(formalParameterIndex);
}

/**
* Writes {@code target_type} and {@code throws_target}
* of {@code target_info} union.
*/
public void throwsTarget(int throwsTypeIndex)
throws IOException
{
output.write(0x17);
write16bit(throwsTypeIndex);
}

/**
* Writes {@code target_type} and {@code localvar_target}
* of {@code target_info} union.
* It must be followed by {@code tableLength} calls
* to {@code localVarTargetTable}.
*/
public void localVarTarget(int targetType, int tableLength)
throws IOException
{
output.write(targetType);
write16bit(tableLength);
}

/**
* Writes an element of {@code table[]} of {@code localvar_target}
* of {@code target_info} union.
*/
public void localVarTargetTable(int startPc, int length, int index)
throws IOException
{
write16bit(startPc);
write16bit(length);
write16bit(index);
}

/**
* Writes {@code target_type} and {@code catch_target}
* of {@code target_info} union.
*/
public void catchTarget(int exceptionTableIndex)
throws IOException
{
output.write(0x42);
write16bit(exceptionTableIndex);
}

/**
* Writes {@code target_type} and {@code offset_target}
* of {@code target_info} union.
*/
public void offsetTarget(int targetType, int offset)
throws IOException
{
output.write(targetType);
write16bit(offset);
}

/**
* Writes {@code target_type} and {@code type_argument_target}
* of {@code target_info} union.
*/
public void typeArgumentTarget(int targetType, int offset, int type_argument_index)
throws IOException
{
output.write(targetType);
write16bit(offset);
output.write(type_argument_index);
}

/**
* Writes {@code path_length} of {@code type_path}.
*/
public void typePath(int pathLength) throws IOException {
output.write(pathLength);
}

/**
* Writes an element of {@code path[]} of {@code type_path}.
*/
public void typePathPath(int typePathKind, int typeArgumentIndex)
throws IOException
{
output.write(typePathKind);
output.write(typeArgumentIndex);
}
}

+ 10
- 8
src/test/javassist/JvstTest4.java View File

@@ -606,10 +606,10 @@ public class JvstTest4 extends JvstTestRoot {
assertEquals(packageName, obj.getClass().getPackage().getName());
}

public static final String BASE_PATH="../";
public static final String JAVASSIST_JAR=BASE_PATH+"javassist.jar";
public static final String CLASSES_FOLDER=BASE_PATH+"build/classes";
public static final String TEST_CLASSES_FOLDER=BASE_PATH+"build/test-classes";
public static final String BASE_PATH = "../";
public static final String JAVASSIST_JAR = BASE_PATH + "javassist.jar";
public static final String CLASSES_FOLDER = BASE_PATH + "build/classes";
public static final String TEST_CLASSES_FOLDER = BASE_PATH + "build/test-classes";

public static class Inner1 {
public static int get() {
@@ -661,8 +661,8 @@ public class JvstTest4 extends JvstTestRoot {
long t2 = endTime2 - endTime;
long t3 = endTime3 - endTime2;
System.out.println("JIRA150: " + t1 + ", " + t2 + ", " + t3);
assertTrue("performance test (the next try may succeed): " + t1 + "/ 5 < " + t2,
t2 < t1 * 5);
assertTrue("performance test (the next try may succeed): " + t1 + "/ 6 < " + t2,
t2 < t1 * 6);
assertTrue("", t3 < t1 * 3);
}

@@ -691,15 +691,17 @@ public class JvstTest4 extends JvstTestRoot {
}

// try to run garbage collection.
int[][] mem = new int[100][];
int[] large;
for (int i = 0; i < 100; i++) {
large = new int[1000000];
large[large.length - 2] = 9;
large[large.length - 2] = 9 + i;
mem[i] = large;
}
System.gc();
System.gc();
int size = javassist.compiler.MemberResolver.getInvalidMapSize();
System.out.println("JIRA150b " + size);
System.out.println("JIRA150b " + size + " " + mem[mem.length - 1][mem[0].length - 2]);
assertTrue("JIRA150b size: " + origSize + " " + size, size < origSize + N);
}


+ 13
- 0
src/test/javassist/JvstTest5.java View File

@@ -1,5 +1,8 @@
package javassist;

import java.lang.annotation.Annotation;
import java.lang.reflect.TypeVariable;

public class JvstTest5 extends JvstTestRoot {
public JvstTest5(String name) {
super(name);
@@ -31,4 +34,14 @@ public class JvstTest5 extends JvstTestRoot {
assertEquals(10, invoke(obj, "run2"));
assertEquals(10, invoke(obj, "run3"));
}

public void testTypeAnno() throws Exception {
CtClass cc = sloader.get("test5.TypeAnno");
cc.getClassFile().compact();
cc.writeFile();
Object obj = make(cc.getName());
TypeVariable<?> t = obj.getClass().getTypeParameters()[0];
Annotation[] annos = t.getAnnotations();
assertEquals("@test5.TypeAnnoA()", annos[0].toString());
}
}

+ 30
- 0
src/test/test5/TypeAnno.java View File

@@ -0,0 +1,30 @@
package test5;

import java.util.ArrayList;

class TypeAnnoSuper {}
interface TypeAnnoI {}

@TypeAnnoA
public class TypeAnno<@TypeAnnoA TT extends @TypeAnnoA String> extends @TypeAnnoA TypeAnnoSuper implements @TypeAnnoA TypeAnnoI {
public @TypeAnnoA String foo(@TypeAnnoA int i) throws @TypeAnnoA Exception {
@TypeAnnoA String s = new @TypeAnnoA String("bar ");
Object t = s;
String ss = (@TypeAnnoA String)t;
ArrayList<@TypeAnnoA String> list = new ArrayList<@TypeAnnoA String>();
if (list instanceof /* @TypeAnnoA */ java.util.List)
System.out.println("ok");

try {
list.add(ss);
} catch (@TypeAnnoA RuntimeException e) {}
return "foo" + list.get(0) + i;
}

@TypeAnnoA double dvalue;
@TypeAnnoA int ivalue @TypeAnnoA [] @TypeAnnoA [] @TypeAnnoA [];

<@TypeAnnoA T extends @TypeAnnoA String> T bar(T t) { return t; }

@TypeAnnoA TT getNull() { return null; }
}

+ 10
- 0
src/test/test5/TypeAnnoA.java View File

@@ -0,0 +1,10 @@
package test5;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeAnnoA {}

Loading…
Cancel
Save