I just ran into a tedious bug with my use of BCEL: I was emitting some
inner class declarations and got the byte length wrong for the
InnerClasses attribute.
Both Sun's JVM and BCEL itself don't seem to actually care about the
length field of attributes when loading a class, so I had never noticed
a problem for a long time.
But when I tried to run my stuff in IBM's websphere runtime, I
(correctly) got a class format error.
Ok, so I fixed it. The problem though is that knowing the byte length
value for attributes is a tedious and fragile thing to maintain. One has
to know the byte lengths of every piece being contributed to the
attribute's data.
It doesn't have to be this way. Why can't the Attribute class compute it
itself? This approach will work:
final public void dump(DataOutputStream file) throws IOException
{
// Dump attribute contents to an in-memory stream first so we can
compute
// the length.
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream memoryStream = new DataOutputStream(byteStream);
dumpAttribute(memoryStream);
memoryStream.close();
byteStream.close();
byte[] bytes = byteStream.toByteArray();
file.writeShort(name_index);
file.writeInt(bytes.length);
file.write(bytes, 0, bytes.length);
}
abstract protected void dumpAttribute(DataOutputStream output) throws
IOException;
The downside I see is a bit of a performance hit on dumping. However,
the benefits of improved usage outweigh that by my standards at least.
The getLength() method will not be valid until after a dump() is called,
but I could not find any usage of this query in the existing sources. I
suggest deprecating getLength() and setLength() as well.
The existing length-based constructors can be still exist but be made
deprecated, essentially ignoring the length arg. Provide new
constructors for all attribute subclasses without the length arg. This
gives a migration path.
Cheers,
Ray Blaak
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]