我试过了
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文件! (< -Ex.javax.tools)这就是我试图让ASM工作的原因。
答案 0 :(得分:4)
似乎您正在尝试将Java源文件编译为类文件。这可以通过Java编译器完成 - javac命令行程序或javax.tools package中的工具。
ASM用于其他目的。 ASM可用于即时创建类文件,无需任何源代码。阅读ASM's documentation以了解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还显示源文件名和行号(visitSource
,visitLineNumber
和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();
}
}
答案 1 :(得分:3)
我认为问题在于库需要调用一组最小的某些方法,我相信你没有足够的方法让它生成一个完整的类。
我建议您使用ASMifier生成一些模板。
您已经以某种方式损坏了文件。没有版本0.0
答案 2 :(得分:0)
您可以从源代码调用Java编译器,将任何Java源代码编译为类文件。编译器是用Java本身编写的,是标准jdk发行版的一部分。尝试寻找一个名为javac的类。