I am trying to wrap my head around this concept. My questions are:
Is this operation costly from a performance point of view, and if so, why?
If I am trying to intercept some parameters being passed to a method by injecting some code after the method is called, does this injection happen once or does it happen every time the method is called?
Where does this injection code reside? In the application source itself or somewhere else?
You can achieve bytecode injection with Java Agents.
A java Agent is a library that intercepts the bytecode loading at the classloader, and enhances it before it is loaded in the JVM. Of course, such a library usually relies on bytecode manipulation librairies such as Javassist, ASM or CGLib.
So the bytecode manipulation is only done once, when the class is loaded.
See the official Javadoc :
http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html
This article explains how to do pretty much what you want to:
http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html
Also, if you're really interested in bytecode fundamentals, this article from one of the JRebel developers should please you:
http://arhipov.blogspot.com/2011/01/java-bytecode-fundamentals.html
Finally, you can take a look at Seren, a librairy I just began to write. It is a Java Agent that enhances serializable classes. It's just the beginning, but it works.
https://github.com/oliviercroisier/seren
Related
Currently I'm trying to modify method bodies residing in classes already loaded by the JVM. I'm aware of the JVM actually not allowing to change the definition of classes that have already been loaded. But my researches brought me to implementations like JRebel or Java Instrumentation API, both using an agent-based approach. I know how to do it right before a class is loaded o behalf of Javassist. But considering e.g. JRebel in an EJB environment where class definitions are loaded on application startup, shouldn't bytecode modification be possible on JVM-loaded classes?
Well, you learned that the Instrumentation API exists and it offers redefinition of classes as an operation. So then it is time to rethink you initial premise of “the JVM actually not allowing to change the definition of classes that have already been loaded”.
You should note that
as the links show, the Instrumentation API is part of the standard API
the support of redefinition of classes is, however, optional. You may ask whether the current JVM supports this feature
it might be limited to not support every class; you may ask whether it’s possible for a particular class
Even if it is supported, the changes may be limited, to cite the documentation:
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.
at the time you perform the redefinition, there might be threads executing code of methods of these classes; these executions will complete using the old code then
So the Instrumentation is merely useful for debugging and profiling, etc.
But other frameworks, like EJB containers, offering class reloading in production code, usually resort to creating new ClassLoaders which create different versions of the classes which then are entirely independent to the older versions.
In a Java runtime environment, the identity of a class consists of a pair of <ClassLoader, Qualified Name> rather than just a qualified name…
I wasn't aware that you can use the instrumentation API to redefine classes (see #Holger's answer). However, as he notes, there are some significant limitations on that approach. Furthermore, the javadoc says:
"This method is intended for use in instrumentation, as described in the class specification."
Using it to materially change the semantics of a class is ... all sorts of bad from the perspective of the Java type system.
We use interceptors to measure the execution time of a bean's public method invocation. nonetheless, when a bean's method invoke other private methods, it seems to ignore the audit interceptor.
How can we measure the execution time of private methods as well?
Using AOP
You could implement a benchmarker using an Aspect-Oriented Programming library like AspectJ.
For instance, see:
this SO question on Catching Private or Inner Methods with AspectJ,
or this article on Profiling with AspectJ.
Using a Profiler
You could implement your own agent extension (for instance, for JProfiler).
Or you could give up on your interceptors and simply inspect from any profiler allow to capture snapshots and to record execution times.
Using JVMTI
Which is what some profilers do, actually.
You could resort to using the JVMTI API (not entirely sure this would fly, to be honest) to implement your own code inspector and directly hook yourself into the JVM.
The Sneaky and Evil Inlining Issue
Regarding jb's (valid) concern in his answer that private methods might be inlined at either compilation time or runtime, some JVMs may not do it or allow to disable this feature.
Oracle's JRockit has a -XnoOpt option that would disable optimizations (including this particular one).
Oracle/Sun's HotSpot at least used to have -XX:-Inline (not sure it still exists or does anything).
However, it means you don't measure exactly what you'd have in production when the inlining is activated. Still, probably handy for inspecting your code.
Interceptors are applied by EJB container on invocation of interface methods - your private methods are invisible to it. What about using profiling tool instead?
Well AFAIK private methods can be inlined at JVM lesiure (even at compilation time), so they can't be profiled since they might not exist in bytecode.
I suppose you could mark your methods protected --- so they will not be inlined even in production, and then profile it.
If you want to profile your test instance you might try visualvm --- visualvm is a very nice alternative. VisualVM is a graphical tool to profile JVM istances that does all the instrumentation needed. http://visualvm.java.net/. Moreover it is a standard tool in most jdk distros.
Is it possible to listen to a method execution of an instance or all instances of a class, without modifying their code ?
Something like:
someInstance.addMethodExecutionListener('methodName', handler);
SomeClass.addMethodExecutionListener('methodName', handler);
It would be for logging purposes...
What you're asking about is a small subset of what you can do with Aspect Oriented Programming. It's not supported in plain Java and its implementations, but it's the central reason for AspectJ.
Depending on the environment you could use different technologies. Spring provides Aspects that you can bind to certain events (e.g. method execution).
If you are in a Java EE container managed environment you can use Interceptors for EJBs or SoapHandlers for Web Services.
One approach is to use the tooling API, JVMTI (replaces the separate debugging and profiling APIs).
Otherwise, you could rewrite the class files to insert your code before the method code. It's not necessarily easy. ASM is good for bytecode manipulation at a low level, but you might want to use some library (or write your own) or possibly use some "aspect" tool.
Bytecode can easily be rewritten "on disc" before loading, or at runtime using the instrumentation API and -javaagent: on the command line.
We have huge codebase and some classes are often used via reflection all over the code. We can safely remove classes and compiler is happy, but some of them are used dynamically using reflection so I can't locate them otherwise than searching strings ...
Is there some reflection explorer for Java code?
No simple tool to do this. However you can use code coverage instead. What this does is give you a report of all the line of code executed. This can be even more useful in either improving test code or removing dead code.
Reflections is by definition very dynamic and you have to run the right code to see what it would do. i.e. you have to have reasonable tests. You can add logging to everything Reflection does if you can access this code, or perhaps you can use instrumentation of these libraries (or change them directly)
I suggest, using appropriately licensed source for your JRE, modifying the reflection classes to log when classes are used by reflection (use a map/WeakHashMap to ignore duplicates). Your modified system classes can replace those in rt.jar with -Xbootclasspath/p: on the command line (on Oracle "Sun" JRE, others will presumably have something similar). Run your program and tests and see what comes up.
(Possibly you might have to hack around issues with class loading order in the system classes.)
I doubt any such utility is readily available, but I could be wrong.
This is quite complex, considering that dynamically loaded classes (via reflection) can themselves load other classes dynamically and that the names of loaded classes may come from variables or some runtime input.
Your codebase probably does neither of these. If this a one time effort searching strings might be a good option. Or you look for calls to reflection methods.
As the other posters have mentioned, this cannot be done with static analysis due to the dynamic nature of Reflection. If you are using Eclipse, you might find this coverage tool to be useful, and it's very easy to work with. It's called EclEmma
Are there any Java runtime exploring tools? I mean the tools allowing to invoke concrete objects' methods in the running application (to check the correct behavior). It would be nice if I could substitute the object with another object of this type also, may be instantiated from sketch or deserialized from some source. As I looked, usual debuggers are limited in this possibilities, but I dont pretend to the fact Ive checked all of them.
I would suggest bytecode manipulation frameworks like ASM or BCEL for this purpose.
I would use basic jUnit and EasyMock for creating different input mock objects to check the behavior of your class in different situations. Then in the end you have a nice set of unit tests to maintain your codebase.
You should be able to achieve this at a higher level than direct bytecode manipulation using AOP tools such as AspectJ. Here are a couple of pointers:
http://www.ibm.com/developerworks/java/library/j-aspectj2/
http://danielroop.com/blog/2007/10/04/jmock-and-aspectj/