fork(2) download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import javax.tools.*;
  4. import java.io.ByteArrayOutputStream;
  5. import java.io.IOException;
  6. import java.io.OutputStream;
  7. import java.lang.reflect.InvocationTargetException;
  8. import java.net.URI;
  9. import java.security.SecureClassLoader;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.io.PrintWriter;
  13. import java.io.StringWriter;
  14. //import org.slf4j.Logger;
  15. //import org.slf4j.LoggerFactory;
  16.  
  17. class Ideone
  18. {
  19. // private static final Logger logger = LoggerFactory.getLogger(Main.class);
  20.  
  21. public static void main (String[] args) throws java.lang.Exception
  22. {
  23. try {
  24. StringWriter writer = new StringWriter();
  25. PrintWriter out = new PrintWriter(writer);
  26. out.println("package com.mycompany.scripts;");
  27. out.println("");
  28. out.println("public class HelloWorld {");
  29. out.println(" public static void main(String args[]) {");
  30. out.println(" System.out.println(\"This is in another java file\");");
  31. out.println(" }");
  32. out.println("}");
  33. out.close();
  34.  
  35. // Full name of the class that will be compiled.
  36. // If class should be in some package,
  37. // fullName should contain it too
  38. // (ex. "testpackage.DynaClass")
  39. String fullName = "com.mycompany.scripts.HelloWorld";
  40.  
  41. // Here we get and specify the source code of the class to be compiled
  42. String src = writer.toString();
  43.  
  44. DynamicCompiler uCompiler = new DynamicCompiler(fullName, src);
  45. uCompiler.compile();
  46. uCompiler.run();
  47.  
  48. } catch (Exception e) {
  49. // logger.error("Exception:", e);
  50. System.out.print("Exception");
  51. }
  52. }
  53. }
  54.  
  55. // Based on: http://j...content-available-to-author-only...t.cz/2011/06/dynamic-in-memory-compilation-using.html
  56. class DynamicCompiler {
  57. private JavaFileManager fileManager;
  58. private String fullName;
  59. private String sourceCode;
  60.  
  61. public DynamicCompiler(String fullName, String srcCode) {
  62. this.fullName = fullName;
  63. this.sourceCode = srcCode;
  64. this.fileManager = initFileManager();
  65. }
  66.  
  67. public JavaFileManager initFileManager() {
  68. if (fileManager != null)
  69. return fileManager;
  70. else {
  71. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  72. fileManager = new
  73. ClassFileManager(compiler
  74. .getStandardFileManager(null, null, null));
  75. return fileManager;
  76. }
  77. }
  78.  
  79. public void compile() {
  80. // We get an instance of JavaCompiler. Then
  81. // we create a file manager
  82. // (our custom implementation of it)
  83. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  84.  
  85. // Dynamic compiling requires specifying
  86. // a list of "files" to compile. In our case
  87. // this is a list containing one "file" which is in our case
  88. // our own implementation (see details below)
  89. List<JavaFileObject> files = new ArrayList<>();
  90. files.add(new CharSequenceJavaFileObject(fullName, sourceCode));
  91.  
  92. // We specify a task to the compiler. Compiler should use our file
  93. // manager and our list of "files".
  94. // Then we run the compilation with call()
  95. compiler.getTask(
  96. null,
  97. fileManager,
  98. null,
  99. null,
  100. null,
  101. files
  102. ).call();
  103. }
  104.  
  105. // Creating an instance of our compiled class and
  106. // running its toString() method
  107. try {
  108. fileManager
  109. .getClassLoader(null)
  110. .loadClass(fullName)
  111. .getDeclaredMethod("main", new Class[]{String[].class})
  112. .invoke(null, new Object[]{null});
  113. //logger.error("InvocationTargetException:", e);
  114. System.out.print("InvocationTargetException");
  115. } catch (NoSuchMethodException e) {
  116. //logger.error("NoSuchMethodException:", e);
  117. System.out.print("NoSuchMethodException");
  118. }
  119. }
  120.  
  121. public class CharSequenceJavaFileObject extends SimpleJavaFileObject {
  122.  
  123. /**
  124.   * CharSequence representing the source code to be compiled
  125.   */
  126. private CharSequence content;
  127.  
  128. /**
  129.   * This constructor will store the source code in the
  130.   * internal "content" variable and register it as a
  131.   * source code, using a URI containing the class full name
  132.   *
  133.   * @param className name of the public class in the source code
  134.   * @param content source code to compile
  135.   */
  136. public CharSequenceJavaFileObject(String className, CharSequence content) {
  137. super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
  138. this.content = content;
  139. }
  140.  
  141. public CharSequence getCharContent(boolean ignoreEncodingErrors) {
  142. return content;
  143. }
  144. }
  145.  
  146. public class ClassFileManager extends ForwardingJavaFileManager {
  147. private JavaClassObject javaClassObject;
  148.  
  149. public ClassFileManager(StandardJavaFileManager standardManager) {
  150. super(standardManager);
  151. }
  152.  
  153. /**
  154.   * Will be used by us to get the class loader for our
  155.   * compiled class. It creates an anonymous class
  156.   * extending the SecureClassLoader which uses the
  157.   * byte code created by the compiler and stored in
  158.   * the JavaClassObject, and returns the Class for it
  159.   */
  160. @Override
  161. public ClassLoader getClassLoader(Location location) {
  162. return new SecureClassLoader() {
  163. @Override
  164. protected Class<?> findClass(String name) throws ClassNotFoundException {
  165. byte[] b = javaClassObject.getBytes();
  166. return super.defineClass(name, javaClassObject.getBytes(), 0, b.length);
  167. }
  168. };
  169. }
  170.  
  171. public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
  172. this.javaClassObject = new JavaClassObject(className, kind);
  173. return this.javaClassObject;
  174. }
  175. }
  176.  
  177. public class JavaClassObject extends SimpleJavaFileObject {
  178. /**
  179.   * Byte code created by the compiler will be stored in this
  180.   * ByteArrayOutputStream so that we can later get the
  181.   * byte array out of it
  182.   * and put it in the memory as an instance of our class.
  183.   */
  184. protected final ByteArrayOutputStream bos =
  185.  
  186. /**
  187.   * Registers the compiled class object under URI
  188.   * containing the class full name
  189.   *
  190.   * @param name
  191.   * Full name of the compiled class
  192.   * @param kind
  193.   * Kind of the data. It will be CLASS in our case
  194.   */
  195. public JavaClassObject(String name, Kind kind) {
  196. super(URI.create("string:///" + name.replace('.', '/')
  197. + kind.extension), kind);
  198. }
  199.  
  200. /**
  201.   * Will be used by our file manager to get the byte code that
  202.   * can be put into memory to instantiate our class
  203.   *
  204.   * @return compiled byte code
  205.   */
  206. public byte[] getBytes() {
  207. return bos.toByteArray();
  208. }
  209.  
  210. /**
  211.   * Will provide the compiler with an output stream that leads
  212.   * to our byte array. This way the compiler will write everything
  213.   * into the byte array that we will instantiate later
  214.   */
  215. @Override
  216. public OutputStream openOutputStream() throws IOException {
  217. return bos;
  218. }
  219. }
  220. }
Success #stdin #stdout 0.38s 714752KB
stdin
Standard input is empty
stdout
This is in another java file