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
JavaBot
JavaBot13mo ago
This post has been reserved for your question.
Hey @Koblížkáč! Please use /close or the Close 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.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
Koblížkáč
KoblížkáčOP13mo ago
note that I know how to transform the bytecode, i just need help with the obtaining and applying the bytecode
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
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?
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
why does this then prints:
No description
Koblížkáč
KoblížkáčOP13mo ago
jdk.internal.loader.ClassLoaders$AppClassLoader@5cb0d902
jdk.internal.loader.ClassLoaders$AppClassLoader@5cb0d902
0x150
0x15013mo ago
might be because its an inner class
Koblížkáč
KoblížkáčOP13mo ago
i see okay its not that
public static void main(String[] args) throws ClassNotFoundException {
CustomClassLoader customClassLoader = new CustomClassLoader();
Class<?> clazz = customClassLoader.loadClass(Main.class.getName());
System.out.println(clazz.getClassLoader());
}
public static void main(String[] args) throws ClassNotFoundException {
CustomClassLoader customClassLoader = new CustomClassLoader();
Class<?> clazz = customClassLoader.loadClass(Main.class.getName());
System.out.println(clazz.getClassLoader());
}
prints: jdk.internal.loader.ClassLoaders$AppClassLoader@5cb0d902
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
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?
0x150
0x15013mo ago
well you load the class via it that should do it
Koblížkáč
KoblížkáčOP13mo ago
well
No description
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
and can i somehow load it so i can use the class normally and have the bytecode changed?
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
what is the entry class?
0x150
0x15013mo ago
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
Koblížkáč
KoblížkáčOP13mo ago
Well but lets say id want every class to be loaded with my classloder, is it possible
0x150
0x15013mo ago
yes just make the class calling those classes loaded by your class loader
class Init {
public static void start() {
// SomeOtherClass is loaded by your class loader
SomeOtherClass.bruh();
}
}
class SomeOtherClass {
public static void bruh() {
// will also load with your class loader
}
}

class Main {
public static void main(String[] a) {
CustomClassLoader cl = new CustomClassLoader();
cl.loadClass("Init").getMethod("bruh").invoke();
}
}
class Init {
public static void start() {
// SomeOtherClass is loaded by your class loader
SomeOtherClass.bruh();
}
}
class SomeOtherClass {
public static void bruh() {
// will also load with your class loader
}
}

class Main {
public static void main(String[] a) {
CustomClassLoader cl = new CustomClassLoader();
cl.loadClass("Init").getMethod("bruh").invoke();
}
}
Koblížkáč
KoblížkáčOP13mo ago
but no way to make it be done automatically without need to use reflection?
0x150
0x15013mo ago
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
JavaBot
JavaBot13mo ago
💤 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.

Did you find this page helpful?