Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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.

Have you looked at BCEL?

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

It's bundled with JRE now.

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

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 :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top