2

I have a generic Java agent based on AspectJ that instruments methods with a certain structure. The agent should be able to work with any Java web application.

The problem - in case the method the agent tries to instrument is very very big, the generated byte code might be greater than 64k --> and as a result the instrumentation will fail, since the JVM doesn't support such methods.

Is there any way to handle such cases? I cannot control the actual application code, only the agent.

An example related to JSPs:

pointcut getJSPRequests(HttpServletRequest req, HttpServletResponse resp):
        args(req, resp) && execution(void _jspService(..));

void around(HttpServletRequest req, HttpServletResponse resp):
        getJSPRequests(req, resp) {
     callSomeMethod(thisJoinPointStaticPart.getSignature(), req, resp);
     proceed(req, resp);

}

Thanks,

Lin

Lin
  • 2,445
  • 5
  • 27
  • 37
  • 3
    Is the instrumentation code itself a significant part of the total method size? If the original size is not extremely close to the 64K limit you might be able to work around the problem by injecting helper method calls into the original code instead of bigger, literal chunks of code. Maybe you want to look what AspectJ does in such cases. BTW, what do you mean by "generic Java agent based on AspectJ"? Do you use AspectJ? If so, what kind of advice are you trying to apply with what kind of pointcut? And why on earth would anybody have methods sized 64K? They may burn in programmers' hell! ;-) – kriegaex Jan 04 '17 at 08:38
  • @kriegaex the agent code is thin, I'm using simple pointcuts that catch call(...) to some methods with a certain signature and extract some info from these methods arguments and return value, but not inside the aspect - the aspect only calls another function that does the logic. The problem is that when I tested my code on some java open source applications such as Hipergate, I encountered code parts with methods that are over 1000 lines! I couldn't instrument them at all... :( same goes when I tried to instrument _jspService() method of JSPs...these generated functions can be very very long.. – Lin Jan 04 '17 at 10:54
  • You can try `execution()` instead of `call()`, which weaves into the callee rather than into the caller. Maybe this way you can avoid instrumenting big callers, possibly in many places depending on the number and type(s) of your pointcut(s). I really need to see some code in order to provide more concrete advice. Another option is to refactor the open source stuff in order to break down methods into smaller ones. But probably there is a way around that and your aspects can be optimised. Show some or all of your code, please. You cannot circumvent JVM limits. – kriegaex Jan 04 '17 at 11:27
  • @kriegaex - I added a simple pointcut call example to _jspService. I use it to call another function and extracted the logic there. It uses execution. – Lin Jan 04 '17 at 11:35
  • Then `_jspService(..)` must be **very** close to maximum size already because the overhead should be minimal here. Is the same method maybe instrumented by other aspects or other types of Java agents, too? BTW, your `around()` advice seems to do nothing a `before()` advice could not do as well. Maybe you want to try that. You only need `around()` if in some circumstances you want to avoid proceeding or want to manipulate the parameters or the result, all of which you do not do here. – kriegaex Jan 04 '17 at 11:40
  • And BTW, call is not execution. First you said it the other way around. So now you can also try to instrument the callers instead of the callee if the latter gets too big. So just try `call()` because then the callee will not be changed at all (unless if resursively calls itself, of course). But first try my previous idea. BTW, can you share an [SSCCE](http://sscce.org/) reproducing the problem on GitHub? – kriegaex Jan 04 '17 at 11:46
  • I make sure that only one aspect per method is possible to avoid additional code parts. The jsp is the easiest example, but it also happens when I try to instrument other functions (either with call or execution). When the agent runs on open source or external customers apps that were written badly, the only way to be able to instrument is to ask them "please fix your code..." which I'd like to avoid...Or maybe to use asm to split the original function, but it seems to risky and not simple at all (if even doable...) – Lin Jan 04 '17 at 11:46
  • 1
    To me asking upstream maintainers to fix their code seems to be an obvious approach. I did that often, equipped with good "pro" arguments, and in most cases I got upstream fixes - sometimes in a few days' time, sometimes after weeks or months. Most of the time OSS developers are kinda proud of their "babies" and willing to improve their code. Specifically, huge methods are an undisputed code smell. Nobody seriously argues that they are good for anything. – kriegaex Jan 04 '17 at 11:51
  • @kriegaex - I'll try your approach, as playing with asm here seems very tricky and risky. Thanks – Lin Jan 04 '17 at 11:57
  • I am still willing to take a look at your GitHub project, if you decide to upload it (optimally including a Maven POM). – kriegaex Jan 04 '17 at 14:23

0 Answers0