Export method local variables in ASM

Source: Internet
Author: User

When a method exception occurs, you need to export the input parameter value and the local variable value for analysis. Previously, because all the tested objects are normal values, the written loadlocalvararray can work normally.

In the past few days, when the method enters, inject a long starttime is used to calculate the method execution time when the method exits. If the local variables are long and double

It occupies two locations, while nextlocal and firstlocal are the address locations of the local variable stack. The actual number of local variables and specific indexes cannot be known at all.

 

Of course, use for (INT I = 0; I <nextlocal-firstlocal; I ++ ){

Try {loadlocal (I + firstlocal)} catch (exception ex ){........}

} It is too cumbersome to use exceptions to determine whether a localindex is available.

 

Check the generatoradapter and find a private yojglist <type> localtypes. During visit, the type of the local variable will be placed in this array. However, the storage method is almost the same as that in the stack. If there are three double values, the stack is:

 

Firstlocal + 0

Firstlocal + 2

Firstlocal + 4

In this case, nextlocal-firstlocal is 6, but loadlocal (6) is definitely abnormal. This list also sets a type to the corresponding position. In this way, it needs to fill in null in the areas not above. The setting is as follows:

 

0 J

1 null

2 J

3 Null

4 J

The length of this list is 5, which can be correctly loadlocal (INDEX). But it is a private variable, so I have to add

Public int getlocallength (){
Return this. localtypes. Size ();
}

 

Note: Because the instrumention function is provided by any app on an independent day, the referenced library is called in premain. If the same library and version are used in the application, it cannot be loaded.

Import the same class because premain has been loaded before Main. To prevent version conflicts, we re-package other common app libraries. This is necessary, therefore, it is acceptable to modify the source code.

 

With this getlocallength (), it is easy to do:

 

Void loadvararray (){

Type object_type = type. getobjecttype ("Java/lang/object ");
Int varcnt = getlocallength ();
If (varcnt = 0) {// returns an empty array
Push (0 );
Newarray (object_type );
Return;
}

/*
* Check the stack space first (long and double occupy two places, one of which is marked as null). If you directly use the stack length to specify an array
* If the placeholder position is null, the return program does not know whether the placeholder is null or whether the value of localvar is null.
*/
Int arrlen = 0;
For (INT I = 0; I <varcnt; I ++ ){
Type T = getlocaltype (Super. firstlocal + I );
If (T! = NULL)
Arrlen ++;
}
Push (arrlen); // the actual length of the array
Newarray (object_type );
Int arrindex = 0;
For (INT I = 0; I <varcnt; I ++ ){
Int Index = super. firstlocal + I;
Type T = getlocaltype (INDEX );
If (t = NULL)
Continue;

DUP ();
Push (arrindex ++ );
Loadlocal (index, t );
Box (t );
Arraystore (object_type );
}
}

 

 

In this way, all the local variables are correctly loaded into the Array (the array is now at the top of the stack, and you can access it ).

 

Complete implementation:

 

