5

私は、後でJVMでコンパイルできるJava ".class"ファイルを外出先で生成する必要があるプロジェクトに取り組んでいます。スタックベースの中間プログラミング言語でもある MSIL (Microsoft IL) を学習して使用した後、次のような問題に直面しています。

  1. IL(C#またはVB用)と比較して、「.class」ファイルのJavaバイトコードには構造化された方法で情報が含まれており、ファイルを理解できる限り、プログラムデータとは別にメタデータが含まれています。本当ですか? ? すべてのクラス ファイルのテンプレート フォームで同じものを生成できますか??
  2. クラスファイルをバイナリで生成することは必須ですか??

「 Joshua Engel による Java™ 仮想マシンのプログラミング 」を参照しましたが、JVm 命令セットについては既に学習しているため、私の目的には役立っていません。

誰でもこれで私を助けてもらえますか?? すべてのヘルプは高く評価されます。単一の 1 をまだ見つけることができなかったので、単純なクラス ファイルを生成する例は非常に役立ちます。

4

5 に答える 5

4

IKVM Java-to-.NET コンパイラを使用して .NET で動作するように変換されたASM バイトコード ライブラリを使用する例:

こんにちは.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
于 2009-11-25T18:18:49.723 に答える
2

ASMバイトコード ライブラリを参照してください。それはかなり人気があります。Clojure、Groovy、Jython、JRuby など、多くの JVM 言語で使用されています。

しかし、Java ソースを生成し、それをコンパイルして .class ファイルを取得する方が簡単かもしれないという他の投稿者に同意します。javac何をする必要があるかによって大きく異なります。

于 2009-11-25T16:19:41.960 に答える
0

真剣な答え。

Java コードを自動生成し、Java コンパイラを使用してクラス ファイルを生成します。これは、BCEL と戦うよりもはるかに簡単に見えます。少なくとも、Java Byte Code よりも「高度な」言語でアルゴリズムをコーディングする方が簡単だからです。

バイトコードを生成する他のプログラミング言語も同様ですが、Java は最も簡単なアプローチの 1 つだと思います。

そして、あなたの質問に来て、

(1) はい、一部のメタデータはかなり静的です。ウィキペディアには、クラス ファイル形式の優れた概要があります。

(2) はい、クラスファイルは「バイナリ」です。Javaバイトコード用の英数字言語(アセンブラなど)はありません(少なくともそのようなツールは聞いたことがありません.javapはバイトコードを読み取り可能に出力できますが、戻る方法はありません)

編集

本当にやりたいことを推測するのはまだ難しいですが、念のため、算術式をJava仮想マシンで評価できる算術式の周りにクラスファイルを書きたい場合は、テンプレートクラスファイルの作成から始めることができます.

その場合、この「エバリュエーター」を Java でコーディングし、すべての有効な入力を評価するまでテストします。プライベート フィールドを使用して式を保持し、ダミーの式で初期化します。

私のJavaコード化されたエバリュエーターのクラスファイルは、「動的な」クラス生成の完璧なテンプレートになります.ダミーの式を実際の式に「置き換える」方法を見つけて、有効なクラスファイルを再作成する必要がありました(いくつかのポインタを調整する必要があるかもしれません.文字列の長さが異なるため)、動作するはずです。

この推測が完全に間違っていたとしても、ケース スタディとして役立つ可能性があり、今後の参考になるかもしれません :)

于 2009-11-25T16:19:18.433 に答える
0

BCELを見たことがありますか?

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

現在は JRE にバンドルされています。

于 2009-11-25T16:12:02.613 に答える
0

以下を保存して、コマンド ラインからSimple.java実行javac Simple.javaします (JDK がインストールされていると仮定します)。

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

これは、少なくとも単純なクラス ファイルを生成する標準的な方法です ;)

于 2009-11-25T16:16:01.437 に答える