Bytecode manipulation
I'm interested in some bytecode manipulation and want to develop a simple library which would allow you to inject annotated code into a different method(similiar to Spongepowered Mixins). The thing is that I don't know how should I approach the bytecode at first. I can:
- Create an agent, which would be loaded and would transform the bytecode
- disadvantage is that the user would have to specify the agent to be loaded, the idea was that it should've been done automatically
- Use custom gradle plugin to transform the bytecode while the jar is making
- disadvantage is that it would only support code inside the jar, so any method in classpath wouldn't work(the idea was it could be injected into any method in classpath)
Maybe there is a different approach I could use, heard fabric uses some sort of custom classloaders but I don't really know how it works
23 Replies
⌛
This post has been reserved for your question.
Hey @Koblížkáč! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
note that I know how to transform the bytecode, i just need help with the obtaining and applying the bytecode
fabric has a custom class loader which minecraft and mods get passed through, that applies the mixin when the class is loaded
when you make a classloader and ask it for a class, the class loader needs to find, load the bytes of the class and define the class using those bytes, then gives you the newly defiend Class instance
you can make your own class loader that transforms those original class bytes before defining the class, which is what fabric does
agents have a similar story but their transforming capabilities are more limited, since the class the bytes belong to is already loaded, and new changes need to conform to a certain limited set of modifications you can make to that already existing class
eg you cant add, remove or change any field descriptors or method descriptors belonging to the class, you can only change method bodies
with the classloader approach, those limitations go away since the class doesnt even exist yet. you can manipulate the raw class bytes in (almost) any way you'd like before defining the class
but you would somehow need to set the custom classloader as the default one, right? Since every class is loaded by appclassloader by default, isnt it?
all classes you load with that class loader will have that class loader as parent class loader, and ergo use that class loader by default
why does this then prints:

might be because its an inner class
i see
okay its not that
prints:
jdk.internal.loader.ClassLoaders$AppClassLoader@5cb0d902
is your class loader actually loading the class or are you passing it to another class loader down the line
like is it your class loader that is defining the class
yeah youre right i was just calling super
but in case like this:
System.out.println(Main.class.getClassLoader());
it would still print the AppClassLoader
is it possible to have it use the custom classloader?well you load the class via it
that should do it
well

Main.class is a direct request to the parent class loader
loading it via the parent sets the class loader for that Class instance
if you'd invoke anything on that Class, it would use your class loader as class loader
and can i somehow load it so i can use the class normally and have the bytecode changed?
you load the entry class from the class loader and call a method on it
that method then uses your class loader to load its classes
and that continues recursively
what is the entry class?
whatever class you define to be the entry point to the other parts of the program you want to modify
for fabric, this would be minecraft's main class
Well but lets say id want every class to be loaded with my classloder, is it possible
yes
just make the class calling those classes loaded by your class loader
but no way to make it be done automatically without need to use reflection?
the only part where you need to do anything is in the reflection part
that is you calling the init method
all methods called by that init method, all classes referenced will be loaded via your class loader
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.