| Method from org.objectweb.asm.ClassWriter Detail: |
int addType(String type) {
key.set(TYPE_NORMAL, type, null, null);
Item result = get(key);
if (result == null) {
result = addType(key);
}
return result.index;
}
Adds the given internal name to #typeTable and returns its index.
Does nothing if the type table already contains this internal name. |
int addUninitializedType(String type,
int offset) {
key.type = TYPE_UNINIT;
key.intVal = offset;
key.strVal1 = type;
key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
Item result = get(key);
if (result == null) {
result = addType(key);
}
return result.index;
}
Adds the given "uninitialized" type to #typeTable and returns its
index. This method is used for UNINITIALIZED types, made of an internal
name and a bytecode offset. |
protected String getCommonSuperClass(String type1,
String type2) {
Class c, d;
try {
c = Class.forName(type1.replace('/", '."));
d = Class.forName(type2.replace('/", '."));
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
if (c.isAssignableFrom(d)) {
return type1;
}
if (d.isAssignableFrom(c)) {
return type2;
}
if (c.isInterface() || d.isInterface()) {
return "java/lang/Object";
} else {
do {
c = c.getSuperclass();
} while (!c.isAssignableFrom(d));
return c.getName().replace('.", '/");
}
}
Returns the common super type of the two given types. The default
implementation of this method loads the two given classes and uses
the java.lang.Class methods to find the common super class. It can be
overridden to compute this common super type in other ways, in particular
without actually loading any class, or to take into account the class
that is currently being generated by this ClassWriter, which can of
course not be loaded since it is under construction. |
int getMergedType(int type1,
int type2) {
key2.type = TYPE_MERGED;
key2.longVal = type1 | (((long) type2) < < 32);
key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
Item result = get(key2);
if (result == null) {
String t = typeTable[type1].strVal1;
String u = typeTable[type2].strVal1;
key2.intVal = addType(getCommonSuperClass(t, u));
result = new Item((short) 0, key2);
put(result);
}
return result.intVal;
}
Returns the index of the common super type of the two given types. This
method calls #getCommonSuperClass and caches the result in the
#items hash table to speedup future calls with the same
parameters. |
public int newClass(String value) {
return newClassItem(value).index;
}
Adds a class reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item.
This method is intended for Attribute sub classes, and is
normally not needed by class generators or adapters. |
Item newClassItem(String value) {
key2.set(CLASS, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(CLASS, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result;
}
Adds a class reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item.
This method is intended for Attribute sub classes, and is
normally not needed by class generators or adapters. |
public int newConst(Object cst) {
return newConstItem(cst).index;
}
Adds a number or string constant to the constant pool of the class being
build. Does nothing if the constant pool already contains a similar item.
This method is intended for Attribute sub classes, and is
normally not needed by class generators or adapters. |
Item newConstItem(Object cst) {
if (cst instanceof Integer) {
int val = ((Integer) cst).intValue();
return newInteger(val);
} else if (cst instanceof Byte) {
int val = ((Byte) cst).intValue();
return newInteger(val);
} else if (cst instanceof Character) {
int val = ((Character) cst).charValue();
return newInteger(val);
} else if (cst instanceof Short) {
int val = ((Short) cst).intValue();
return newInteger(val);
} else if (cst instanceof Boolean) {
int val = ((Boolean) cst).booleanValue() ? 1 : 0;
return newInteger(val);
} else if (cst instanceof Float) {
float val = ((Float) cst).floatValue();
return newFloat(val);
} else if (cst instanceof Long) {
long val = ((Long) cst).longValue();
return newLong(val);
} else if (cst instanceof Double) {
double val = ((Double) cst).doubleValue();
return newDouble(val);
} else if (cst instanceof String) {
return newString((String) cst);
} else if (cst instanceof Type) {
Type t = (Type) cst;
return newClassItem(t.getSort() == Type.OBJECT
? t.getInternalName()
: t.getDescriptor());
} else {
throw new IllegalArgumentException("value " + cst);
}
}
Adds a number or string constant to the constant pool of the class being
build. Does nothing if the constant pool already contains a similar item. |
Item newDouble(double value) {
key.set(value);
Item result = get(key);
if (result == null) {
pool.putByte(DOUBLE).putLong(key.longVal);
result = new Item(index, key);
put(result);
index += 2;
}
return result;
}
Adds a double to the constant pool of the class being build. Does nothing
if the constant pool already contains a similar item. |
public int newField(String owner,
String name,
String desc) {
return newFieldItem(owner, name, desc).index;
}
Adds a field reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item.
This method is intended for Attribute sub classes, and is
normally not needed by class generators or adapters. |
Item newFieldItem(String owner,
String name,
String desc) {
key3.set(FIELD, owner, name, desc);
Item result = get(key3);
if (result == null) {
put122(FIELD, newClass(owner), newNameType(name, desc));
result = new Item(index++, key3);
put(result);
}
return result;
}
Adds a field reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item. |
Item newFloat(float value) {
key.set(value);
Item result = get(key);
if (result == null) {
pool.putByte(FLOAT).putInt(key.intVal);
result = new Item(index++, key);
put(result);
}
return result;
}
Adds a float to the constant pool of the class being build. Does nothing
if the constant pool already contains a similar item. |
Item newInteger(int value) {
key.set(value);
Item result = get(key);
if (result == null) {
pool.putByte(INT).putInt(value);
result = new Item(index++, key);
put(result);
}
return result;
}
Adds an integer to the constant pool of the class being build. Does
nothing if the constant pool already contains a similar item. |
Item newLong(long value) {
key.set(value);
Item result = get(key);
if (result == null) {
pool.putByte(LONG).putLong(value);
result = new Item(index, key);
put(result);
index += 2;
}
return result;
}
Adds a long to the constant pool of the class being build. Does nothing
if the constant pool already contains a similar item. |
public int newMethod(String owner,
String name,
String desc,
boolean itf) {
return newMethodItem(owner, name, desc, itf).index;
}
Adds a method reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item.
This method is intended for Attribute sub classes, and is
normally not needed by class generators or adapters. |
Item newMethodItem(String owner,
String name,
String desc,
boolean itf) {
int type = itf ? IMETH : METH;
key3.set(type, owner, name, desc);
Item result = get(key3);
if (result == null) {
put122(type, newClass(owner), newNameType(name, desc));
result = new Item(index++, key3);
put(result);
}
return result;
}
Adds a method reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item. |
public int newNameType(String name,
String desc) {
key2.set(NAME_TYPE, name, desc, null);
Item result = get(key2);
if (result == null) {
put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
Adds a name and type to the constant pool of the class being build. Does
nothing if the constant pool already contains a similar item. This
method is intended for Attribute sub classes, and is normally not
needed by class generators or adapters. |
public int newUTF8(String value) {
key.set(UTF8, value, null, null);
Item result = get(key);
if (result == null) {
pool.putByte(UTF8).putUTF8(value);
result = new Item(index++, key);
put(result);
}
return result.index;
}
Adds an UTF8 string to the constant pool of the class being build. Does
nothing if the constant pool already contains a similar item. This
method is intended for Attribute sub classes, and is normally not
needed by class generators or adapters. |
public byte[] toByteArray() {
// computes the real size of the bytecode of this class
int size = 24 + 2 * interfaceCount;
int nbFields = 0;
FieldWriter fb = firstField;
while (fb != null) {
++nbFields;
size += fb.getSize();
fb = fb.next;
}
int nbMethods = 0;
MethodWriter mb = firstMethod;
while (mb != null) {
++nbMethods;
size += mb.getSize();
mb = mb.next;
}
int attributeCount = 0;
if (ClassReader.SIGNATURES && signature != 0) {
++attributeCount;
size += 8;
newUTF8("Signature");
}
if (sourceFile != 0) {
++attributeCount;
size += 8;
newUTF8("SourceFile");
}
if (sourceDebug != null) {
++attributeCount;
size += sourceDebug.length + 4;
newUTF8("SourceDebugExtension");
}
if (enclosingMethodOwner != 0) {
++attributeCount;
size += 10;
newUTF8("EnclosingMethod");
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
size += 6;
newUTF8("Deprecated");
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0
&& (version & 0xffff) < Opcodes.V1_5)
{
++attributeCount;
size += 6;
newUTF8("Synthetic");
}
if (innerClasses != null) {
++attributeCount;
size += 8 + innerClasses.length;
newUTF8("InnerClasses");
}
if (ClassReader.ANNOTATIONS && anns != null) {
++attributeCount;
size += 8 + anns.getSize();
newUTF8("RuntimeVisibleAnnotations");
}
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations");
}
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
}
size += pool.length;
// allocates a byte vector of this size, in order to avoid unnecessary
// arraycopy operations in the ByteVector.enlarge() method
ByteVector out = new ByteVector(size);
out.putInt(0xCAFEBABE).putInt(version);
out.putShort(index).putByteArray(pool.data, 0, pool.length);
out.putShort(access).putShort(name).putShort(superName);
out.putShort(interfaceCount);
for (int i = 0; i < interfaceCount; ++i) {
out.putShort(interfaces[i]);
}
out.putShort(nbFields);
fb = firstField;
while (fb != null) {
fb.put(out);
fb = fb.next;
}
out.putShort(nbMethods);
mb = firstMethod;
while (mb != null) {
mb.put(out);
mb = mb.next;
}
out.putShort(attributeCount);
if (ClassReader.SIGNATURES && signature != 0) {
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
}
if (sourceFile != 0) {
out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
}
if (sourceDebug != null) {
int len = sourceDebug.length - 2;
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
out.putByteArray(sourceDebug.data, 2, len);
}
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(newUTF8("Deprecated")).putInt(0);
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0
&& (version & 0xffff) < Opcodes.V1_5)
{
out.putShort(newUTF8("Synthetic")).putInt(0);
}
if (innerClasses != null) {
out.putShort(newUTF8("InnerClasses"));
out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
out.putByteArray(innerClasses.data, 0, innerClasses.length);
}
if (ClassReader.ANNOTATIONS && anns != null) {
out.putShort(newUTF8("RuntimeVisibleAnnotations"));
anns.put(out);
}
if (ClassReader.ANNOTATIONS && ianns != null) {
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
return out.data;
}
Returns the bytecode of the class that was build with this class writer. |
public void visit(int version,
int access,
String name,
String signature,
String superName,
String[] interfaces) {
this.version = version;
this.access = access;
this.name = newClass(name);
thisName = name;
if (ClassReader.SIGNATURES && signature != null) {
this.signature = newUTF8(signature);
}
this.superName = superName == null ? 0 : newClass(superName);
if (interfaces != null && interfaces.length > 0) {
interfaceCount = interfaces.length;
this.interfaces = new int[interfaceCount];
for (int i = 0; i < interfaceCount; ++i) {
this.interfaces[i] = newClass(interfaces[i]);
}
}
}
|
public AnnotationVisitor visitAnnotation(String desc,
boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write type, and reserve space for values count
bv.putShort(newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
if (visible) {
aw.next = anns;
anns = aw;
} else {
aw.next = ianns;
ianns = aw;
}
return aw;
}
|
public void visitAttribute(Attribute attr) {
attr.next = attrs;
attrs = attr;
}
|
public void visitEnd() {
}
|
public FieldVisitor visitField(int access,
String name,
String desc,
String signature,
Object value) {
return new FieldWriter(this, access, name, desc, signature, value);
}
|
public void visitInnerClass(String name,
String outerName,
String innerName,
int access) {
if (innerClasses == null) {
innerClasses = new ByteVector();
}
++innerClassesCount;
innerClasses.putShort(name == null ? 0 : newClass(name));
innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
innerClasses.putShort(access);
}
|
public MethodVisitor visitMethod(int access,
String name,
String desc,
String signature,
String[] exceptions) {
return new MethodWriter(this,
access,
name,
desc,
signature,
exceptions,
computeMaxs,
computeFrames);
}
|
public void visitOuterClass(String owner,
String name,
String desc) {
enclosingMethodOwner = newClass(owner);
if (name != null && desc != null) {
enclosingMethod = newNameType(name, desc);
}
}
|
public void visitSource(String file,
String debug) {
if (file != null) {
sourceFile = newUTF8(file);
}
if (debug != null) {
sourceDebug = new ByteVector().putUTF8(debug);
}
}
|