2009-11-25 14 views
5

Estoy trabajando en un proyecto que requiere que genere un archivo java ".class" sobre la marcha que luego se puede compilar en la JVM. Después de aprender y trabajar con MSIL (Microsoft IL), que es también un lenguaje de programación intermedia basada en pila, los siguientes son los problemas que estoy enfrentando:Generación de archivo .class para JVM

  1. En comparación con la IL (para C# o VB) el código de bytes de Java en El archivo ".class" contiene información de forma estructurada y, en la medida en que pude entender el archivo, contiene los metadatos además de los datos del programa, ¿es cierto? ¿Puedo generar lo mismo en una plantilla para cada archivo de clase?
  2. ¿Es obligatorio generar el archivo de clase en binario?

He hecho referencia a la "Programación para la máquina virtual Java ™ de Joshua Engel", pero no cumplió mi propósito ya que aprendí sobre el conjunto de instrucciones JVm.

¿Alguien puede ayudarme con esto? Toda la ayuda será muy apreciada. Un ejemplo para generar un archivo de clase simple sería realmente útil ya que no pude encontrar un solo 1 todavía.

+3

Generación de un archivo .class es lo que el compilador hace. ¿Qué hay de malo en generar el código y compilarlo? ¿O es algo así como Reflection.Emit o Dynamic IL generación en .NET lo que desea para Java? – OregonGhost

+0

¿Tu proyecto es escribir un compilador de Java? –

+1

Ya mi proyecto es algo así como un compilador, estoy usando C# .NET, uno de los principales objetivos es generar el archivo .class (bytecode) dinámicamente. –

Respuesta

4

ejemplo utilizando el ASM bytecode library se convirtió al trabajar con .NET utilizando los 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); 
     } 
    } 
} 

comandos:

$ 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 
+0

Esto es todo lo que estaba buscando, por ejemplo, esto de nuevo ... por tonelada –

0

¿Has mirado a BCEL?

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

Es incluido con JRE ahora.

+0

ya lo he visto, pero no resuelve mi propósito. Aunque puede ser que haya tenido mucho, porque mi problema es generar yo mismo el bytecode (por mi aplicación) y no una segunda aplicación. –

0

Guarde lo siguiente en Simple.java y hacer javac Simple.java desde la línea de comandos (suponiendo que tiene instalado el JDK)

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

Eso es, al menos, una forma estándar para generar un archivo de clase simple;)

+0

Thnx Andreas, pero el problema es generar el archivo de clase yo mismo no por el comando javac en JVM –

+0

(esta respuesta no fue realmente grave;)) –

0

respuesta seria .

Generaría automáticamente código Java y usaría el compilador Java para generar el archivo de clase. Esto parece mucho más fácil que luchar contra BCEL. Al menos porque es más fácil codificar un algoritmo en un lenguaje 'más alto' que en Java Byte Code.

Cualquier otro lenguaje de programación que produzca código de bytes también lo hará, pero creo que Java es uno de los enfoques más fáciles.

y llegando a sus preguntas,

(1) Sí, algunos metadatos es bastante estático. Wikipedia tiene una buena descripción de class file format

(2) Sí, el archivo de clase es 'binario'. No hay ninguna alfanumérico idioma (como ensamblador) para el código de bytes de Java (al menos no he oído hablar de ninguna de estas herramientas, javap puede imprimir el código de bytes de lectura pero no hay camino de vuelta)

Editar

Aún difícil de adivinar, lo que realmente desea hacer, pero por si acaso, desea escribir un archivo de clase en torno a una expresión aritmética que pueda evaluar esa expresión aritmética en una máquina virtual java, entonces realmente podría comenzar con la creación de un archivo de clase de plantilla.

En ese caso codifico este 'evaluador' en Java y lo pruebo hasta que evalúe todas las entradas válidas.Usaría un campo privado para mantener la expresión, inicializada con una expresión ficticia.

El archivo de clase de mi evaluador codificado en Java sería una plantilla perfecta para la generación de clases "dinámicas", solo tenía que averiguar cómo "reemplazar" la expresión ficticia por una real, recrear un archivo de clase válido (puede tener para ajustar algunos punteros debido a diferentes longitudes de cadena) y debería funcionar.

Incluso si esta suposición es totalmente erróneo, puede servir como estudio de caso y puede ayudarle en su camino :)

+0

Um ... Mi aplicación permite al usuario escribir sentencias en texto sin formato, convirtiendo esto a sintaxis java, ¿no requerirá esto demasiada sobrecarga ya que entonces este código java debería ser compilado y ejecutado en JVM? –

+0

Esas declaraciones, ¿cuál es el lenguaje de programación del que provienen? ¿Y pensé que tu archivo de clase estaría diseñado para ejecutarse en un jvm de todos modos? –

+0

No provienen de ningún lenguaje de programación, ¡simplemente texto en inglés! –

2

Es posible que desee ver en la biblioteca ASM código de bytes. Es bastante popular. Muchos lenguajes JVM lo usan: Clojure, Groovy, Jython, JRuby.

Pero estoy de acuerdo con otros postsers que puede ser más simple para generar la fuente de Java y compilarlo con javac para obtener su archivo .class. Depende mucho de lo que necesita hacer.

+0

tendré que pensar en esto, supongo, esto –

Cuestiones relacionadas