I am a bit new to the Java ecosystem. I am reading the ASM way (in this doc https://www.baeldung.com/java-asm ) to do Java instrumentation.
And I don't know when ASM changes the byte code, to be specific it takes effect in compile time and changes the class directly OR it changes the code at the runtime of class loading.
The ASM library is not responsible for changing bytecode at all. It’s a tool for transforming a sequence of bytes (in the class file format) into another sequence of bytes (again in the class file format), though you could also use it for just analyzing class files or generating class files from scratch.
So what you get at the end, is just a byte array.
Since it’s your own responsibility to use this byte array to effectively change a class (if that’s what you want), you are the one deciding how and when the changes apply.
You can read and write class files in a filesystem which is as trivial as reading and writing bytes from and to files. These changes will become effective the next time you start a JVM using this location as classpath or module path. If there’s a JVM already running using this location, the change may become effective when the class is loaded if it hasn’t been loaded yet.
You can use defineClass
on a MethodHandles.Lookup
to inject a class into an existing context which will supersede an existing class definition if it has not been loaded yet
You can create a custom ClassLoader
using your changed class definitions which is technically not changing classes but creating a new version in its own context. This may still be feasible for some use cases.
Actually changing classes at runtime can be done through Agents or a Debugger. Java Agents can use the Instrumentation API which allows to install class file transformers to be invoked on demand or actively trigger a transformation. The API allows both, load time transformation or changing an already loaded class but permitted changes to already loaded classes are limited.
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.