|
Java™ by example!
|
|
|
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!
|
|
|
|
|