Methods Summary |
---|
public void | accept(IClassDefVisitor visitor, java.lang.Object ctx)
visitor.visit (this, ctx);
|
public int | addCONSTANT_Utf8(java.lang.String value, boolean keepUnique)
if (keepUnique)
{
final int existing = m_constants.findCONSTANT_Utf8 (value);
if (existing > 0)
{
return existing;
}
// [else fall through]
}
return m_constants.add (new CONSTANT_Utf8_info (value));
|
public int | addClassref(java.lang.String classJVMName)
final int name_index = addCONSTANT_Utf8 (classJVMName, true);
// TODO: this should do uniqueness checking:
return m_constants.add (new CONSTANT_Class_info (name_index));
|
public int | addField(java.lang.String name, java.lang.String descriptor, int access_flags)Adds a new declared field to this class [with no attributes]
// TODO: support Fields with initializer attributes?
// TODO: no "already exists" check done here
final int name_index = addCONSTANT_Utf8 (name, true);
final int descriptor_index = addCONSTANT_Utf8 (descriptor, true);
final Field_info field = new Field_info (access_flags, name_index, descriptor_index,
ElementFactory.newAttributeCollection (0));
return m_fields.add (field);
|
public int | addField(java.lang.String name, java.lang.String descriptor, int access_flags, IAttributeCollection attributes)Adds a new declared field to this class [with given attributes]
// TODO: support Fields with initializer attributes?
// TODO: no "already exists" check done here
final int name_index = addCONSTANT_Utf8 (name, true);
final int descriptor_index = addCONSTANT_Utf8 (descriptor, true);
final Field_info field = new Field_info (access_flags, name_index, descriptor_index, attributes);
return m_fields.add (field);
|
public int | addFieldref(Field_info field)Adds a reference to a field declared by this class.
// TODO: keepUnique flag
final CONSTANT_NameAndType_info nametype = new CONSTANT_NameAndType_info (field.m_name_index, field.m_descriptor_index);
final int nametype_index = m_constants.add (nametype); // TODO: unique logic
return m_constants.add (new CONSTANT_Fieldref_info (m_this_class_index, nametype_index));
|
public int | addFieldref(int offset)Adds a reference to a field declared by this class.
// TODO: keepUnique flag
final Field_info field = m_fields.get (offset);
final CONSTANT_NameAndType_info nametype = new CONSTANT_NameAndType_info (field.m_name_index, field.m_descriptor_index);
final int nametype_index = m_constants.add (nametype); // TODO: unique logic
return m_constants.add (new CONSTANT_Fieldref_info (m_this_class_index, nametype_index));
|
public int | addMethod(Method_info method)
return m_methods.add (method);
|
public int | addNameType(java.lang.String name, java.lang.String typeDescriptor)
final int name_index = addCONSTANT_Utf8 (name, true);
final int descriptor_index = addCONSTANT_Utf8 (typeDescriptor, true);
return m_constants.add (new CONSTANT_NameAndType_info (name_index, descriptor_index));
|
public int | addStringConstant(java.lang.String value)
final int value_index = addCONSTANT_Utf8 (value, true);
// TODO: const uniqueness
return m_constants.add (new CONSTANT_String_info (value_index));
|
public java.lang.Object | clone()Performs a deep copy.
try
{
final ClassDef _clone = (ClassDef) super.clone ();
// do deep copy:
_clone.m_version = (int []) m_version.clone ();
_clone.m_constants = (IConstantCollection) m_constants.clone ();
_clone.m_interfaces = (IInterfaceCollection) m_interfaces.clone ();
_clone.m_fields = (IFieldCollection) m_fields.clone ();
_clone.m_methods = (IMethodCollection) m_methods.clone ();
_clone.m_attributes = (IAttributeCollection) m_attributes.clone ();
return _clone;
}
catch (CloneNotSupportedException e)
{
throw new InternalError (e.toString ());
}
|
public final long | computeSUID(boolean skipCLINIT)This follows the spec at http://java.sun.com/j2se/1.4.1/docs/guide/serialization/spec/class.doc6.html#4100
as well as undocumented hacks used by Sun's 1.4.2 J2SDK
long result = m_declaredSUID;
if (result != 0L)
return result;
else
{
try
{
final ByteArrayOStream bout = new ByteArrayOStream (1024); // TODO: reuse these
final DataOutputStream dout = new DataOutputStream (bout);
// (1) The class name written using UTF encoding:
dout.writeUTF (Types.vmNameToJavaName (getName ())); // [in Java format]
// (2) The class modifiers written as a 32-bit integer:
// ACC_STATIC is never written for nested classes/interfaces;
// however, ACC_SUPER must be ignored:
{
// this is tricky: for static/non-static nested classes that
// were declared protected in the source the usual access flags
// will have ACC_PUBLIC set; the only way to achieve J2SDK
// compatibility is to recover the source access flags
// from the InnerClasses attribute:
final int [] nestedAccessFlags = new int [1];
final int modifiers = (isNested (nestedAccessFlags)
? nestedAccessFlags [0]
: getAccessFlags ())
& (ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT);
// if/when emma decides to instrument interfaces for <clinit>
// coverage, compensate for javac bug in which ABSTRACT bit
// was set for an interface only if the interface declared methods
// [Sun's J2SDK]:
dout.writeInt (modifiers);
}
// not doing another J2SDK compensation for arrays, because
// we never load/instrument those
// (3) The name of each interface sorted by name written using UTF encoding
{
final IInterfaceCollection interfaces = getInterfaces ();
final String [] ifcs = new String [interfaces.size ()];
final int iLimit = ifcs.length;
for (int i = 0; i < iLimit; ++ i)
{
// [in Java format]
ifcs [i] = Types.vmNameToJavaName (((CONSTANT_Class_info) m_constants.get (interfaces.get (i))).getName (this));
}
Arrays.sort (ifcs);
for (int i = 0; i < iLimit; ++ i)
{
dout.writeUTF (ifcs [i]);
}
}
// (4) For each field of the class sorted by field name (except
// private static and private transient fields):
// a. The name of the field in UTF encoding.
// b. The modifiers of the field written as a 32-bit integer.
// c. The descriptor of the field in UTF encoding
{
final IFieldCollection fields = getFields ();
final FieldDescriptor [] fds = new FieldDescriptor [fields.size ()];
int fcount = 0;
for (int f = 0, fLimit = fds.length; f < fLimit; ++ f)
{
final Field_info field = fields.get (f);
final int modifiers = field.getAccessFlags ();
if (((modifiers & ACC_PRIVATE) == 0) ||
((modifiers & (ACC_STATIC | ACC_TRANSIENT)) == 0))
fds [fcount ++] = new FieldDescriptor (field.getName (this), modifiers, field.getDescriptor (this));
}
if (fcount > 0)
{
Arrays.sort (fds, 0, fcount);
for (int i = 0; i < fcount; ++ i)
{
final FieldDescriptor fd = fds [i];
dout.writeUTF (fd.m_name);
dout.writeInt (fd.m_modifiers);
dout.writeUTF (fd.m_descriptor);
}
}
}
// (5) If a class initializer exists, write out the following:
// a. The name of the method, <clinit>, in UTF encoding.
// b. The modifier of the method, ACC_STATIC, written as a 32-bit integer.
// c. The descriptor of the method, ()V, in UTF encoding.
// (6) For each non-private constructor sorted by method name and signature:
// a. The name of the method, <init>, in UTF encoding.
// b. The modifiers of the method written as a 32-bit integer.
// c. The descriptor of the method in UTF encoding.
// (7) For each non-private method sorted by method name and signature:
// a. The name of the method in UTF encoding.
// b. The modifiers of the method written as a 32-bit integer.
// c. The descriptor of the method in UTF encoding.
// note: although this is not documented, J2SDK code uses '.''s as
// descriptor separators (this is done for methods only, not for fields)
{
final IMethodCollection methods = getMethods ();
boolean hasCLINIT = false;
final ConstructorDescriptor [] cds = new ConstructorDescriptor [methods.size ()];
final MethodDescriptor [] mds = new MethodDescriptor [cds.length];
int ccount = 0, mcount = 0;
for (int i = 0, iLimit = cds.length; i < iLimit; ++ i)
{
final Method_info method = methods.get (i);
final String name = method.getName (this);
if (! hasCLINIT && IClassDefConstants.CLINIT_NAME.equals (name))
{
hasCLINIT = true;
continue;
}
else
{
final int modifiers = method.getAccessFlags ();
if ((modifiers & ACC_PRIVATE) == 0)
{
if (IClassDefConstants.INIT_NAME.equals (name))
cds [ccount ++] = new ConstructorDescriptor (modifiers, method.getDescriptor (this));
else
mds [mcount ++] = new MethodDescriptor (name, modifiers, method.getDescriptor (this));
}
}
}
if (hasCLINIT && ! skipCLINIT)
{
dout.writeUTF (IClassDefConstants.CLINIT_NAME);
dout.writeInt (ACC_STATIC);
dout.writeUTF (IClassDefConstants.CLINIT_DESCRIPTOR);
}
if (ccount > 0)
{
Arrays.sort (cds, 0, ccount);
for (int i = 0; i < ccount; ++ i)
{
final ConstructorDescriptor cd = cds [i];
dout.writeUTF (IClassDefConstants.INIT_NAME);
dout.writeInt (cd.m_modifiers);
dout.writeUTF (cd.m_descriptor.replace ('/", '."));
}
}
if (mcount > 0)
{
Arrays.sort (mds, 0, mcount);
for (int i = 0; i < mcount; ++ i)
{
final MethodDescriptor md = mds [i];
dout.writeUTF (md.m_name);
dout.writeInt (md.m_modifiers);
dout.writeUTF (md.m_descriptor.replace ('/", '."));
}
}
}
dout.flush();
if (DEBUG_SUID)
{
byte [] dump = bout.copyByteArray ();
for (int x = 0; x < dump.length; ++ x)
{
System.out.println ("DUMP[" + x + "] = " + dump [x] + "\t" + (char) dump[x]);
}
}
final MessageDigest md = MessageDigest.getInstance ("SHA");
md.update (bout.getByteArray (), 0, bout.size ());
final byte [] hash = md.digest ();
if (DEBUG_SUID)
{
for (int x = 0; x < hash.length; ++ x)
{
System.out.println ("HASH[" + x + "] = " + hash [x]);
}
}
// final int hash0 = hash [0];
// final int hash1 = hash [1];
// result = ((hash0 >>> 24) & 0xFF) | ((hash0 >>> 16) & 0xFF) << 8 | ((hash0 >>> 8) & 0xFF) << 16 | ((hash0 >>> 0) & 0xFF) << 24 |
// ((hash1 >>> 24) & 0xFF) << 32 | ((hash1 >>> 16) & 0xFF) << 40 | ((hash1 >>> 8) & 0xFF) << 48 | ((hash1 >>> 0) & 0xFF) << 56;
for (int i = Math.min (hash.length, 8) - 1; i >= 0; -- i)
{
result = (result << 8) | (hash [i] & 0xFF);
}
return result;
}
catch (IOException ioe)
{
throw new Error (ioe.getMessage ());
}
catch (NoSuchAlgorithmException nsae)
{
throw new SecurityException (nsae.getMessage());
}
}
|
public final int | getAccessFlags()
return m_access_flags;
|
public IAttributeCollection | getAttributes()
return m_attributes;
|
public IConstantCollection | getConstants()
return m_constants;
|
public final long | getDeclaredSUID()
return m_declaredSUID;
|
public IFieldCollection | getFields()
return m_fields;
|
public int[] | getFields(java.lang.String name)
return m_fields.get (this, name);
|
public IInterfaceCollection | getInterfaces()
return m_interfaces;
|
public long | getMagic()
return m_magic;
|
public IMethodCollection | getMethods()
return m_methods;
|
public int[] | getMethods(java.lang.String name)
return m_methods.get (this, name);
|
public java.lang.String | getName()
return getThisClass ().getName (this);
|
public com.vladium.jcd.cls.constant.CONSTANT_Class_info | getSuperClass()
return (CONSTANT_Class_info) m_constants.get (m_super_class_index);
|
public int | getSuperClassIndex()
return m_super_class_index;
|
public com.vladium.jcd.cls.constant.CONSTANT_Class_info | getThisClass()
return (CONSTANT_Class_info) m_constants.get (m_this_class_index);
|
public int | getThisClassIndex()
return m_this_class_index;
|
public int[] | getVersion()
return m_version;
|
public boolean | isInterface()
return (m_access_flags & ACC_INTERFACE) != 0;
|
public boolean | isNested(int[] nestedAccessFlags)
final InnerClassesAttribute_info innerClassesAttribute = m_attributes.getInnerClassesAttribute ();
if (innerClassesAttribute == null)
return false;
else
return innerClassesAttribute.makesClassNested (m_this_class_index, nestedAccessFlags);
|
public boolean | isSynthetic()
return m_attributes.hasSynthetic ();
|
public Method_info | newEmptyMethod(java.lang.String name, java.lang.String descriptor, int access_flags)
// TODO: flag for making synthetic etc
final int attribute_name_index = addCONSTANT_Utf8 (Attribute_info.ATTRIBUTE_CODE, true);
final int name_index = addCONSTANT_Utf8 (name, true);
final int descriptor_index = addCONSTANT_Utf8 (descriptor, true);
final IAttributeCollection attributes = ElementFactory.newAttributeCollection (0);
final CodeAttribute_info code = new CodeAttribute_info (attribute_name_index, 0, 0,
CodeAttribute_info.EMPTY_BYTE_ARRAY,
AttributeElementFactory.newExceptionHandlerTable (0),
ElementFactory.newAttributeCollection (0));
attributes.add (code);
final Method_info method = new Method_info (access_flags, name_index, descriptor_index, attributes);
return method;
|
public final void | setAccessFlags(int flags)
m_access_flags = flags;
|
public final void | setDeclaredSUID(long suid)
m_declaredSUID = suid;
|
public void | setMagic(long magic)
m_magic = magic;
|
public void | setSuperClassIndex(int super_class_index)
m_super_class_index = super_class_index;
|
public void | setThisClassIndex(int this_class_index)
m_this_class_index = this_class_index;
|
public void | setVersion(int[] version)
m_version [0] = version [0];
m_version [1] = version [1];
|
public void | writeInClassFormat(com.vladium.jcd.lib.UDataOutputStream out)
if (out == null) throw new IllegalArgumentException ("null input: out");
out.writeU4 (m_magic);
out.writeU2 (m_version [1]);
out.writeU2 (m_version [0]);
m_constants.writeInClassFormat (out);
out.writeU2 (m_access_flags);
out.writeU2 (m_this_class_index);
out.writeU2 (m_super_class_index);
m_interfaces.writeInClassFormat (out);
m_fields.writeInClassFormat (out);
m_methods.writeInClassFormat (out);
m_attributes.writeInClassFormat (out);
|