Oliver Watkins
Oliver Watkins

Reputation: 13489

Java Reflection : looking at the lines of code in a method?

I want be able to extract the insides of a method using java reflection (or any other method that might exist).

I have a test data where i am generating different styles of charts. I want to be able to display the chart, and then in a panel next to it, display the java code that created that chart.

All I need to do is to get into these methods, and pull out the insides. Does reflection allow this?

chart = TestData.createChart1();
chart.display()
chart = TestData.createChart2();
chart.display()
chart = TestData.createChart3();
    ...
chart = TestData.createChartN();
chart.display()

Inside one of my methods i might have something like this :

public static PieChart createChart1() {

    //I WANT ALL THE CODE FROM HERE....

    ArrayList<Segment> values = new ArrayList<Segment>();
    values.add(new Segment(0, null, 15, "music", Color.RED));
    values.add(new Segment(0, null, 52, "photos", Color.BLUE));
    values.add(new Segment(0, null, 33, "applications", Color.GREEN));

    PieChart pieChart = new PieChart(values, "Disk Space Usage");

    pieChart.width = 600;
    pieChart.height = 600;
    pieChart.topOffset = 50;
    pieChart.leftOffset = 50;
    pieChart.rightOffset = 50;
    pieChart.bottomOffset = 50;
    pieChart.initialWidth = 100;
    pieChart.incrementWidth = 50;

    //TO HERE....

    return pieChart;
}

Upvotes: 1

Views: 1741

Answers (2)

Ira Baxter
Ira Baxter

Reputation: 95326

The good part about reflection is that it gives a program access to some aspects of its source code. The not so good part is that what you can get it is determined and therefore limited by the language designers and implementers. The raw source code is one part that they reasonably don't want to offer. If they did so, every compiled reflective system would contain it source code and that would create a vast intellectual property leak.

If you want programmatic access to the full content of computer programs (including those in Java), the class of tools called Program Transformation (PTS) systems are ideal. These tools are generally designed to parse the source code language of interest, build internal compiler data structures (typically abstract syntax trees or ASTs) containing the complete equivalent of source code (often including precise source code position information). The really useful part from OP's point of view is that the PTS can usually invert the parsing process, and regenerate the source (or a designated part) from the internal structures. As an alternative, one can use the precise source position information to extract the original text from the original files; this is mostly only useful if you care about exact formatting and/or what's in the whitespace.

To get OP's effect using our DMS Software Reengineering Toolkit, one would use DMS's Java front end, and code a custom tool with roughly the following code:

       (include `Java~v7/ParserComponent.par')
        ...
       (local (;; [myFile string] 
                  [myTree AST:Tree]
              );;
           ...
           (= myFile ... )  ; get a file path from somewhere
           (= myTree (ParserComponent:Parse myFile ...))
           (AST:ScanTree myTree
                 (procedure [subtree AST:Tree]
                     (;;  (ifthen (== (AST:subtree Grammar:Nonterminals:_method_declaration))
                               (;;  (ParserComponent:PrettyPrintFidelity
                                         (AST:GetNthGrammarChild myTree 3) ; the method body
                                         ...
                                     )
                               );;
                          )

                          (return ~t) ; signal to ScanTree to continue looking 
                     );;
                 )
           )AST
       )local

Note the tree scan (think of this as a visitor) that hunts for AST nodes of type "method_declaration", a term taken literally from the Java grammar. Having found such an AST node type, it navigates to the method body and calls DMS's prettyprinter to regenerate text in Fidelity mode, which reproduces the original indentation and line breaks, and the comments, from the original source code. [All of this information is in DMS's trees].

If OP wants a specifically named method; he would use DMS's NameResolver component, which builds a full symbol table including for each definition a reference (specifically to a tree) to the source code point that provides the definition. Then one could look up a qualified name using that symbol table, grab the defining tree, and print it.

Upvotes: 2

pdem
pdem

Reputation: 4067

  1. java reflexion doesn't allow to read the line of codes, and the pcode on wich the reflexion rely doesn't contain the source code, only the compiled code, if it was compiled with debug options, also the line numbers.

  2. Since your method "createChart" only creates an object, you could only analyze the content of the result object (the "chart")

    chart = TestData.createChart1();
    analyze(chart);
    chart.display();
    

Then in your "analyze" method do whatever you want to display the objet, like a Json Serialision, Xml ... or simply a toString if the result is exploitable.

Upvotes: 0

Related Questions