invoking javac programmatically

H

Hack Bert

Hi all,

i have to invoke javac in my java program to compile java code thts
generated on the fly. these java classes all implement an interface
called IC.

there is an invocation scenario thats part of the javac man page (on
unix) and i got this to work nicely using

String javacArguments[] = new String[1];
javacArguments[0] = sourceFileName;

com.sun.tools.javac.Main.compile(javacArguments);

and

Class compiledCode = Class.forName(className);

Constructor constructor = compiledCode.getConstructor();

instance = (IC) constructor.newInstance();

but this method has the drawback that my java source code has to be
generated into a file and the resulting .class is again on disk.

what i want to do is to compile from a string / stringbuffer / char
stream into a byte buffer that could be consumed by the

ClassLoader.defineClass(String name, byte[] b, ...)

method in order to avoid the disk io and to hide the generated java code.

has anyone out there some code,how the classes that make up the javac
can be abused to do this ? (i know that this would be absolutely
undocumented and can change anytime...)

thx.

thomas
 
J

jan V

has anyone out there some code,how the classes that make up the javac
can be abused to do this ? (i know that this would be absolutely
undocumented and can change anytime...)

Given that you know your solution would be flaky at best, and given that you
wish to hide any generated stuff from users, have you considered generating
a .class byte stream directly? Depending on the complexity of the logic you
generate, this could actually be simpler than you may think. That way, you
could feed defineClass() with the in-memory output of your generation stage.

There are a number of .class file parsing/constructing/editing libs out
there to let you concentrate on your "business logic".
 
T

Thomas Hawtin

Hack said:
what i want to do is to compile from a string / stringbuffer / char
stream into a byte buffer that could be consumed by the

I believe javac currently can only use files, but in Java SE 6 it will
be available through an API that uses a virtual filesystem of some
description.

Is there some other way around it? Using an interpreter. Compiling on a
server.

If you generate byte code I strongly suggest using ObjectWeb ASM rather
BCEL. BCEL is just nasty. Writing byte codes is nasty enough.

Tom Hawtin
 
J

jan V

If you generate byte code I strongly suggest using ObjectWeb ASM rather
BCEL. BCEL is just nasty. Writing byte codes is nasty enough.

Why ? If someone is comfortable with machine code or assembler, then
generating bytecode may be preferable to generating Java, then compiling,
then loading the class.

At least the JVM spec has remained ultra-stable since its inception, whereas
Sun seems hell-bent on undermining the language's original strength and
simplicity by "enhancing" the language every major JDK release nowadays.

If you generated some bytecode sequence, chances are your sequence will
continue to work flawlessly in 5 and 10 years time, whereas if you generated
some Java language logic or methods, maybe some future language enhancement
will break such a scheme. For example, if you were unlucky enough to use
"enum" as a variable name in the past, you'd be up the proverbial creek with
a spoon....
 
T

Thomas Hawtin

jan said:
Why ? If someone is comfortable with machine code or assembler, then
generating bytecode may be preferable to generating Java, then compiling,
then loading the class.

It may be. However it is not a trivial undertaking. You make it sound as
if using javac to handle bytecode generation is more involved than hand
rolling.

I'm familiar with assembler and Java bytecode (by coincidence the JVM
spec is open in front of me) yet find bytecode generators difficult to
follow.

Even trivial operations take many lines. You have the logic of the
generated mixed in with that of the generator. Generating source is
vastly less verbose, so it is easier to see what is happening.

At least in most modern assembly language you are chiefly dealing with
manipulating registers who's interpretation remains fixed over short
lengths. Bytecode instructions do not stand on their own. (Hint: if you
are not too concerned about size, prefer local variables over stack
trickery.)

It introduces another language and library into the mix.
At least the JVM spec has remained ultra-stable since its inception, whereas
Sun seems hell-bent on undermining the language's original strength and
simplicity by "enhancing" the language every major JDK release nowadays.

He seemed happy enough playing about with javac entry points. javac has
very useful -source and -target options, that will cope with, say, extra
keywords. If you are paranoid you can fully qualify type names.

Tom Hawtin
 
J

jan V

He seemed happy enough playing about with javac entry points. javac has
very useful -source and -target options, that will cope with, say, extra
keywords. If you are paranoid you can fully qualify type names.

Hmm.. those arguments are pretty strong. Generating Java source which a
human reader would cringe at is not an issue, so I agree with you that with
the -source and -target options one could limit to the minimum to chances
that future changes to the language would break a solution. Though it
doesn't address the possibility of the javac command line parameter syntax
changing....
 
T

Thomas Hawtin

jan said:
Hmm.. those arguments are pretty strong. Generating Java source which a
human reader would cringe at is not an issue, so I agree with you that with
the -source and -target options one could limit to the minimum to chances
that future changes to the language would break a solution. Though it
doesn't address the possibility of the javac command line parameter syntax
changing....

I believe Tomcat comes with the Eclipse JDT compiler. So there doesn't
appear to be any reason to root around for javac in a separately
downloaded JDK.

Still a solution that doesn't generate any bytecode by any means has
advantages, if at all possible.

Tom Hawtin
 
H

Hack Bert

jan said:
There are a number of .class file parsing/constructing/editing libs out
there to let you concentrate on your "business logic".

would you please name the most common ones ?

thx.

Hack
 
R

Roedy Green

Given that you know your solution would be flaky at best, and given that you
wish to hide any generated stuff from users, have you considered generating
a .class byte stream directly?

see http://mindprod.com/jgloss/jasm.html
on how you might do that. With libraries like BCEL you are not
constructing the class file hex byte by byte.
If you have some Forth in your background, it should come fairly
easily since the JVM is very much like a dialect of Forth.

Have a look at various disassemblers including javap. See
http://mindprod.com/jgloss/disassembler.html

If you write some typical java you are composing on the fly, and look
at the byte code it generates, it should be easier for you to generate
the byte codes directly.
 
J

jan V

There are a number of .class file parsing/constructing/editing libs out
would you please name the most common ones ?

;-) The most common one for me is the one I wrote myself... so I'm no expert
on the others "out there". I just know there are several. You'll have to put
your Google shoes on..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,828
Latest member
LauraCastr

Latest Threads

Top