为 JVM 生成 .class 文件

发布于 2024-08-13 06:42:02 字数 402 浏览 7 评论 0原文

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

  1. 与 IL(用于 C# 或 VB)相比,“.class”文件中的 java 字节码包含以结构化方式提供信息,据我所知该文件,它包含除程序数据之外的元数据,这是真的吗?我可以为每个类文件生成相同的模板形式吗?
  2. 是否必须以二进制形式生成类文件?

我参考了“Joshua Engel 的 Java™ 虚拟机编程”,但它没有达到我的目的,因为我已经了解了 JVM 指令集。

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

I am working on a project that requires me to generate a java ".class" file on the go that can be later on compiled on the JVM. After learning and working with MSIL (Microsoft IL) which is also a stack based intermediate programming language, the following are the problems I am facing :

  1. As compared to the IL (for C# or VB) the java bytecode in ".class" file contains information in a structured manner and as far as i could understand the file, it contains the metadata apart from the program data, is it true?? Can i generate the same in a template form for every class file??
  2. Is it compulsory to generate the class file in binary??

I have refered to " Programming for the Java™ Virtual Machine By Joshua Engel " but it has not served my purpose as I have already learned about the JVm instruction set.

Can anybody please help me with this?? All help will be highly appreciated.
An example for generating a simple class file would be really helpful as i could not locate a single 1 yet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

江城子 2024-08-20 06:42:02

使用 ASM 字节码库 转换为使用 .NET 使用 IKVM Java 到 .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

Example using the ASM bytecode library converted to work with .NET using the IKVM Java-to-.NET compiler:

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);
        }
    }
}

commands:

$ 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
扮仙女 2024-08-20 06:42:02

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

但我确实同意其他发帖者的观点,即生成 Java 源代码并使用 javac 编译它以获得 .class 文件可能会更简单。很大程度上取决于你需要做什么。

You may want to look at the ASM bytecode library. It's pretty popular. A lot of JVM languages use it: Clojure, Groovy, Jython, JRuby.

But I do agree with other postsers that it may be simpler to generate the Java source and compile it with javac to get your .class file. Depends a lot on what you need to do.

吾性傲以野 2024-08-20 06:42:02

你看过BCEL吗?

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

现在与 JRE 捆绑在一起。

Have you looked at BCEL?

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

It's bundled with JRE now.

北方。的韩爷 2024-08-20 06:42:02

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

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

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

Save the following to Simple.java and do javac Simple.java from the command line (assuming you have JDK installed)

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

That's at least a standard way to generate a simple class file ;)

听闻余生 2024-08-20 06:42:02

认真的回答。

我会自动生成 Java 代码并使用 Java 编译器生成类文件。这看起来比对抗 BCEL 容易多了。至少因为用“高级”语言编写算法比用 Java 字节码更容易。

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

回答你的问题,

(1)是的,一些元数据是相当静态的。维基百科对 类文件格式有很好的概述

(2) 是的,类文件是“二进制”。 java字节码没有字母数字语言(如汇编程序)(至少我没有听说过任何这样的工具,javap可以打印可读的字节码,但没有回头路)

编辑

仍然很难猜测,你真正想要做什么,但以防万一,你想围绕算术表达式编写一个类文件,可以在 java 虚拟机中计算该算术表达式,那么你真的可以从创建一个模板类开始文件。

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

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

即使这个猜测完全错误,它也可以作为案例研究,并可能对您有所帮助:)

Serious answer.

I'd auto-generate Java code and use the Java compiler to generate the class file. This look a lot easier then battling BCEL. At least because it's easier to code an algorithm in a 'higher' language than in Java Byte Code.

Any other programming language that produces byte code will do aswell, but i guess Java is one of the easiest approaches.

And coming to your questions,

(1) Yes, some metadata is pretty static. Wikipedia has a nice overview of the class file format

(2) Yes, the classfile is 'binary'. There is no alphanumerical language (like assembler) for java bytecode (at least I haven't heard of any such tool, javap can print bytecode readable but there's no way back)

Edit

Still hard to guess, what you really want to do, but just in case, you want to write a classfile around an arithmetic expression that can evaluate that arithmetic expression in a java virtual machine, then you really could start with creating a template class file.

In that case I'd code this 'evaluator' in Java and test it until it evaluates all valid inputs. I'd use a private field to hold the expression, initialised with a dummy expression.

The classfile of my Java coded evaluator would be a perfect template for the 'dynamic' class generation - I just had to find out how to 'replace' the dummy expression with a real one, recreate valid classfile (you may have to adjust some pointers because of different string lengths) and it should work.

Even if this guess is totally wrong, it may serve as case study and may help you on your way :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文