Package COM. alibaba. instrumention. classop; <br/> Import COM. alibaba. citrus. ASM. methodvisitor; <br/> Import COM. alibaba. citrus. ASM. type; <br/> Import COM. alibaba. citrus. ASM. commons. adviceadapter; <br/> Import COM. alibaba. instrumention. util; <br/>/** <br/> * Comment of instrumtionadviceadapter <br/> * @ author axman. wang <br/> */<br/> public class instrumentionadviceadapter extends adviceadapter {<Br/> private string methodname; <br/> private string DESC; <br/> private string classname; <br/> private int startlocal; <br/> protected instruments onadviceadapter (methodvisitor mV, int access, string methodname, <br/> string DESC, string signature, string [] exceptions, <br/> string classname) {<br/> super (mV, access, methodname, DESC); <br/> This. methodname = methodname; <br/> This. desc = DESC; <Br/> This. classname = classname; <br/>}< br/> protected void onmethodenter () {<br/>/* invoke the statbaen */<br/> This. MV. visittypeinsn (new, util. methodinfo_classname); <br/> This. MV. visitinsn (DUP); <br/> This. MV. visitldcinsn (this. methodname); <br/> This. MV. visitldcinsn (this. DESC); <br/> This. MV. visitldcinsn (this. classname); <br/> This. MV. visitmethodinsn (invokespecial, util. methodinfo_class Name, util. cstor_name, <br/> util. methodinfo_cstor_desc); <br/> This. MV. visitmethodinsn (invokestatic, util. stat_classname, util. stat_before_name, <br/> util. stat_before_desc); <br/>/* Make a timer start variable */<br/> This. startlocal = This. newlocal (type. long_type); <br/> This. MV. visitmethodinsn (invokestatic, "Java/lang/system", "nanotime", "() J"); <br/> This. MV. visitvarinsn (lstore, startlocal ); <Br/>}< br/> protected void onmethodexit (INT opcode) {<br/> If (opcode> = ireturn & opcode <= return) {<br/> This. MV. visitmethodinsn (invokestatic, "Java/lang/system", "nanotime", "() J"); <br/> This. MV. visitvarinsn (lLoad, startlocal); <br/> This. MV. visitinsn (LSUB); <br/> This. MV. visittypeinsn (new, util. methodinfo_classname); <br/> This. MV. visitinsn (DUP); <br/> This. MV. visitldcinsn (this. metho Dname); <br/> This. MV. visitldcinsn (this. DESC); <br/> This. MV. visitldcinsn (this. classname); <br/> This. MV. visitmethodinsn (invokespecial, util. methodinfo_classname, util. cstor_name, <br/> util. methodinfo_cstor_desc); <br/> This. MV. visitmethodinsn (invokestatic, util. stat_classname, util. stat_after_name, <br/> util. stat_after_desc); <br/>} else if (opcode = athrow) {<br/> This. MV. visitinsn (DUP );// Copy exception instance of stack top <br/> This. MV. visittypeinsn (new, util. methodinfo_classname); <br/> This. MV. visitinsn (DUP); <br/> This. MV. visitldcinsn (this. methodname); <br/> This. MV. visitldcinsn (this. DESC); <br/> This. MV. visitldcinsn (this. classname); <br/> This. MV. visitmethodinsn (invokespecial, util. methodinfo_classname, util. cstor_name, <br/> util. methodinfo_cstor_desc); <br/> loadvararray (T Rue); // load the local variable array <br/> loadargarray (); // load the parameter array <br/> This. MV. visitmethodinsn (invokestatic, util. stat_classname, util. stat_error_name, <br/> util. stat_error_desc); <br/>}< br/> private void loadvararray (Boolean removeinjection) {<br/> type object_type = type. getobjecttype ("Java/lang/object"); <br/> int varcnt = getlocallength (); <br/> If (varcnt = 0) {// return an empty array <br/> push (0); <br/> New Array (object_type); <br/> return; <br/>}< br/>/* <br/> * Check the stack space first (long and double occupy two places, one of them is marked as null). If an array is directly specified with the stack length <br/> *, The placeholder position is null, the returned program does not know whether the placeholder is null or whether the value of localvar is null <br/> */<br/> int arrlen = 0; <br/> for (INT I = 0; I <varcnt; I ++) {<br/> type T = getlocaltype (super. firstlocal + I); <br/> If (T! = NULL) <br/> arrlen ++; <br/>}< br/> If (removeinjection) {<br/> arrlen --; // remove the injected startlocal <br/>}< br/> push (arrlen); // the actual length of the array <br/> newarray (object_type ); <br/> int arrindex = 0; <br/> Boolean isfirst = true; <br/> for (INT I = 0; I <varcnt; I ++) {<br/> int Index = super. firstlocal + I; <br/> type T = getlocaltype (INDEX); <br/> If (t = NULL) <br/> continue; <br/> If (removeinjection & isfirst) {<br/> isfirst = false; <br/> continue; <br/>}< br/> DUP (); <br/> push (arrindex ++); <br/> loadlocal (index, T); <br/> box (t); <br/> arraystore (object_type ); <br/>}< br/>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.