如 LeetCode、Codeforces、洛谷、各大廠面試筆試平台,本質都是:前端提交代碼字符串 → 後端動態編譯/解釋執行 → 沙箱隔離 → 返回結果。
javax.tools.JavaCompiler) 或調用 javac 進程,將字符串編譯為 .class 字節碼。ClassLoader 定義類,反射調用 main 或指定方法。--cpus=1 --memory=256m --pids-limit=50 --network=none)。ptrace, clone, execve 等)。Future.get(timeout) + Process.destroyForcibly())。public class SimpleJavaRunner {
public static String run(String javaCode, String className, String[] args) throws Exception {
// 1. 寫入臨時文件
Path tempDir = Files.createTempDirectory("oj_");
Path srcFile = tempDir.resolve(className + ".java");
Files.write(srcFile, javaCode.getBytes(StandardCharsets.UTF_8));
// 2. 編譯
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compileResult = compiler.run(null, null, null, srcFile.toString());
if (compileResult != 0) return "Compilation Error";
// 3. 加載並運行
URLClassLoader classLoader = new URLClassLoader(new URL[]{tempDir.toUri().toURL()});
Class> clazz = classLoader.loadClass(className);
Method main = clazz.getMethod("main", String[].class);
// 捕獲標準輸出
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream oldOut = System.out;
System.setOut(new PrintStream(baos));
try {
main.invoke(null, (Object) args);
} finally {
System.setOut(oldOut);
}
return baos.toString();
}
}
絕不可直接在業務服務器運行用戶代碼!** 必須使用獨立判題機/容器集群,網絡隔離,定期銷毀重建。歷史上多起 OJ 平台被「挖礦代碼」「刪庫代碼」「反彈 Shell」攻陷,教訓慘痛。