Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为JVM生成.class文件_Java_Bytecode_Jvm Languages - Fatal编程技术网

Java 为JVM生成.class文件

Java 为JVM生成.class文件,java,bytecode,jvm-languages,Java,Bytecode,Jvm Languages,我正在从事一个项目,该项目要求我在运行中生成一个java“.class”文件,稍后可以在JVM上编译该文件。在学习和使用MSIL(Microsoft IL)这一基于堆栈的中间编程语言后,我面临以下问题: 与IL(对于C#或VB)相比,“.class”文件中的java字节码以结构化的方式包含信息,据我所知,该文件包含程序数据之外的元数据,是真的吗??我可以为每个类文件生成相同的模板表单吗 是否必须以二进制格式生成类文件 我提到了“Java编程”™ 虚拟机(Joshua Engel)“但它没有达到我

我正在从事一个项目,该项目要求我在运行中生成一个java“.class”文件,稍后可以在JVM上编译该文件。在学习和使用MSIL(Microsoft IL)这一基于堆栈的中间编程语言后,我面临以下问题:

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

    有人能帮我吗??我们将非常感谢您的帮助。
    一个生成简单类文件的示例将非常有用,因为我还没有找到一个1。

    您看过BCEL吗


    现在它与JRE捆绑在一起。

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

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

    严肃的回答

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

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

    说到你的问题

    (1) 是的,有些元数据是相当静态的。维基百科对这个问题有一个很好的概述

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

    编辑

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

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

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


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

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

    但是我同意其他帖子的观点,生成Java源代码并用
    javac
    编译它以获取.class文件可能更简单。这在很大程度上取决于您需要执行的操作。

    示例使用转换为使用.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);
            }
        }
    }
    

    生成.class文件是编译器的工作。生成代码并编译它有什么问题?或者像.NET中的Reflection.Emit或Dynamic IL generation之类的东西是您想要的Java吗?您的项目是要编写Java编译器吗?是的,我的项目有点像编译器,我使用的是C#.NET,主要目标之一是动态生成.class文件(字节码)。快速问题:允许使用其他.NET库吗?或者这是一个家庭作业类型的问题,你必须自己编写字节码生成库吗?这不是一个家庭作业问题,但它需要我自己生成字节码。我怎样才能使用其他.NET库来达到这个目的呢?是的,我见过它,但它不能解决我的目的。虽然我有;我没有得到太多,因为我的问题是自己生成字节码(由我的应用程序生成),而不是由第二个应用程序生成。Thnx Andreas,但问题是自己生成类文件,而不是由JVM中的javac命令生成(这个答案不是很严重;))嗯…我的应用程序允许用户以纯文本形式键入语句,将其转换为java语法,会不会需要太多的开销,因为java代码必须在JVM上编译和运行??这些语句,它们来自于什么编程语言?我还以为你的类文件应该设计成在jvm上运行呢?它们不是来自任何编程语言,只是纯英语文本!您需要如何让它们以字节码的形式出现?它是一种特定于领域的语言还是纯文本(在编程环境中没有“语句”)?它实际上只是纯文本,偶尔包含需要计算的算术表达式。我想,这是我一直在寻找的东西,再次是stobor…一吨
    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