0

我努力了

    ClassWriter t = new ClassWriter(0);

    t.visitSource("testing.java", null);

    t.visitEnd();

    byte d[] = t.toByteArray();

    FileOutputStream p = null;

    try
    {
        p = new FileOutputStream("testing.class");
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }

    try
    {
        p.write(d);
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

testing.java 中的文本是:

public class testing
{
    public static void main(String args[])
    {
        System.out.println("Works!");
    }
}

但是,当我尝试运行类文件时,它给了我这个错误:

Exception in thread "main" java.lang.UnsupportedClassVersionError: testing : Unsupported major.minor version 0.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

我将如何修复它以便类文件输出“Works!” 到控制台?

编辑:

我不希望它必须访问 jdk 文件!(<- 例如 javax.tools)这就是我试图让 ASM 工作的原因。

4

3 回答 3

6

似乎您正在尝试将 Java 源文件编译为类文件。这可以通过 Java 编译器 - javac命令行程序或javax.tools 包中的工具来完成。

ASM 用于不同的目的。ASM 可用于即时创建类文件,无需任何源代码。阅读ASM 的文档以了解 Java 字节码以及如何使用 ASM 生成和阅读它。

以下是使用 javax.tools 包编译文件的方式。或者,您可以使用Process调用命令行工具。检查文档以获取其他参数 - 使用什么类路径,在哪里写入文件等。

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class TestingCompile {
    public static void main(String[] args) {
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        int result = javac.run(null, null, null, "C:\\path\\to\\Testing.java");
        if (result != 0) {
            throw new RuntimeException("compile failed: exit " + result);
        }
    }
}

下面是如何使用 ASM 创建相同的类文件,而不使用源文件。我很确定这不是你想要做的——否则你就不必问这个问题了。;)

这只是ASMifierClassVisitor的输出,因此仍需要将字节写入文件或动态加载到类加载器中。我使用了该-debug参数,以便 ASMifier 还显示源文件名和行号( 和 调用是可选的visitSourcevisitLineNumber因此visitLocalVariable如果不需要调试信息,您可以省略它们和相关标签)。

import org.objectweb.asm.*;

public class TestingDump implements Opcodes {

    public static byte[] dump() throws Exception {

        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Testing", null, "java/lang/Object", null);

        cw.visitSource("Testing.java", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(1, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "LTesting;", null, l0, l1, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(3, l0);
            mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitLdcInsn("Works!");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(4, l1);
            mv.visitInsn(RETURN);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l2, 0);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}
于 2012-04-15T21:32:47.617 回答
4

我认为问题在于该库希望调用最少的某些方法,并且我相信您没有足够的方法让它生成一个完整的类。

我建议你使用 ASMifier 来生成一些模板。


您以某种方式损坏了文件。没有0.0版本

于 2012-04-15T07:01:20.513 回答
0

您可以从源代码调用 Java 编译器以将任何 Java 源代码编译为类文件。编译器是用 Java 本身编写的,是标准 jdk 版本的一部分。尝试寻找一个名为 javac 的类。

于 2012-04-15T20:16:49.840 回答