我想编辑一个带有字节码的jar文件,我创建了一个项目来编辑它。我有2个功能:
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();
}
而且
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();
}
代码工作,我得到了jar,但当我启动它时:线程“main”中的异常java.lang.Unsupport tedClassVersionError: net/minecraft/m/d已由Java运行时(类文件版本0.0)的最新版本编译,该版本的Java运行时仅识别高达52.0的类文件版本
我试图找到一种方法来设置类文件版本,但找不到一个,有什么想法吗?
你的陈述
return new ClassWriter(classReader,
ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES).toByteArray();
创建一个新的类编写器,但在请求生成的字节码之前不向其写入任何内容。
您必须用类信息填充它。在您的具体情况下:
ClassWriter cw = new ClassWriter(classReader,
ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(cw);
return cw.toByteArray();
比如classReader。accept(classNode,ClassReader.EXPAND_FRAMES)
将所有信息从类读取器复制到类节点。接受(cw)
将修改后的信息从类节点复制到类编写器。
从字面上回答这个问题,调用access(int version, int access,java.lang.String name,java.lang.String签名,java.lang.String overName,java.lang.String[]接口)
将指定类的主要信息,包括版本号,但是,使用Visitor Pattern时将自动调用该方法。
在项目结构中,我已经将所有内容都设置为java 11,在java编译器设置中,我的本地java版本也是11,可能有什么问题?
我试图在AWS云中运行docker镜像,因此在本地,用jdk-11.0.1编译应用程序,并编写如下docker文件;请注意,我没有在AWS ec2实例中安装任何JDK,因为我已经在最终图像中包含了采用OpenJDK/openjdk11:latest image。。 线程“main”java中出现异常。lang.UnsupportedClassVersionError:com/example/dem
我正在尝试启动我为Spring Boot项目构建的jar文件。首先我做了: 然后,我尝试启动jar文件,但出现以下错误: 线程“main”Java.lang.UnsupportedClassVersionError中出现异常:IT/sysdata/Helios_BackEnd_Admin/HeliosAdminBackEndApplication已由较新版本的Java运行时(类文件版本55.0)编
这个问题和这个问题很相似,除了环境和我得到这个错误的方式。我也试过答案中提供的解决方案,但没有运气。 我正在使用Eclipse在Computer1上开发一个Spring Boot应用程序。Computer1和Eclipse上的JDK/JRE版本是JDK13.0.1。 现在,我使用eclipse mvn install创建了一个fat-JAR,并将fat-JAR复制到Computer2。当我在Com
这个问题与这个问题非常相似,除了环境和我得到这个错误的方式。我也尝试了答案中提供的解决方案,但没有运气。 我正在使用Eclipse在Computer1上开发Spring Boot应用程序。Computer1和Eclipse上的JDK/JRE版本是JDK 13.0.1。 现在,我使用eclipse mvn install创建了一个Fat-JAR并将Fat-JAR复制到Computer2。当我在Com
这是我尝试执行exe的第一个应用程序。我正在使用Launch4j来执行此操作。执行并尝试运行后,我收到此错误: Blockquote Launch4j——线程“main”java中的异常。lang.UnsupportedClassVersionError:FakeMain是由最新版本的Java运行时(类文件版本55.0)编译的,这个版本的Java运行时只识别高达52.0的类文件版本 我搜索了一些关