java - Modifying line numbers in Javassist -


so have been using javassist bit lately, , have run question haven't been able find answer to. insertat method of ctmethod allows insert code @ specific line number, overwrite line or keep it, , how make opposite of default? have application modifies source before runtime javassist, based on 'hooks' in xml file. want make line can overridden, or line can placed above line instead of overriding it. there hackish ways that, i'd rather use proper way.

the easy part

the method insertat(int linenumber, string src) present in ctmethod object allows injecting code written in src before code in given line.

for instance, take following (simple) example program:

public class testsubject {     public static void main(string[] args) {      testsubject testsubject = new testsubject();      testsubject.print();    }     private void print() {     system.out.println("one"); // line 9     system.out.println("two"); // line 10     system.out.println("three"); // line 11    } } 

by coding (keep in mind method variable must ctmethod representation of print method):

   // notice said line 10, sysout of "two"    method.insertat(10, true, "system.out.println(\"one , half\");"); 

will inject new sysout instruction in class. output of new class be:

 1  1 , half  2   3 

the hard part

javassist not provide easy way remove line of code, if want replace you'll have no choice hack way through.

how it? well, let me introduce new friend (if don't know yet), codeattribute object.

the codeattribute object responsible holding bytecode represents method flow besides code attribute has attribute called linenumberattribute helps map line numbers bytecode array. summing object has need!

the idea in following example quite simple. relate bytes in bytecode array line should removed , substitute bytes no operation code.

once again, method ctmethod representation of method print

    // let's erase sysout "two"     int linenumbertoreplace = 10;     // access code attribute     codeattribute codeattribute = method.getmethodinfo().getcodeattribute();      // access linenumberattribute     linenumberattribute linenumberattribute = (linenumberattribute)      codeattribute.getattribute(linenumberattribute.tag);      // index in bytecode array instruction starts     int startpc = linenumberattribute.tostartpc(linenumbertoreplace);      // index in bytecode array following instruction starts     int endpc = linenumberattribute.tostartpc(linenumbertoreplace+1);      system.out.println("modifying " + startpc + " " + endpc);      // let's bytecode array     byte[] code = codeattribute.getcode();     (int = startpc; < endpc; i++) {       // change byte no operation code        code[i] = codeattribute.nop;     } 

running modification in original testsubject class, result in injected class following output:

 1  3 

summing up

when have need add line , still keeping existing one, need use example given in the easy part if want replace line, have first remove existing line using example given in the hard part , inject new line using 1st example.

also keep in mind in examples assumed comfortable basics of javassist showing juicy parts, instead of deal. that's why, instance, in examples there no ctclass.writefile... still need it, left out because expect should know have it.

if need in code examples, ask. i'll glad help.


Comments

Popular posts from this blog

android - getbluetoothservice() called with no bluetoothmanagercallback -

sql - ASP.NET SqlDataSource, like on SelectCommand -

ios - Undefined symbols for architecture armv7: "_OBJC_CLASS_$_SSZipArchive" -