Skip to content

Instantly share code, notes, and snippets.

@audinue
Last active March 26, 2025 16:39
Show Gist options
  • Save audinue/f4a24b2a65216de00a7fac80ef6153a6 to your computer and use it in GitHub Desktop.
Save audinue/f4a24b2a65216de00a7fac80ef6153a6 to your computer and use it in GitHub Desktop.
Runs Java code from string.
import java.io.ByteArrayOutputStream
import java.io.OutputStream
import java.net.URI
import javax.tools.*
fun main() {
val outputs = mutableMapOf<String, ByteArrayOutputStream>()
val compiler = ToolProvider.getSystemJavaCompiler()
compiler.getTask(
null,
object : ForwardingJavaFileManager<StandardJavaFileManager>(
compiler.getStandardFileManager(null, null, null)
) {
override fun getJavaFileForOutput(
location: JavaFileManager.Location,
className: String,
kind: JavaFileObject.Kind,
sibling: FileObject
): JavaFileObject {
return object : SimpleJavaFileObject(URI.create(className), kind) {
override fun openOutputStream(): OutputStream {
val output = ByteArrayOutputStream()
outputs[className] = output
return output
}
}
}
},
null,
null,
null,
listOf(
object : SimpleJavaFileObject(URI.create("Main.java"), JavaFileObject.Kind.SOURCE) {
override fun getCharContent(ignoreEncodingErrors: Boolean): CharSequence {
return """
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
"""
}
}
)
).call()
object : ClassLoader() {
override fun findClass(name: String): Class<*> {
val bytes = outputs[name]!!.toByteArray()
return defineClass(name, bytes, 0, bytes.size)
}
}.loadClass("Main")
.getMethod("main", Array<String>::class.java)
.invoke(null, arrayOf<String?>(null))
}
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
public class Runner {
public static void main(String[] args) throws Exception {
HashMap<String, ByteArrayOutputStream> outputs = new HashMap<>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.getTask(
null,
new ForwardingJavaFileManager<StandardJavaFileManager>(
compiler.getStandardFileManager(null, null, null)
) {
@Override
public JavaFileObject getJavaFileForOutput(
Location location,
String className,
JavaFileObject.Kind kind,
FileObject sibling
) {
return new SimpleJavaFileObject(URI.create(className), kind) {
@Override
public OutputStream openOutputStream() {
ByteArrayOutputStream output = new ByteArrayOutputStream();
outputs.put(className, output);
return output;
}
};
}
},
null,
null,
null,
Arrays.asList(
new SimpleJavaFileObject(URI.create("Main.java"), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return "public class Main {" +
" public static void main(String[] args) {" +
" System.out.println(\"Hello world!\");" +
" }" +
"}";
}
}
)
).call();
new ClassLoader() {
@Override
protected Class<?> findClass(String name) {
byte[] bytes = outputs.get(name).toByteArray();
return defineClass(name, bytes, 0, bytes.length);
}
}
.loadClass("Main")
.getMethod("main", String[].class)
.invoke(null, new Object[]{null});
}
}
@audinue
Copy link
Author

audinue commented Mar 26, 2025

Useful for testing Java code generators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment