views:

234

answers:

5

Hello Everybody, 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.

A: 

Have you looked at BCEL?

http://en.wikipedia.org/wiki/Byte%5FCode%5FEngineering%5FLibrary

It's bundled with JRE now.

ZZ Coder
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
A: 

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_D
Thnx Andreas, but the problem is generating the class file my self n not by the javac command in JVM
Raghav Bali
(this answer was not really serious ;) )
Andreas_D
A: 

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_D
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
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_D
They don't come from any programing language, just plain english text!
Raghav Bali
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_D
Its really just plain text that occasionally include arithmetic expressions that need evaluation
Raghav Bali
@Raghav: If the front-end is in .NET, why would you want to evaluate the arithmetic expressions in a Java VM?
Stobor
@stoborActually 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
+2  A: 

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
will have to think upon this i guess, thnx
Raghav Bali
+3  A: 

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
This is smthing i was looking for, thnx stobor yt again...thnx a ton
Raghav Bali