Bytecode Instrumentation Example

This topic applies to Java version only. 

 

As it was mentioned before you can skip all the work of enabling TA in your classes by injecting TA awareness in their original, "unaware" code. In the current scenario this means:

  • generate the Activatable interface declaration;
  • add bind(objectContainer) method implementation;
  • generate a field to keep a reference to the corresponding Activator instance;
  • generate activate() call at the beginning of every method.

This is accomplished via a classloader that injects this code into the persistent classes when they are loaded. (Currently persistent classes have to be "tagged" by providing an appropriate ClassFilter instance.) In addition to this db4o also explicitly needs to be configured to use the (instrumenting) classloader of the persistent classes.

Let's look how it is implemented at the example.

We will use SensorPanelTA class without TA code (note that we can access fields directly without getter methods):

SensorPanelTA.java
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.taexamples.instrumented; 04 05public class SensorPanelTA { 06 07 public Object _sensor; 08 09 public SensorPanelTA _next; 10 11 public SensorPanelTA() { 12 // default constructor for instantiation 13 } 14 15 public SensorPanelTA(int value) { 16 _sensor = new Integer(value); 17 } 18 19 public SensorPanelTA createList(int length) { 20 return createList(length, 1); 21 } 22 23 public SensorPanelTA createList(int length, int first) { 24 int val = first; 25 SensorPanelTA root = newElement(first); 26 SensorPanelTA list = root; 27 while (--length > 0) { 28 list._next = newElement(++val); 29 list = list._next; 30 } 31 return root; 32 } 33 34 protected SensorPanelTA newElement(int value) { 35 return new SensorPanelTA(value); 36 } 37 38 public String toString() { 39 return "Sensor #" + _sensor; 40 } 41}

The following configuration should be used:

TAInstrumentationExample.java: configureTA
01private static Configuration configureTA() { 02 Configuration configuration = Db4o.newConfiguration(); 03 configuration.activationDepth(0); 04 // if using collections, uncomment 05 //configuration.add(new PagedListSupport()); 06 configuration.add(new TransparentActivationSupport()); 07 // configure db4o to use instrumenting classloader 08 configuration.reflectWith(new JdkReflector( 09 TAInstrumentationExample.class.getClassLoader())); 10 11 return configuration; 12 }

The main method should provide the testing code:

TAInstrumentationExample.java: main
1public static void main(String[] args) { 2 testActivation(); 3 }
TAInstrumentationExample.java: storeSensorPanel
01private static void storeSensorPanel() { 02 new File(DB4O_FILE_NAME).delete(); 03 ObjectContainer container = database(configureTA()); 04 if (container != null) { 05 try { 06 // create a linked list with length 10 07 SensorPanelTA list = new SensorPanelTA().createList(10); 08 container.set(list); 09 } finally { 10 closeDatabase(); 11 } 12 } 13 }
TAInstrumentationExample.java: testActivation
01private static void testActivation() { 02 storeSensorPanel(); 03 Configuration configuration = configureTA(); 04 05 ObjectContainer container = database(configuration); 06 if (container != null) { 07 try { 08 System.out.println("Zero activation depth"); 09 Query query = container.query(); 10 query.constrain(SensorPanelTA.class); 11 query.descend("_sensor").constrain(new Integer(1)); 12 ObjectSet result = query.execute(); 13 listResult(result); 14 if (result.size() > 0) { 15 SensorPanelTA sensor = (SensorPanelTA) result.get(0); 16 SensorPanelTA next = sensor._next; 17 while (next != null) { 18 System.out.println(next); 19 next = next._next; 20 } 21 } 22 } finally { 23 closeDatabase(); 24 } 25 } 26 }

A separate class should be used to run the instrumented example:

TAInstrumentationRunner.java
01/* Copyright (C) 2007 db4objects Inc. http://www.db4o.com */ 02 03package com.db4odoc.taexamples.instrumented; 04 05import java.lang.reflect.Method; 06import java.net.URL; 07 08import com.db4o.instrumentation.BloatClassEdit; 09import com.db4o.instrumentation.BloatInstrumentingClassLoader; 10import com.db4o.instrumentation.ByNameClassFilter; 11import com.db4o.instrumentation.ClassFilter; 12import com.db4o.ta.instrumentation.InjectTransparentActivationEdit; 13 14public class TAInstrumentationRunner { 15 16 public static void main(String[] args) throws Exception { 17 // list the classes that need to be instrumented 18 ClassFilter filter = new ByNameClassFilter(new String[] { SensorPanelTA.class.getName() }); 19 // inject TA awareness 20 BloatClassEdit edit = new InjectTransparentActivationEdit(filter); 21 // get test class and run main method 22 BloatInstrumentingClassLoader loader = new BloatInstrumentingClassLoader(new URL[]{}, TAInstrumentationRunner.class.getClassLoader(), filter, edit); 23 Class mainClass = loader.loadClass(TAInstrumentationExample.class.getName()); 24 Method mainMethod = mainClass.getMethod("main", new Class[]{ String[].class }); 25 mainMethod.invoke(null, new Object[]{ new String[]{} }); 26 } 27 // end main 28}
The instrumentation API/configuration is still under heavy development and is a subject to changes.