Wednesday, 5 December 2012

Byteman 2.1.2 has been released

Byteman 2.1.2 is now available for download. You can obtain a copy either as a binary-only or full-source zip from the project downloads page or you can depend upon the version available in the Maven Central repository.

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
Downcasting is particularly helpful when dealing with generic types when you know that a specific type parameter is used. For example when injecting into this class

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.

4 comments:

  1. Hi,
    you 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

    ReplyDelete
  2. Hi,

    This 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.

    ReplyDelete
  3. This blog is really informative i really had fun reading it.

    ReplyDelete
  4. Thanks, Raul. It's nice to be appreciated :-) I hope you have as much fun trying out Byteman.

    ReplyDelete