Klassen Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM

Diskutiere Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM im Allgemeine Java-Themen Bereich.
S

Skyriiy

Hallo liebes Forum,
ich bin neu im Thema ASM und versuche mit dem folgenden Code eine unbekannte bzw vom Nutzer definierte menge an Variablen in meine Klasse "ItemList" hinzufügen zu lassen. Hierzu verwende ich for-loops und eine statische variable welche die Anzahl der hinzuzufügenden Felder enthält.

Java:
protected static byte[] write() {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;

        cw.visit(52, ACC_PUBLIC + ACC_SUPER, "de/blutmondgilde/ibocore/item/ItemList", null, "java/lang/Object", null);
        cw.visitSource("ItemList.java", null);
        cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC);

        {
            fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;", "Lnet/minecraftforge/registries/DeferredRegister<Lnet/minecraft/item/Item;>;", null);
            fv.visitEnd();
        }
        {
            fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "TEST_ITEM", "Lnet/minecraftforge/fml/RegistryObject;", "Lnet/minecraftforge/fml/RegistryObject<Lnet/minecraft/item/Item;>;", null);
            fv.visitEnd();
        }
        {
            for (int i = 0; i < itemCount; i++) {
                fv = cw.visitField(
                        ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
                        ITEM_PREFIX + i,
                        "Lnet/minecraftforge/fml/RegistryObject;",
                        "Lnet/minecraftforge/fml/RegistryObject<Lnet/minecraft/item/Item;>;",
                        null);
                fv.visitEnd();
            }
        }
        {
            mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(line++, l0);
            mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/registries/ForgeRegistries", "ITEMS", "Lnet/minecraftforge/registries/IForgeRegistry;");
            mv.visitLdcInsn("ibocore");
            mv.visitMethodInsn(INVOKESTATIC, "net/minecraftforge/registries/DeferredRegister", "create", "(Lnet/minecraftforge/registries/IForgeRegistry;Ljava/lang/String;)Lnet/minecraftforge/registries/DeferredRegister;", false);
            mv.visitFieldInsn(PUTSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(line++, l1);
            mv.visitFieldInsn(GETSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
            mv.visitLdcInsn("test_item");
            mv.visitInvokeDynamicInsn("get", "()Ljava/util/function/Supplier;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("()Ljava/lang/Object;"), new Handle(Opcodes.H_NEWINVOKESPECIAL, "de/blutmondgilde/ibocore/item/templates/DefaultItemTemplate", "<init>", "()V"), Type.getType("()Lnet/minecraft/item/Item;")});
            mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/registries/DeferredRegister", "register", "(Ljava/lang/String;Ljava/util/function/Supplier;)Lnet/minecraftforge/fml/RegistryObject;", false);
            mv.visitFieldInsn(PUTSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "TEST_ITEM", "Lnet/minecraftforge/fml/RegistryObject;");

            Label[] labels = new Label[itemCount + 1];
            for (int i = 0; i < itemCount; i++) {
                //Label
                labels[i] = new Label();
                mv.visitLabel(labels[i]);
                mv.visitLineNumber(line++, labels[i]);
                mv.visitFieldInsn(
                        GETSTATIC,
                        "de/blutmondgilde/ibocore/item/ItemList",
                        "ITEM_REGISTRY",
                        "Lnet/minecraftforge/registries/DeferredRegister;"
                );
                //Item Registry Name
                mv.visitLdcInsn("generated_item_" + i);
                mv.visitInvokeDynamicInsn(
                        "get",
                        "()Ljava/util/function/Supplier;",
                        new Handle(
                                Opcodes.H_INVOKESTATIC,
                                "java/lang/invoke/LambdaMetafactory",
                                "metafactory",
                                "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"),
                        new Object[]{
                                Type.getType("()Ljava/lang/Object;"),
                                new Handle(Opcodes.H_NEWINVOKESPECIAL,
                                        "de/blutmondgilde/ibocore/item/templates/DefaultItemTemplate",
                                        "<init>", "()V"),
                                Type.getType("()Lnet/minecraft/item/Item;")
                        }
                );
                mv.visitMethodInsn(
                        INVOKEVIRTUAL,
                        "net/minecraftforge/registries/DeferredRegister",
                        "register",
                        "(Ljava/lang/String;Ljava/util/function/Supplier;)Lnet/minecraftforge/fml/RegistryObject;",
                        false
                );
                //Var Name
                mv.visitFieldInsn(
                        PUTSTATIC,
                        "de/blutmondgilde/ibocore/item/ItemList",
                        ITEM_PREFIX + i,
                        "Lnet/minecraftforge/fml/RegistryObject;"
                );
            }

            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 0);
            mv.visitEnd();

        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(12, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lde/blutmondgilde/ibocore/item/ItemList;", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "register", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(3 + line++, l0);
            mv.visitFieldInsn(GETSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
            mv.visitMethodInsn(INVOKESTATIC, "net/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext", "get", "()Lnet/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext", "getModEventBus", "()Lnet/minecraftforge/eventbus/api/IEventBus;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/registries/DeferredRegister", "register", "(Lnet/minecraftforge/eventbus/api/IEventBus;)V", false);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(3 + line++, l1);
            mv.visitLdcInsn("IBO-Core/Items");
            mv.visitMethodInsn(INVOKESTATIC, "org/apache/logging/log4j/LogManager", "getLogger", "(Ljava/lang/String;)Lorg/apache/logging/log4j/Logger;", false);
            mv.visitLdcInsn("Registered Items");
            mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/logging/log4j/Logger", "info", "(Ljava/lang/String;)V", true);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLineNumber(3 + line++, l2);
            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 0);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

Die Methode wird direkt aus meiner "main" Methode aufgerufen. Leider werden die Bytecode Änderungen nicht übernommen. Generiert die Methode nur den Code und ich muss ihn noch irgendwie anwenden?

Vielen Dank im voraus für jede Hilfe!
 
MoxxiManagarm

MoxxiManagarm

Was ist bei dir ASM? Für mich bedeudet das Abstract State Machine, aber ich sehe erstmal keinen Zusammenhang davon zu deinem Code
 
L

LimDul

Aus dem Bauch heraus -du manipulierst den ByteCode. Wenn die Klasse, deren ByteCode du änderst, schon geladen ist,wirst du die vermutlich neu laden müssen. Du wirst also an der Stelle vermutlich nicht um eigene ClassLoader drumrumkommen. Damit steigst du aber sehr tief in technische Gefilde herab, die ich persönlich unter Schwarze Magie ablege :)
 
Thema: 

Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben