[ASM] Генерация локальной переменной

Версия Minecraft
1.7.10
API
Forge
236
4
22
Доброй ночи всем. Нужна мелкая помощь по asm`у. Вообщем, очень часто бывают случаи, где нужно "запаковать" значение в локальную переменную. Допустим чтобы вставить код до RETURN`а / THROW`a и не только. Так вот, чтобы "создать" эту переменную я всегда пользовался следующим кодом, который сам же написал, и как ни странно, он работал нормально:

Генерация локальной переменной:
    public static LocalVariableNode createLocalField(MethodNode method, String descriptor) {
        var label = new LabelNode();
        if (method.localVariables == null)
            method.localVariables = new ArrayList();
        var defaultName = "varASM_";
        var suffix = method.localVariables.stream().filter(var -> var.name.startsWith(defaultName)).map((varx) -> varx.name.substring(defaultName.length())).mapToInt(ASMUtils::parseInt).max().orElse(-1) + 1;
        var var = new LocalVariableNode(defaultName + suffix, descriptor, (String)null, label, label, method.localVariables.size());
        method.localVariables.add(var);
        return var;
    }

    private static int parseInt(String str) {
        try {
            return Integer.parseInt(str);
        } catch (Exception var2) {
            return 0;
        }
    }
Но по неизвестным причинам этот способ перестал работать и начал давать ошибку при использовании. Возможно беда в флагах для ClassReader и(или) ClassWriter. Для них я в последнее время юзаю примерно такую логику, не знаю на сколько она верна, ибо в гугле нет инфы, как определить, какие флаги нужно сюда пихать, по этому если знаете как правильнее - напишите. Текущий код:

Основа трансформера:
public byte[] transform(String name, String transformedName, byte[] clazzBytes) {
        ClassNode classNode = new ClassNode();
        int majorVersion = (clazzBytes[6] & 255) << 8 | clazzBytes[7] & 255;
        boolean java7 = majorVersion > 50;
        ClassReader classReader = new ClassReader(clazzBytes);
        classReader.accept(classNode, java7 ? 4 : 8);
        //Сам трансформер
        ClassWriter writer = new ClassWriter(java7 ? 2 : 1);
        classNode.accept(writer);
        return writer.toByteArray();
    }
Основной же мой вопрос - как "доделать" метод генерации локальных переменных в методе, чтобы не было подобных ошибок (краш ниже)?
 
Краш-лог
[00:15:36] [main/ERROR] [LaunchWrapper]: Unable to launch
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_292]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_292]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_292]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_292]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.NoClassDefFoundError: net/minecraft/block/BlockStaticLiquid
at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 8 more
Caused by: java.lang.ClassNotFoundException: net.minecraft.block.BlockStaticLiquid
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_292]
at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 8 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
at org.objectweb.asm.Frame.merge(Frame.java:1311) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1475) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:834) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:726) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:412) ~[asm-debug-all-5.0.3.jar:5.0.3]
at com.mymod.core.handlers.ASMHandler.transform(ASMHandler.java:53) ~[main/:?]
at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_292]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_292]
at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 8 more
Краш-лог:
[00:15:36] [main/ERROR] [LaunchWrapper]: Unable to launch
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_292]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_292]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_292]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_292]
	at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
	at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
	at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.NoClassDefFoundError: net/minecraft/block/BlockStaticLiquid
	at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
	at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
	at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
	... 8 more
Caused by: java.lang.ClassNotFoundException: net.minecraft.block.BlockStaticLiquid
	at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_292]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_292]
	at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
	at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
	at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
	... 8 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
	at org.objectweb.asm.Frame.merge(Frame.java:1311) ~[asm-debug-all-5.0.3.jar:5.0.3]
	at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1475) ~[asm-debug-all-5.0.3.jar:5.0.3]
	at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:834) ~[asm-debug-all-5.0.3.jar:5.0.3]
	at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:726) ~[asm-debug-all-5.0.3.jar:5.0.3]
	at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:412) ~[asm-debug-all-5.0.3.jar:5.0.3]
	at com.mymod.core.handlers.ASMHandler.transform(ASMHandler.java:53) ~[main/:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_292]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_292]
	at net.minecraft.block.Block.registerBlocks(Block.java:250) ~[Block.class:?]
	at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
	at net.minecraft.client.Minecraft.<init>(Minecraft.java:323) ~[Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
	... 8 more
236
4
22
Вопрос не актуален. Проблема оказалась не в генерации переменной, а в том, что я вставил несколько инструкций подряд через method.instructions.insert(), а нужно было сначала их собрать в InsnList, и уже потом его вставлять.
 
1,074
72
372
Впервые вижу такую мудрёную логику чтения и записи класса. В чём смысл определять версию класса? Использовать числовые значения вместо констант в исходнике - это не комильфо.
 

tox1cozZ

aka Agravaine
8,456
598
2,892
В чём смысл определять версию класса?
Начиная с седьмой версии джавы, сильно изменился процесс верификации байткода.
Ради этого приходится включать автоматическую генерацию stack map frame'ов.
На более старых версиях байткода это лишняя трата времени.
Подробнее здесь: What is a stack map frame
 
1,074
72
372
Начиная с седьмой версии джавы, сильно изменился процесс верификации байткода.
А в коде упоминается какое-то различие между седьмой и восьмой. В принципе, библиотека сама должна с этим справляться, используя фиксированно заданный набор флагов без лишнего if.
 
7,099
324
1,510
Попробуй не учитывать этот аспект, поделись результатами
 

tox1cozZ

aka Agravaine
8,456
598
2,892
А в коде упоминается какое-то различие между седьмой и восьмой. В принципе, библиотека сама должна с этим справляться, используя фиксированно заданный набор флагов без лишнего if.
Ты не видишь что-ли что там тернарный оператор?
 
Сверху