Java 为JVM生成.class文件
我正在从事一个项目,该项目要求我在运行中生成一个java“.class”文件,稍后可以在JVM上编译该文件。在学习和使用MSIL(Microsoft IL)这一基于堆栈的中间编程语言后,我面临以下问题: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)“但它没有达到我
一个生成简单类文件的示例将非常有用,因为我还没有找到一个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