为JVM生成.class文件

时间:2009-11-25 16:07:41

标签: java bytecode jvm-languages

我正在开发一个项目,要求我随时生成一个java“.class”文件,以后可以在JVM上编译。在学习并使用MSIL(Microsoft IL)(也是基于堆栈的中间编程语言)之后,我面临以下问题:

  1. 与IL(对于C#或VB)相比,“。class”文件中的java字节码以结构化方式包含信息,据我所知,该文件包含除程序数据之外的元数据,是真的??我可以在每个类文件的模板表单中生成相同的文件吗?
  2. 是否必须以二进制生成类文件?
  3. 我已经提到“由Joshua Engel编写Java™虚拟机程序”,但由于我已经了解了JVm指令集,所以它没有达到我的目的。

    有人可以帮帮我吗?所有帮助将受到高度赞赏。 生成简单类文件的示例非常有用,因为我找不到单个1。

5 个答案:

答案 0 :(得分:4)

使用ASM bytecode library使用IKVM Java-to-.NET compiler转换为与.NET一起使用的示例:

hello.cs中:

using System;
using System.IO;
using org.objectweb.asm;

namespace test.helloWorld
{
    public class helloDump
    {

        public static byte[] dump ()
        {

            ClassWriter cw = new ClassWriter(0);
            MethodVisitor mv;

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

            mv = cw.visitMethod(Opcodes.__Fields.ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.__Fields.ALOAD, 0);
            mv.visitMethodInsn(Opcodes.__Fields.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            mv.visitInsn(Opcodes.__Fields.RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();

            mv = cw.visitMethod(Opcodes.__Fields.ACC_PUBLIC + Opcodes.__Fields.ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
            mv.visitCode();
            mv.visitFieldInsn(Opcodes.__Fields.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitLdcInsn("Hello World!");
            mv.visitMethodInsn(Opcodes.__Fields.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
            mv.visitInsn(Opcodes.__Fields.RETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();

            cw.visitEnd();

            return cw.toByteArray();
        }

        public static void Main(string[] args)
        {
            FileStream helloWorldFile = new FileStream("hello.class", FileMode.Create);
            byte[] helloWorldClass = dump();
            helloWorldFile.Seek(0, SeekOrigin.Begin);
            helloWorldFile.Write(helloWorldClass, 0, helloWorldClass.Length);
        }
    }
}

命令:

$ ikvmc -out:org.objectweb.asm.dll -target:library -version:3.2.0.0 asm-3.2.jar
$ mcs -r:org.objectweb.asm.dll  hello.cs
$ mono hello.exe
$ ls hello.class
$ java hello

答案 1 :(得分:2)

您可能需要查看ASM字节码库。它很受欢迎。很多JVM语言都使用它:Clojure,Groovy,Jython,JRuby。

但我同意其他帖子,可能更容易生成Java源代码并使用javac编译它以获取.class文件。很大程度上取决于你需要做什么。

答案 2 :(得分:0)

你看过BCEL了吗?

http://en.wikipedia.org/wiki/Byte_Code_Engineering_Library

它现在与JRE捆绑在一起。

答案 3 :(得分:0)

将以下内容保存到Simple.java并从命令行执行javac Simple.java(假设您已安装JDK)

public class SimpleJava {
  public static main(String[] args) {
    System.out.println("Big Sorry, couldn't stop myself ;-)");
  }
}

这至少是生成简单类文件的标准方法;)

答案 4 :(得分:0)

认真回答。

我会自动生成Java代码并使用Java编译器生成类文件。这看起来比与BCEL战斗容易得多。至少因为用比Java字节码更高的语言编写算法更容易。

任何其他生成字节代码的编程语言都可以,但我猜Java是最简单的方法之一。

回答你的问题,

(1)是的,一些元数据非常静态。维基百科对class file format

有一个很好的概述

(2)是的,类文件是'二进制'。对于java字节码没有 alphanumerical 语言(比如汇编程序)(至少我没有听说过任何这样的工具,javap可以打印字节码可读但是没有办法回来)

修改

还是很难猜到,你真的想要做什么,但为了以防万一,你想围绕一个算术表达式编写一个类文件,可以在java虚拟机中评估该算术表达式,那么你真的可以从创建一个模板类文件。

在这种情况下,我会用Java编写这个'评估者'并对其进行测试,直到它评估所有有效输入。我使用私有字段来保存表达式,用虚拟表达式初始化。

我的Java编码求值程序的类文件将是“动态”类生成的完美模板 - 我只需要找出如何用真实表达式“替换”虚拟表达式,重新创建有效的类文件(您可能必须因为不同的字符串长度而调整一些指针)并且它应该可以工作。

即使这个猜测是完全错误的,它也可以作为案例研究,可以帮助你:)