Byte Code Generation

 

ASM - asm.objectweb.org

The ASM library has been used exclusively to provide all the byte code generation. I have no hesitation in recommending as ASM. It is especially good for Developers wanting complete control over the generated byte code.

Dynamically generated subclasses


package app.data;
..
@Entity
class Order {
...
}

...

  Order order = (Order)Ebean.find(Order.class, 10);

  // classname = "app.data.Order$$EntityBean"
  String className = order.getClass().getName();

When you get a Reference/Proxy or a Bean back from a query what you are actually getting is a "Dynamically generated subclass".

In the case of app.data.Order there is a dynamically created class called Order$$EntityBean which extends Order and implements the EntityBean interface.


package app.data;
..
class Order$$EntityBean extends Order implements EntityBean {
...
}

Not really "Byte code Enhancement"

This is not done via java instrumentation nor by modifying the classloading. If one of these techniques where used then you could "enhance" the byte code for actual Order class itself. This is why I will try to avoid describing these special beans as "byte code enhanced".

Its important to note that Ebean is actually creating a second Class with a $$EntityBean suffix.

"Vanilla" Beans and "Dynamically generated subclass"


  // this is a "Vanilla" Bean
  Order orderVanilla = new Order();

  // orderRef is a "Dynamically generated subclass"
  Order orderRef = (Order)Ebean.getReference(Order.class, 23);

  // It implements the EntityBean interface
  EntityBean orderEb = (EntityBean)orderRef;

I have not used the term POJO as I believe some people may well consider orderRef a POJO. In the documentation I am going to refer to plain ordinary beans as "Vanilla" as compared with orderRef (in the example above) which is best described as a "Dynamically generated subclass".

Note: As the "Dynamically generated subclasses" implement the EntityBean interface they are often refered to in the source code as EntityBean's.

Method Interception for Lazy Loading

One of the core demands for using byte code generation is to use method interception to provide lazy loading for reference/proxy beans.


  Order orderRef = (Order)Ebean.getReference(Order.class, 23);

  // getting the Id will NOT invoke lazy loading
  orderRef.getId();

  // any call to a "getter" or "setter" on a non-transient
  // property will invoke lazy loading
  Customer cust = orderRef.getCustomer();

In the code above the customer is a non-transient property. The getter method is intercepted and the lazy loading of the bean is invoked.

The lazy loading will fetch the data for the bean and copy in the non-transient property values into the bean before returning the customer object.

Method Interception for Optimistic Concurrency Checking

The other core demand of method interception of beans in Ebean is to detect when a bean is being modified and keep its "Old/Original Values". The "Old Values" is used to perform Optimistic Concurrency checking for Beans that do not have a Version property.

There is a code example which can perhaps explain the creation of "Old Values" and setter interception.

equals and hashcode

In addition a equals and hashcode implementation can be generated and the issues surrounding this is discussed here.

Reflection Replacement

Another use of Byte code generation is to generate code to replace standard reflection. Obviously getter and setter methods are used a lot in ORM and ASM is used to generate code to replace the use of Reflection for performance reasons.

Introduction User Guide (pdf) Install/Configure Public JavaDoc Whitepapers
General Database Specific Byte Code Deployment Annotations Features
Top Bugs Top Enhancements
woResponse