esuslogo
 [To advertise Java(tm) Events here, contact us!]
banner

Java™
by example!






New @ Esus.com


  gb  In-house search engine for better results!

  gb  Get updates with the esus.com
newsletter!









  Home 
 Browse Categories 
 Ask a Java Question 
 Help 
  For Java Tips & Tricks, subscribe to the esus.com newsletter!
Search Java Q&A, Links, API's:   adv 

How do I on-the-fly compile a java source contained in a String?



A bit of hacking around lead to the following example. Create an instance of InMemorySourceCompiler and pass it the name of the program and the source code as a String. Any suggestions/improvements are appreciated as a comment to this answer.

The following example creates a JFrame that contains the output of the source.

Main.java:


import java.lang.reflect.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.*;
import java.util.*;
import java.io.*;

import sun.tools.javac.*;
import sun.tools.java.*;

public class Main extends JFrame
{
public Main(String s) {
getContentPane().add(new JTextArea(s, 3, 50));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(1);
}
});
}

public static void main(String args[]) throws Exception
{
// Save all data written to System.out to a byte array and display in frame
PrintStream ps = System.out;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));

InMemorySourceCompiler imsCompiler = new InMemorySourceCompiler("Test",
"public class Test {" +
" public static void main(String args[]) {" +
" System.out.println(\"Output of program:\");" +
" for (int i=0; i<10; i++) {" +
" System.out.println(i);" +
" }" +
" System.out.println(\"End of output.\");" +
" }" +
"}");
imsCompiler.executeMain();

byte[] b = baos.toByteArray();

System.setOut(ps);

String s = new String(b);

Main main = new Main(s);
main.setSize(200, 230);
main.setVisible(true);
}
}

class InMemorySourceCompiler {
protected String name;
protected String source;
protected Class compiledClass;

public InMemorySourceCompiler(String name, String source) throws Exception {
this.name = name;
this.source = source;
loadClass();
}

protected void loadClass() throws Exception {
ClassPath cp = new ClassPath(System.getProperty("java.class.path"));
OutputStream os = System.out;
BatchEnvironment be = new BatchEnvironment(os, cp);
be.flags = 0x41004;
be.majorVersion = 45;
be.minorVersion = 3;
be.covFile = null;
be.setCharacterEncoding(null);

be.parseFile(new InMemorySourceClassFile(name+".java", source));

ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);

be.flushErrors();
Vector v = new Vector();

for (Enumeration enum = be.getClasses(); enum.hasMoreElements();) {
v.addElement(enum.nextElement());
}

for (int i=0; i<v.size(); i++) {
ClassDeclaration cd = (ClassDeclaration) v.elementAt(i);
Object object = cd.getClassDefinition(be);

if (object instanceof SourceClass) {
SourceClass sourceclass = (SourceClass) object;
cd.setDefinition(sourceclass, 5);
SourceClass sourceclass1 = (SourceClass) object;
baos.reset();
sourceclass.compile(baos);
}
else if (object instanceof BinaryClass) {
BinaryClass binaryclass = (BinaryClass) object;
binaryclass.write(be, baos);
}
byte[] b = baos.toByteArray();

InMemorySourceCompilerClassLoader myClassLoader = new InMemorySourceCompilerClassLoader();
compiledClass = myClassLoader.getClassFromBytes(name, b);
}
}

public void executeMain() throws Exception {
Method m = compiledClass.getMethod("main", new Class[]{ String[].class });
m.invoke(null, new Object[]{null});
}

static class InMemorySourceCompilerClassLoader extends ClassLoader
{
public Class getClassFromBytes(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}
}

class InMemorySourceClassFile extends ClassFile
{
private String filename;
private String text;

public InMemorySourceClassFile(String filename, String text) {
super(new File(filename));
this.filename = filename;
this.text = text;
}

public String getAbsoluteName() {
return filename;
}

public boolean exists() {
return true;
}

public InputStream getInputStream() {
return new StringBufferInputStream(text);
}

public String getName() {
return filename;
}

public String getPath() {
return "";
}

public boolean isDirectory() {
return false;
}

public boolean isZipped() {
return false;
}

public long lastModified() {
return new Date().getTime();
}

public long length() {
return text.length();
}

public String toString() {
return filename;
}
}




Further Information
Author of answer: unknown

Comments to this answer are only viewable by members. Login or become a member!





Terms of Service | Privacy Policy | Contact

Copyright © 2000-2003 Esus.com - All Rights Reserved 
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. Esus.com is independent of Sun Microsystems, Inc. All other trademarks are the sole property of their respective owners.