Java agents are neat, but what relatively few people realize is that there are two agent APIs, one for agents written in Java and one for agents written in C++. The latter is drastically more powerful but hardly ever used. It exposes all the functionality available to Java agents like class redefinition, and then a lot more.
The C++ API gives you access to, amongst other things: manipulating the stack by reading/writing local variables or forcing early returns with values of your choice, learning what locks a thread holds, walking the heap including unreachable objects, tagging objects, adding field watches, getting the bytecodes of a method, intercepting the entire JNI API, receiving callbacks on dozens of different events including things like field modification, JITC, object allocation and the begin/end of GC.
Very few people really take advantage of this API, even though it can be used to achieve remarkable effects all against public, stable API.