Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Class compiled by a more recent version of the Java Runtime (0.0), this version of the Java Runtime only recognizes class file versions up to 52.0

I want to edit a jar file, with byte code, and i created a project to edit it.
I have 2 functions :

    public static byte[] transform(byte[] buf){
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(buf);
    classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

    for (MethodNode method : classNode.methods) {
        if(method.name.equals(shouldSideBeRenderedMethod) && method.desc.startsWith("(L") && method.desc.endsWith(";IIII)Z")){
            System.out.println("[*] Patching bytecode of shouldSideBeRendered...");
            InsnList insnList = new InsnList();

            Label label0 = new Label();
            insnList.add(new LabelNode(label0));
            insnList.add(new VarInsnNode(ALOAD, 0));
            insnList.add(new FieldInsnNode(GETFIELD, blockClass.replaceAll("\\.", "/"), unlocalizedNameField, "Ljava/lang/String;"));
            insnList.add(new LdcInsnNode("stone"));
            insnList.add(new MethodInsnNode(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false));
            Label label1 = new Label();
            insnList.add(new JumpInsnNode(IFNE, new LabelNode(label1)));
            insnList.add(new InsnNode(ICONST_1));
            Label label2 = new Label();
            insnList.add(new JumpInsnNode(GOTO, new LabelNode(label2)));
            insnList.add(new LabelNode(label1));
            insnList.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null));
            insnList.add(new InsnNode(ICONST_0));
            insnList.add(new LabelNode(label2));
            insnList.add(new FrameNode(Opcodes.F_SAME1, 0, null, 1, new Object[]{Opcodes.INTEGER}));
            insnList.add(new InsnNode(IRETURN));
            Label label3 = new Label();
            insnList.add(new LabelNode(label3));

            method.instructions.insertBefore(method.instructions.getFirst(), insnList);
        }
    }

    return new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES).toByteArray();
}

And

JarFile jarFile = new JarFile(jarPath);
    List<JarEntry> entries = Collections.list(jarFile.entries());
    HashMap<String, byte[]> classMap = new HashMap<>();
    entries.forEach(jarEntry -> {
        try {
            if(jarEntry.getName().equals(blockClass.replaceAll("\\.", "/") + ".class")){
                classMap.put(jarEntry.getName(), transform(IOUtils.toByteArray(jarFile.getInputStream(jarEntry))));
            }else{
                classMap.put(jarEntry.getName(), IOUtils.toByteArray(jarFile.getInputStream(jarEntry)));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
    System.out.println("[+] Jar loaded !");

    System.out.println("[*] Writing patched jar...");
    try {
        JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream("output.jar"));
        for (Map.Entry<String, byte[]> entry : classMap.entrySet()) {
            JarEntry jarEntry = new JarEntry(entry.getKey());
            jarOutputStream.putNextEntry(jarEntry);
            jarOutputStream.write(entry.getValue());
            jarOutputStream.closeEntry();
        }
        jarOutputStream.close();

        System.out.println("[+] Patched jar successfully written to output.jar !");
    } catch (Exception e) {
        e.printStackTrace();
    }

The code works, i got the jar, but when i launch it : Exception in thread "main" java.lang.UnsupportedClassVersionError: net/minecraft/m/d has been compiled by a more recent version of the Java Runtime (class file version 0.0), this version of the Java Runtime only recognizes class file versions up to 52.0

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I tried to find a way to set class file version, but can’t find one, any idea pls ?

>Solution :

Your statement

return new ClassWriter(classReader,
        ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES).toByteArray();

create a new ClassWriter but doesn’t write anything to it before requesting the generated bytecode.

You have to populate it with the class information. In your specific case:

ClassWriter cw = new ClassWriter(classReader,
                                 ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(cw);
return cw.toByteArray();

Like classReader.accept(classNode, ClassReader.EXPAND_FRAMES); copied all information from the class reader to the classNode, the classNode.accept(cw); will copy the modified information from the classNode to the class writer.

To answer the question literally, a call to
visit​(int version, int access, java.lang.String name, java.lang.String signature, java.lang.String superName, java.lang.String[] interfaces) will specify the main information of the class, including the version number, however, the method will be invoked automatically when using the Visitor Pattern.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading