본문 바로가기
JAVA/Java Study

[동적 컴파일] 자바 동적 컴파일러

by 늑인 2024. 12. 18.
public class DynamicCompiler {

    public static void main(String[] args) {
        String sourceCode = 
            "public class HelloWorld {" +
            "   public void sayHello() {" +
            "       System.out.println(\"Hello, World!\");" +  // 누락된 세미콜론 추가
            "   }" +
            "}";

        try {
            // 컴파일된 클래스를 메모리에 저장하기 위한 임시 경로
            File tempDir = new File(System.getProperty("java.io.tmpdir"));

            // JavaCompiler API를 사용하여 코드 컴파일
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

            // Java 소스 코드 파일 생성
            File sourceFile = new File(tempDir, "HelloWorld.java");
            System.out.println(sourceFile);
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(sourceFile))) {
                writer.write(sourceCode);
            }

            // 컴파일 옵션 설정
            Iterable<? extends JavaFileObject> compilationUnits = 
                fileManager.getJavaFileObjectsFromFiles(Collections.singletonList(sourceFile));

            // DiagnosticCollector를 사용하여 에러 메시지 수집
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
            
            // CompilationTask 생성 시 diagnostics를 전달
            JavaCompiler.CompilationTask task = compiler.getTask(
                null, 
                fileManager, 
                diagnostics, // 에러 메시지 수집기 추가
                null, 
                null, 
                compilationUnits
            );

            // 컴파일 수행
            boolean success = task.call();

            // 컴파일 오류가 발생한 경우, 에러 메시지를 출력
            if (!success) {
                StringBuilder errorMessages = new StringBuilder();
                for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                    errorMessages.append("Error on line " + diagnostic.getLineNumber() + ": " + diagnostic.getMessage(null) + "\n");
                }
                System.err.println("Compilation failed:\n" + errorMessages.toString());
                sourceFile.delete();
                return;
            }


            // 컴파일된 클래스 로드
            URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { tempDir.toURI().toURL() });
            Class<?> clazz = classLoader.loadClass("HelloWorld");

            // 클래스 인스턴스 생성 및 메소드 호출
            Object instance = clazz.getDeclaredConstructor().newInstance();
            Method method = clazz.getMethod("sayHello");

            PrintStream orign = System.out;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(baos);
            System.setOut(ps);  // System.out을 새로운 PrintStream으로 변경

            // 메소드 호출 (콘솔 출력이 ByteArrayOutputStream으로 캡처됨)
            method.invoke(instance);

            // 콘솔 출력된 값을 가져오기
            String consoleOutput = baos.toString().trim();  // trim()을 사용하여 양쪽 공백 제거

            System.setOut(orign);

            // 캡처된 콘솔 출력 값 출력
            System.out.println("Captured Console Output: " + consoleOutput);


            // 임시 파일 정리
            sourceFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

'JAVA > Java Study' 카테고리의 다른 글

[Java] 한글 자소분리  (0) 2024.11.08
[Java] Record  (0) 2024.10.30
[GIS] 1. Shp 파일  (1) 2024.09.06
[Java] Mvc 패턴 Model1 , Model2  (0) 2024.06.25
[Java] Virtual Thread  (0) 2024.06.05