December 08, 2004

Stack trace translation using annotations

Code generators and compilers that use Java as an intermediate language (e.g, JSP compilers) can take advantage of the new Java annotations feature for translating stack traces.

Why is this necessary? Any runtime error in the form of an exception will have its stack trace expressed in terms of the intermediate java code. Troubleshooting the problem could become a nightmare, unless the line and number information is presented in the context of the components and methods originally written by the developer.

In simple terms, the idea is to place line number information in metadata blocks in every class generated by the compiler. This information is accessed during runtime to interpret and translate stack traces back into something the developer will understand.

Let's consider a hypothetical component called "MyObj" that has two methods: "methodA" and "methodB". Here's an example of what the intermediate Java code might look like:

@TranslationTable(lines = {
  @Entry(line=11,component="MyObj",method="methodA",sourceLine=241),
  @Entry(line=12,component="MyObj",method="methodA",sourceLine=247),
  @Entry(line=13,component="MyObj",method="methodA",sourceLine=249),
  @Entry(line=18,component="MyObj",method="methodB",sourceLine=340)
})
public class AutogeneratedObject
{
  void autogeneratedMethod1()
  {
     int a = 1;
     int b = 2;
     autogeneratedMethod2();
  }

  void autogeneratedMethod2()
  {
     throw new RuntimeException();
  }
}


The metadata block is made of a tag (@TranslationTable) that contains a list of sub-tags (@Entry). Each entry represents a line of significant code in the generated class. Information about the line number in the generated class and the name of the original component, method and line number it maps to are stored in each entry.

Here's the definition of the Entry tag:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface Entry
{
  int line();

  String component();
  String method() default "[unknown]";
  int sourceLine();
}


And here's the TranslationTable tag:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TranslationTable
{
  Entry[] lines();
}


The stack trace translator takes each stack frame, obtains the associated class, queries the class for it's TranslationTable metadata and looks up the TranslationTableEntry for the line reported by the stack frame.

This is what the stack trace translator might look like. I know, I know, the implementation very inefficient (linear traversals of the translation tables, no caching)... I'm just trying to make a point here :)

StackTraceElement[] translate(StackTraceElement[] elements)
{
  List result = new ArrayList();

  for (StackTraceElement element : elements) {
     try {
       Class clazz = Class.forName(element.getClassName());
       TranslationTable table = (TranslationTable) clazz.getAnnotation(TranslationTable.class);

       boolean found = false;
       if (table != null) {
         for (Entry line : table.lines()) {
           if (line.line() == element.getLineNumber()) {
             result.add(new StackTraceElement(line.component(), line.method(), line.component(), line.sourceLine()));
             found = true;
             break;
           }
         }
       }

       if (table == null || !found) {
         result.add(element);
       }
     }
     catch (ClassNotFoundException e) {
       e.printStackTrace();
     }

  }

  return result.toArray(new StackTraceElement[0]);
}


If you're not in the mood for trying out the code, I already did it for you :). Here's a regular Java stack trace:

java.lang.RuntimeException
  at AutogeneratedObject.autogeneratedMethod2(Test.java:18)
  at AutogeneratedObject.autogeneratedMethod1(Test.java:13)
  at Test.main(Test.java:25)


And the translated version:

MyObj.methodB(340)
MyObj.methodA(249)
Test.main(25)

2 Comments:

Blogger The Jack said...

Thanks ever so much, very useful article. If you do not mind, please visit my article related to pandeglang district in Banten, Indonesia at Kenali dan Kunjungi Objek Wisata di Pandeglang or Kenali dan Kunjungi Objek Wisata di Pandeglang second and also Kenali dan Kunjungi Objek Wisata di Pandeglang Objek Wisata Air Terjun Curug Gendang or related to a leadership at Mengembalikan Jati Diri Bangsa and Oes Tsetnoc or Oes Tsetnoc the second and our hard work at Kerja Keras Adalah Energi Kita that's right Kerja Keras Adalah Energi Kita, and Kenali dan Kunjungi Objek Wisata di Pandeglang Memasuki Babak Akhir also Objek Wisata Taman Wisata Alam Carita, Kenali dan Kunjungi Objek Wisata di Pandeglang, or Kenali dan Kunjungi Objek Wisata di Pandeglang, also Kenali dan Kunjungi Objek Wisata di Pandeglang, or Kenali dan Kunjungi Objek Wisata di Pandeglang, also Kenali dan Kunjungi Objek Wisata di Pandeglang, or Kenali dan Kunjungi Objek Wisata di Pandeglang, also Kenali dan Kunjungi Objek Wisata di Pandeglang, or Kenali dan Kunjungi Objek Wisata di Pandeglang, very smart thank you!

October 28, 2009 11:03 PM  
Anonymous Anonymous said...

ed hardy clothes
ed hardy shirts
ed hardy jackets
ed hardy hoodies
ed hardy boots
ed hardy polo shirts
ed hardy shoes
ed hardy jeans
ed hardy outerwear
ed hardy long sleeve shirts
ed hardy bags
ed hardy winter boots
ed hardy handbags
ed hardy love kills slowly shirts
ed hardy love kills slowly shoes
ed hardy love kills slowly boots
ed hardy trousers
ed hardy mens
ed hardy womens
ed hardy t shirts
ed hardy sunglasses
ghd hair straighteners mk4
hair straightners
ghd iv styler hair straightener
ghd hair straightners
cheap ghd hair straighteners

December 08, 2009 6:56 PM  

Post a Comment

<< Home