Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between redefine and retransform in javaagent

When packing a jar file with custom java agent, you can add the following properties:

  • Can-Redefine-Classes
  • Can-Retransform-Classes

What is the difference between those two?

If redefinition happens before class is loaded and retransformation after, then when does exactly retransformation happen?

like image 397
Average Joe Avatar asked Sep 25 '13 15:09

Average Joe


People also ask

Can redefine classes VS can Retransform classes?

redefineClasses to change the actual definition of existing (and already loaded) classes. The agent will provide the bytecode for the new definition. Retransformation refers to the process of class file transformation which is normally applied at class loading time.

What is the purpose of Javaagent?

In general, a java agent is just a specially crafted jar file. It utilizes the Instrumentation API that the JVM provides to alter existing byte-code that is loaded in a JVM. For an agent to work, we need to define two methods: premain – will statically load the agent using -javaagent parameter at JVM startup.

Can you have more than one Javaagent?

The -javaagent option may be used multiple times on the same command-line, thus starting multiple agents. The premain methods will be called in the order that the agents are specified on the command line. More than one agent may use the same <jarpath> .

What is Javaagent option?

Java agents are a special type of class which, by using the Java Instrumentation API, can intercept applications running on the JVM, modifying their bytecode.


2 Answers

They seem almost redundant in the functionality they offer us. The main difference seems to be that when we redefine a class, we supply a byte[] with the new definition out of the blue, whereas when we retransform, we get a byte[] containing the current definition via the same API, and we return a modified byte[].

Therefore, to redefine, we need to know more about the class. Consider the use-case of injecting profiling trace statements. With retransform you can do that more directly: just look at the bytecode given, modify it, and return it. But if we went the redefine route, we would need to fetch the original byte[] from somewhere (like getResourceAsStream()).

Another apparent difference is in how we interact with other class transformers; who goes first. Transforms are applied to the original or a redefined class, so several transforms can be additive, for example.

Historically, if we look at the Since comments in the API documentation, or on page 238 of this book (Friesen 2007 Beginning Java SE 6 Platform), we notice that redefinition capabilities were introduced in Java 5, and retransformation in Java 6. My guess is that retransformation was introduced as a more general capability, but redefinition had to be retained for backwards compatibility.

Quoting the key sentence about retransformation methods from the book linked above:

Agents use these methods to retransform previously loaded classes without needing to access their class files.


The second part of the question:

If redefinition happens before class is loaded and retransformation after, then when does exactly retransformation happen?

No, redefinition happens after the class is loaded, as well as retransformation. They happen when you call your Instrumentation instance's redefineClasses(..) and retransformClasses(..) methods, respectively.

Here is a question to any experts passing by: is there anything you can do by redefining classes, that you can't do by retransforming them? My guess is that the answer is "nothing".

like image 97
Evgeni Sergeev Avatar answered Sep 20 '22 13:09

Evgeni Sergeev


Redefinition means that at an arbitrary point of time an agent will invoke Instrumentation. redefineClasses to change the actual definition of existing (and already loaded) classes. The agent will provide the bytecode for the new definition.

Retransformation refers to the process of class file transformation which is normally applied at class loading time. Agents can register ClassFileTransformers which are called one after another to apply transformations to the byte code before the class will be initialized. So Retransformation refers to the capability of the JVM to repeat this process for already loaded classes. In this case an agent may invoke Instrumentation.retransformClasses specifying which classes to retransform but no bytecode. Instead the JVM will call all registered retransforming capable ClassFileTransformers providing the actual bytecode (or the result of the previous transformer for a chained transformer).

like image 40
Abhishek Srivastava Avatar answered Sep 20 '22 13:09

Abhishek Srivastava