English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 동적 컴파일 및 실행 코드 예제

일부 경우에, 우리는 동적 java 코드를 생성하고, 동적 컴파일을 통해 코드를 실행해야 합니다. JAVAAPI는 동적 컴파일을 구현하기 위한相应的 도구(JavaCompiler)를 제공합니다. 아래에서는 JavaCompiler를 통해 java 코드 동적 컴파일을 구현하는 방법을 간단한 예제를 통해 소개합니다.

1. JavaCompiler 가져오기

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

JDK가 제공하는 java 컴파일러를 가져옵니다. 컴파일러가 제공되지 않으면 null을 반환합니다;

2. 컴파일

//java 파일 관리 클래스 가져오기
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
//java 파일 객체 이터레이터 가져오기
Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);
//컴파일 파라미터 설정
ArrayList<String> ops = new ArrayList<String>();
ops.add("-Xlint:unchecked");
//class path 설정
ops.add("-classpath");
ops.add(CLASS_PATH);
//컴파일 작업 가져오기
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
//컴파일 작업 실행
task.call();

编译할 소스 코드에서 다른 코드를 참조하는 경우, 참조 코드 경로를 설정해야 합니다-class path에 있지 않으면 컴파일 실패합니다.

3. 실행

//로드할 클래스 이름
String className = "xxx.xxx.xxx";
//클래스 로드기 가져오기
ClassLoader classLoader = XXX.class.getClassLoader();
//로드 클래스
Class<?> cls = classLoader.loadClass(className);
//메서드 호출 이름
String methodName = "execute";
//메서드 파라미터 타입 배열
Class<?>[] paramCls = {...};
//메서드 가져오기
Method method = cls.getDeclaredMethod(methodName , paramCls);
//클래스 인스턴스 생성
Object obj = cls.newInstance();
//메서드 매개변수
Object[] params = {...};
//메서드 호출
Object result = method.invoke(obj, params);

4. 전체 코드

