5

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.

Raghav Bali
  • 81
  • 2
  • 2
  • 9
  • 3
    Generating a .class file is what the compiler does. What's wrong with generating the code and compiling it? Or is something like Reflection.Emit or Dynamic IL generation in .NET what you want for Java? – OregonGhost Nov 25 '09 at 16:12
  • Is your project to write a java compiler? – matt b Nov 25 '09 at 16:16
  • 1
    Ya my project is somewhat like a compiler, I am using C#.NET, one of the primary aims are to generate the .class file(bytecode) dynamically. – Raghav Bali Nov 25 '09 at 16:19
  • Quick question: is it allowed to use other .NET libraries? Or is this a homework-type question where you have to write the bytecode generation library yourself? – Stobor Nov 25 '09 at 16:25
  • its not a homework question but ya it requires me to do bytecode generation myself. how can i use other .NET libraries for the purpose?? – Raghav Bali Nov 25 '09 at 16:31
  • You mention .NET libraries a few times -- is the idea here actually to generate a Java .class file from a .NET app? I was initially assuming you'd be generating the bytecode from a Java app. – overthink Nov 25 '09 at 16:35
  • @oregonhost Don't know much about Reflection.Emit but yes i want to generate bytecodes on the fly, i can do it with CIL/MSIL but am stuck with JVM part – Raghav Bali Nov 25 '09 at 16:38
  • You could use the BCEL or ASM libraries which other people have suggested, but use them as .NET libraries. IKVM can compile the jar files into .NET dlls which can be directly referenced by your code... See http://www.ikvm.net/userguide/ikvmc.html – Stobor Nov 25 '09 at 16:46
  • example: `ikvmc -out:org.objectweb.asm.dll -target:library -version:3.2.0.0 asm-3.2.jar` creates org.objectweb.asm.dll, which is a full-fledged .NET library which creates Java bytecode... – Stobor Nov 25 '09 at 16:49
  • @Stobor thnx a lot, i guess this might do it. – Raghav Bali Nov 25 '09 at 16:51

5 Answers5

4

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
Stobor
  • 44,246
  • 6
  • 66
  • 69
2

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.

overthink
  • 23,985
  • 4
  • 69
  • 69
0

Have you looked at BCEL?

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

It's bundled with JRE now.

ZZ Coder
  • 74,484
  • 29
  • 137
  • 169
  • ya, i have seen it but it doesnot solve my purpose. Though may be i havn;t got much because my problem is to generate the bytecode myself(by my application) and not by a 2nd application. – Raghav Bali Nov 25 '09 at 16:21
0

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

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
0

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

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • Um...My application allows user to type in statements in plain text, converting this to java syntax, won't this call for too much overhead as then this java code would have to be compiled and run on JVM?? – Raghav Bali Nov 25 '09 at 16:35
  • Those statements, what's the programming language they come from? And I thought you're class file shall be designed to run on a jvm anyway? – Andreas Dolk Nov 25 '09 at 16:45
  • They don't come from any programing language, just plain english text! – Raghav Bali Nov 25 '09 at 16:46
  • And how do you need them to show up in bytecode? Is it a sort of domain specific language or really just plain text (no 'statements' in programming context)? – Andreas Dolk Nov 25 '09 at 16:54
  • Its really just plain text that occasionally include arithmetic expressions that need evaluation – Raghav Bali Nov 25 '09 at 17:13
  • @Raghav: If the front-end is in .NET, why would you want to evaluate the arithmetic expressions in a Java VM? – Stobor Nov 26 '09 at 11:41
  • @stobor Actually the fact is, I want the 'plain text' entered by the user to be executable on .NET as well as JVM, m able to do so with .NET but having a rough time with JVM. Currently I am busy with my exams, but after that i need to give a try to ASM n the above stated method using template classes in java itself. – Raghav Bali Dec 03 '09 at 09:29