Byteman 2.1.2 is for the most part a maintenance update to release 2.1.0, fixing about half a dozen bugs. However, it does include a few new features. In particular:
- Allow downcasts when initialising local vars in the BIND clause
- Support computing object size as a standard method in Helper
class Foo
{
void foo(List names)
. . .
}
downcasting allows you to bind elements of the argument list using the type String rather than the generic type Object
RULE access name as a name
CLASS Foo
METHOD foo
BIND first : String = $names.get(0);
second : String = $names.get(1);
IF first == "Andrew" && second == "Dinn"
DO throw new Exception("Won't get fooed again!")
ENDRULE
Of course, Byteman performs a checkcast before binding the variables so when the rule executes if you try to downcast a value which is not an instance of the subtype your program will see a ClassCastException.
If you want to disable downcasting and revert to the old behaviour where the type checker flags this as a type error the simply set system property
org.jboss.byteman.disallow.downcasts
in the JVM running the Byteman agent.
Hi,
ReplyDeleteyou are writing about new feature of byteman:
Support computing object size as a standard method in Helper
Can you provide any sample code for this functionality?
Thanks
Hi,
ReplyDeleteThis functionality is available with the latest release (2.1.2). The default helper class now provides a method with signature
public long getObjectSize(Object o);
This means that you can call this method as a built-in operation in your rules. Lets assume you havea class ByteArrayCache which hands out byte[] arrays on demand and then caches them when a client releases them for reuse. i.e.
class ByteArrayCache
{
public byte[] allocate(int minimumSize) { ... }
public void reuse(byte[] byteArray) { ... }
. . .
}
So, you might write some rules like this:
CLASS ByteArrayCache
METHOD allocate(int)
AT EXIT
BIND size = getObjectSize($!)
IF TRUE
DO traceln("allocated = " + incrementCounter("allocateCount", size))
ENDRULE
CLASS ByteArrayCache
METHOD reuse(byte[])
AT EXIT
BIND size = getObjectSize($1)
IF TRUE
DO traceln("allocated = " + decrementCounter("allocateCount", size))
ENDRULE
These rules trace how much byte[] storage has been handed out by class ByteArrayCache. In the first rule $! refers to a byte[] returned by allocate(). In the second rule $1 refers to the byte[] returned to the cache in the call to release().
Notice that in rule 1 you cannot use the size argument as the byte[] may be bigger than the required size. You could estimate the size using $!.length in the first rule and $1.length in the second rule but that only counts the number of bytes in the byte[]. It does not take account of how much space is used by the object header. getObjectSize returns an estimate of the total size of the byte[] including any Object header words which precede the byte contents. It is only an estimate but it is probably more accurate than just counting the bytes in the array.