java class 转 字节码,从内存中获取Java类字节码(经过多次转换)

  • Post author:
  • Post category:java


I’m working on a coremod for Minecraft, and transform a lot of the classes as they are loaded.

The problem however is that there are multiple coremods which also transform the same classes that I am, and I am getting some strange behavior that I want to look into.

Then comes the problem, how do I inspect the bytecode after it has been transformed multiple times?

When I transform it I just get an byte[] input that I run trough ASM and then return my modified bytecode.

My idea was to just to dump the class bytecode to a .class file after the class was loaded, and inspect it from there. But I can’t seem to find any way to actually get the bytecode after the class is loaded.

The closest I can find is getResource, but that returns the bytecode as it was BEFORE it was transformed, not what I want.

TLDR:

How do I get the bytecode of a class AFTER it has been modified and loaded?

-Can’t use ClassLoader.getResource as it returns unmodified version.

-Can’t get it during load time as I want to catch transforms happening after my own.

Is there some external program that can dump the in-memory bytecode or something?

Hoping someone can help me with this =)

解决方案

As far as I know, the only interface for runtime access to bytecode is provided by Java Agents. This is also how you create classfile transformers in the first place, so you should already be using one. Just modify it to dump the classfile.

Edit: As far as the order of transformation, according to the docs, it is

Retransformation incapable transformers

Retransformation incapable native transformers

Retransformation capable transformers

Retransformation capable native transformers

So ideally you’d want a retransformation capable native transformer. But writing native code is a pain. Setting your transformer to enable retransformation will help a lot, but it’s still possible for another retransformer registered later to run after you. The best option I can think of is to register your agent again. Or find all calls to register a transformer and insert yours afterwards.