//ClassUtil.java
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClassUtil {
	private static final Log logger = LogFactory.getLog(ClassUtil.class);
	private static JavaCompiler compiler;
	static{
		compiler = ToolProvider.getSystemJavaCompiler();
	}
	/**
   * Java 파일 경로를 가져오기
   * @param file
   * @return
   */
	private static String getFilePath(String file){
		int last1 = file.lastIndexOf('/);
		int last2 = file.lastIndexOf('\');
		return file.substring(0, last1>last2?last1:last2)+File.separatorChar;
	}
	/**
   * java 파일 컴파일
   * @param ops 编译参数
   * @param files 컴파일 파일
   */
	private static void javac(List<String> ops,String... files){
		StandardJavaFileManager manager = null;
		try{
			manager = compiler.getStandardFileManager(null, null, null);
			Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);
			JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
			task.call();
			if(logger.isDebugEnabled()){
				for (String file:files)
				          logger.debug("Java 파일 컴파일:" + file);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		finally{
			if(manager!=null){
				try {
					manager.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
   * Java 파일 생성
   * @param file 파일 이름
   * @param source java代码
   * @throws Exception
   */
	private static void writeJavaFile(String file,String source)throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("Java 소스 코드를 쓰기:"+file);
		}
		BufferedWriter bw = null;
		try{
			File dir = new File(getFilePath(file));
			if(!dir.exists())
			        dir.mkdirs();
			bw = new BufferedWriter(new FileWriter(file));
			bw.write(source);
			bw.flush();
		}
		catch(Exception e){
			throw e;
		}
		finally{
			if(bw!=null){
				bw.close();
			}
		}
	}
	/**
   * 로드 클래스
   * @param name 클래스 이름
   * @return
   */
	private static Class<?> load(String name){
		Class<?> cls = null;
		ClassLoader classLoader = null;
		try{
			classLoader = ClassUtil.class.getClassLoader();
			cls = classLoader.loadClass(name);
			if(logger.isDebugEnabled()){
				logger.debug("Load Class["+name+"] by \+classLoader);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		return cls;
	}
	/**
   * 编译代码并加载类
   * @param filePath java代码路径
   * @param source java代码
   * @param clsName 类名
   * @param ops 编译参数
   * @return
   */
	public static Class<?> loadClass(String filePath, String source, String clsName, List<String> ops){
		try {
			writeJavaFile(CLASS_PATH+filePath,source);
			javac(ops,CLASS_PATH+filePath);
			return load(clsName);
		}
		catch (Exception e) {
			logger.error(e);
		}
		return null;
	}
	/**
   * 调用类方法
   * @param cls 类
   * @param methodName 方法名
   * @param paramsCls 方法参数类型
   * @param params 方法参数
   * @return
   */
	public static Object invoke(Class<?> cls, String methodName, Class<?>[] paramsCls, Object[] params){
		Object result = null;
		try {
			Method method = cls.getDeclaredMethod(methodName, paramsCls);
			Object obj = cls.newInstance();
			result = method.invoke(obj, params);
		}
		catch (Exception e) {
			logger.error(e);
		}
		return result;
	}
}

5. 테스트

public class ClassUtilTest {
	private static final Log logger = LogFactory.getLog(ClassUtilTest.class);
	public static void main(String args[]){
		StringBuilder sb = new StringBuilder();
		sb.append("package com.even.test;");
		sb.append("import java.util.Map;\nimport java.text.DecimalFormat;\n");
		sb.append("public class Sum{\n");
		sb.append("private final DecimalFormat df = new DecimalFormat(\"#.#####\");\n");
		sb.append("public Double calculate(Map<String,Double> data){\n");
		sb.append("double d = (30*data.get(\"f1\") + 20*data.get(\"f2\") + 50*data.get(\"f3\"))/100;\n");
		sb.append("return Double.valueOf(df.format(d));}}\n");
		//컴파일 파라미터 설정
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//코드 컴파일, class 반환
		Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);
		//테스트 데이터 준비
		Map<String,double> data = new HashMap<String,double>();
		data.put("f1", 10.0);
		data.put("f2", 20.0);
		data.put("f3", 30.0);
		//테스트 메서드 실행
		Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});
		//출력 결과
		logger.debug(data);
		logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);
	}

테스트 결과

16:12:02.860 DEBUG com.even.tools.ClassUtil - Write Java Source Code to: .../classes//com/even/test/Sum.java
16:12:03.544 DEBUG com.even.tools.ClassUtil - Compile Java File:.../classes//com/even/test/Sum.java
16:12:03.545 DEBUG com.even.tools.ClassUtil - Load Class[com.even.test.Sum] by sun.misc.Launcher$AppClassLoader@73d16e93
16:12:03.547 DEBUG com.even.test.ClassUtilTest - {f1=10.0, f2=20.0, f3=30.0}
16:12:03.547 DEBUG com.even.test.ClassUtilTest - (30*f1+20*f2+50*f3)/100 = 22.0

결론

이 문서에서 Java 동적 컴파일 실행 코드 예제에 대한 모든 내용을 설명했습니다. 도움이 되셨기를 바랍니다. 관심이 있는 분은 이 사이트를 계속 참조하십시오:

java 프로그래밍 동적 컴파일 로드 코드 공유

Java 동적 계획의 편집 거리 문제 예제 코드

Java에서의 참조와 동적 대리자 구현에 대한 자세한 설명

불충분한 부분이 있으면 알려주시기 바랍니다. 친구들의 이 사이트에 대한 지원에 감사합니다!

고지사항: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권자가 모두 소유하고 있으며, 인터넷 사용자가 자발적으로 기여하고 자체적으로 업로드한 내용입니다. 이 사이트는 소유권을 가지지 않으며, 인공 편집을하지 않았으며, 관련 법적 책임을 부담하지 않습니다. 저작권 위반 내용을 발견하면 이메일을 보내 주십시오: notice#oldtoolbag.com(이메일을 보내는 경우, #을 @으로 변경하십시오. 신고하시고 관련 증거를 제공하십시오. 확인되면 이 사이트는 즉시 위반 내용을 삭제합니다.)

추천해드립니다