I've read this post which does the bytecode instrumentation in a "line by line" approach. It's clumsy and bug-prone. I wonder if Javassit supports "replacing" or "swapping" a class with an instrumented class. I see the redefineClasses method but I'm not sure it's used for that purposes, plus I can't find any examples around that.
I appreciate if anyone in SO can give me an example on using redefineClasses
in Javassist
My goal is to use Java instrumentation to extract some meaningful data inside multiple Java classes and methods, much more than just printing start/end time in those examples. That's why I think "swapping a Java class" approach is more efficient during development.
What do you guys think and recommend?
Because you are new to Java instrumentation, I want to elaborate a little more on Johannes' correct comments: I recommend you to not just read the Baeldung article but also some related javadocs.
For example, the Java 8 API documentation for Instrumentation.redefineClasses
clearly states the limitations when redefining classes:
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.
Alas, the restrictions have not been lifted as of Java 17. The same method is described there as follows:
The supported class file changes are described in JVM TI RedefineClasses.
The document pointed to basically says the same as the Java 8 documentation, only in some more detail:
The redefinition may change method bodies, the constant pool and attributes (unless explicitly prohibited). The redefinition must not add, remove or rename fields or methods, change the signatures of methods, change modifiers, or change inheritance. The redefinition must not change the
NestHost
,NestMembers
,Record
, orPermittedSubclasses
attributes. These restrictions may be lifted in future versions.
Besides, the very same restrictions apply to Instrumentation.retransformClasses
, the difference basically being that you do not start from scratch there but use existing class bytes as an input and can chain multiple transformers in order to incrementally instrument your existing class. But even with redefinition, the base line stays the original class, if it was loaded before.