Solved

compile Java source in memory (and run result)

Posted on 2009-05-10
17
850 Views
Last Modified: 2012-05-06
Hello everybody,

I want to build Java sources dynamically and compile them - and of course run the generated classes FROM MEMORY (i.e. without generating files, just to stress this as much as I can :-)).

I know it's "always" been possible to invoke javac, but for one thing, I don't like accessing a "com.sun.java.tools..."-package, and also, this required java source files.

It looks like this has become a lot easier in Java 6 and I've come across a "solution" at
http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm.

Unfortunately, it doesn't work 100%: The compilation succeeds, but the (attempted) call results in a ClassNotFoundException.

Who can help me solve this? I'd hope it's just a small thing... the folks at java2s.com wouldn't post sample code that is untested and broken, would they? :-)
0
Comment
Question by:Ronald112197
  • 5
  • 5
  • 5
  • +2
17 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 24348944
What problems are you having with the code? Please post the stack trace. It runs fine for me
0
 
LVL 2

Author Comment

by:Ronald112197
ID: 24349168
it prints:
Success: true
Class not found: java.lang.ClassNotFoundException: HelloWorld

Stacktrace:
java.lang.ClassNotFoundException: HelloWorld
      at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:169)
      at CompileSourceInMemory.main(CompileSourceInMemory.java:52)

I'm running this in Eclipse - code style is 6.0, default VM is JDK 6.

Hmm... interesting - it actually works when I invoke it from the command line (I don't recompile, I just run it from the command line using JDK 6)... what could be causing this effect? Do I have to move the question to the "Eclipse"-section now? :-)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24349236
It's probably because Eclipse has its own ideas about the classpath
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 100 total points
ID: 24349276
You can tell what the command line one is by doing the following, and what Eclipse's is by looking at the .classpath file
 out.println("public class HelloWorld {");

    out.println("  public static void main(String args[]) {");

    out.println("    System.out.println(\"This is in another java file and here is the classpath\");");

    out.println("    System.out.println(System.getProperty(\"java.class.path\"));");

    out.println("  }");

    out.println("}");

    out.close();

Open in new window

0
 
LVL 92

Expert Comment

by:objects
ID: 24350413
>  Do I have to move the question to the "Eclipse"-section now? :-)

probably a good idea. This is an eclipse problem, to do with its class loaders. In particular it only picks up classes in a source folder (which you're generated ones are not in)

0
 
LVL 92

Expert Comment

by:objects
ID: 24352000
> the folks at java2s.com wouldn't post sample code that is untested and broken, would they? :-)

doubt much of their code is tested :)   though they aren't as bad as some of the sites around.


You would need to use a custom class loader to handle loading the class from memory


0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24352382
>>You would need to use a custom class loader to handle loading the class from memory

That's not the case (as the code you've just run shows)
0
 
LVL 92

Accepted Solution

by:
objects earned 200 total points
ID: 24353244
Theres details on a classloader that should enable you to load the class in the following article

http://www.nobel-joergensen.com/roller/java/entry/using_eclipse_compiler_to_create

Its using the eclipse compiler but the concept is the same. Use of the eclipse compiler may also be of interest.

0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 2

Expert Comment

by:harrys
ID: 24353245
Its a side effect of eclipse's classloader/classpath handling, the code runs fine when invoked from the command line
0
 
LVL 92

Expert Comment

by:objects
ID: 24353282
thats right, so using a custom class loader should get around it.
0
 
LVL 12

Assisted Solution

by:Gibu George
Gibu George earned 200 total points
ID: 24356873
The problem is that the class file is generated into the projects root folder if you change that to the default output folder it will work from eclipse. I change this line and it worked for me

JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

to
JavaFileObject file = new JavaSourceFromString("../bin/HelloWorld", writer.toString());
where ../bin/ is the default output folder
0
 
LVL 2

Author Comment

by:Ronald112197
ID: 24359179
O I C.... :-)

See, this is me playing with code I copied and pasted without examining closely what it does. Naive as I am, I thought that a class called compileINmemory would actually compile in memory ;D

Looking at it again, I see that the page title is more accurate: "compile FROM memory" (to disk)

I don't like having to change the code to run from Eclipse, but the last comment pointed me to the simple solution: configure the program's working directory to be the "classes"-folder (or any other folder that's on the classpath). This is fine since I don't have to change the code for Eclipse, just configure Eclipse...

I guess my problem is solved and I'm ready to split the points between CEHJ and gibu_george.

However, I now don't like the code so much any more :-( What happens if I put my classes into a jar-file? The generated classes end up in whichever (working) directory the user happens to be in? (btw: Is the current directory ALWAYS on the classpath? I think that was not the case in older versions of Java...)

I'll toss in an extra 250 points for code that puts my class into a package (which for some reason isn't as easy as I'd thought... ) and actually compiles IN memory without creating files on disk... (which should be fine as an addition since MY question is actually called "compile IN memory"...

Regards,

Ronald
0
 
LVL 2

Author Comment

by:Ronald112197
ID: 24359193
P.S.: I think I've seen the solution (compile IN memory) in some blog, but I can't find it any more :-(
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 100 total points
ID: 24359243
0
 
LVL 92

Expert Comment

by:objects
ID: 24359907
> configure the program's working directory to be the "classes"-folder (or any other folder that's on the classpath).

mentioned that earlier:
objects> In particular it only picks up classes in a source folder (which you're generated ones are not in)

>  and actually compiles IN memory without creating files on disk...

the example I posted above compiles in memory

0
 
LVL 2

Author Comment

by:Ronald112197
ID: 24673640
Hello experts,

sorry for my long absence - I really didn't have time to do this lately - but I've always had you on my mind ;-))

I have finally implemented the full solution and it works quite nicely (I also need the "dynamically compiled class" to interact with my other classes and even that seems to be no problem so far - I run from Eclipse so far and hope there won't be additional problems with the "deployed" version which uses a special classloader... we'll see...)

I'll split the points as follows:
100 to CEHJ for "continued support" and some pointers in the right direction, although it didn't quite nail it...

200 to gibu_george for clearly showing and solving the problem I had - although I'd like to mention that I don't like his proposed solution: Adjusting the code to make up for environment problems is not such a good idea. As I mentioned above, I reconfigured Eclipse instead and the code will work both in Eclipse and in a JDK... Anyway, it showed me what was going on... (should've figured that out by myself, I guess...)

200 "new points" to objects for posting the correct code sample that I am now using (and which solves all the problems I had with the previous sample). It's quite compact, self-contained and seems to work quite nicely. I think the link posted by CEHJ is basically the same, but it's split across several classes in different packages and I'd need to download and adjust all of them to remove dependencies to even other utility classes in the packages...
@objects: You said "Use of the Eclipse compiler may also be of interest" - why? It's an additional download, an additional dependency and an additional source of incompatibilities. Using the JDK compiler in Eclipse works just fine (it seems to be a little slow on the startup, though...). Any advantage in using the Eclipse compiler?

Thanks!
0
 
LVL 2

Author Comment

by:Ronald112197
ID: 24674446
Hello experts!

As I'd feared, I have problems with our special classloader (some classes are encrypted).
I have posted a new question about this, you can find it at http://www.experts-exchange.com/Programming/Languages/Java/Q_24508460.html

Maybe you have some ideas? (and I'll be a lot faster with the grading this time as I'm currently working on this and feel like I'm "almost there"...)
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now