0

At some point in my program I need the initial class file bytes (the bytes describing the class before any transformations were applied). The methods I evaluated so far are:

  • Using the corresponding classloader to get the resource and simply loading the byte array again. This won't work for dynamically generated classes though (ASM, proxies, etc).

  • Storing a reference to the initial class file bytes in a ClassFileTransformer. While this works it means that I need to proactively store all byte arrays for all classes in case I need some of them later one. No cool.

  • Pretty much the same as above but using JVMTIs ClassFileLoadHook. The issue is the same as with the ClassFileTransformer though.

  • I checked what is happening when Instrumentation.retransformClasses is called. In the end this comes down to a native method needing the instanceKlassHandles to get the class file bytes. So nothing I can really access as well (at least I wouldn't know how).

Any other ideas for how I could get the initial class file bytes without storing a reference to the bytes for all classes upfront?

Haasip Satang
  • 457
  • 3
  • 17
  • just wondering - why do you need this? maybe you can reformulate requirements and find another solution? – Iłya Bursov Apr 24 '17 at 23:08
  • As you state yourself, the `ClassLoader` approach may fail for generated classes and all other approaches are basically the same. They all suffer from the fact that there is no guaranty that your agent is the first one in the list, further, Instrumentation doesn’t have to be supported for all classes, so you are back where you started from. And in case of retransformation, you won’t get the exact initial bytes, only equivalent bytecode… – Holger Apr 24 '17 at 23:18
  • @Holger the order I guess I can guarantee as I have control over how the app is started. But even if my transformer would be the first one in the list that would mean I'd need to keep a copy a all class file bytes which would consume memory. As for the retransformation, equivalent byte code would be good enough. Any other idea than what I've tried already? – Haasip Satang Apr 24 '17 at 23:42
  • @Lashane Unfortunately I can't give details about the project here. All I can say is that the original, untransformed class bytes are needed. I hope the question shows that I've done some research already before asking. Any idea why it was down voted? – Haasip Satang Apr 24 '17 at 23:49
  • For a Java Agent, the combination of [`Class[] getAllLoadedClasses()`](https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#getAllLoadedClasses--) and [`void retransformClasses(Class[])`](https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#retransformClasses-java.lang.Class...-) should be sufficient to get the (equivalent) byte code of all classes. As said, there is no general guaranty that all classes are transformable, but in HotSpot, they are. – Holger Apr 25 '17 at 12:56
  • Yes,the only doubt I have is that while I can guarantee the order of the agents I can't control what they are doing and if they are implemented in a proper way to handle retransformations. So in order to avoid potential issues (with agents leading to class schema changes, etc) I was thinking to just return an invalid class file from the first agent and handle the `ClassFormatError`. This would prevent other transformers from actually doing something useful with it (and potentially adding their logic twice). Definitely hacky but it's the only way I see to stop the process. Better ideas? – Haasip Satang Apr 25 '17 at 17:27

0 Answers0