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

Java dynamic compilation and execution code example

In some cases, we need to dynamically generate Java code, compile it dynamically, and then execute the code. The JAVAAPI provides the corresponding tools (JavaCompiler) to implement dynamic compilation. Below, we will introduce through a simple example how to dynamically compile Java code using JavaCompiler.

1. Get JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

Get the Java compiler provided by JDK, if no compiler is provided, return null;

2. Compilation

//Get Java file management class
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
//Get Java file object iterator
Iterable<? extends JavaFileObject> it = manager.getJavaFileObjects(files);
//Set compilation parameters
ArrayList<String> ops = new ArrayList<String>();
ops.add("-Xlint:unchecked");
//Set classpath
ops.add("-classpath);
ops.add(CLASS_PATH);
//Get compilation task
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, ops, null, it);
//Execute compilation task
task.call();

When the source code we want to compile refers to other code, we need to set the path of the referenced code to-If not in the classpath, the compilation will fail.

3. Execution

//Class name to load
String className = "xxx.xxx.xxx";
//Get class loader
ClassLoader classLoader = XXX.class.getClassLoader();
//Load class
Class<?> cls = classLoader.loadClass(className);
//Call method name
String methodName = "execute";
//Method parameter type array
Class<?]>[] paramCls = {...};
//Get method
Method method = cls.getDeclaredMethod(methodName , paramCls);
//Create class instance
Object obj = cls.newInstance();
//Method parameters
Object[] params = {...};
//Invoke method
Object result = method.invoke(obj, params);

IV. Complete Code

//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();
	}
	/**
   * Get the Java file path
   * @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.separator character;
	}
	/**
   * Compile java file
   * @param ops Compilation parameters
   * @param files Compilation 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("Compile Java File:") + file);
			}
		}
		catch(Exception e){
			logger.error(e);
		}
		finally{
			if(manager!=null){
				try {
					manager.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
   * Generate java file
   * @param file File name
   * @param source Java code
   * @throws Exception
   */
	private static void writeJavaFile(String file,String source)throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("Write Java Source Code to:")+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();
			}
		}
	}
	/**
   * Load class
   * @param name Class 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;
	}
	/**
   * Compile code and load class
   * @param filePath Java code path
   * @param source Java code
   * @param clsName Class name
   * @param ops Compilation parameters
   * @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;
	}
	/**
   * Invoke class method
   * @param cls Class
   * @param methodName Method name
   * @param paramsCls Method parameter types
   * @param params Method parameters
   * @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;
	}
}

Five, Test

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");
		//Set compilation parameters
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//Compile code, return class
		Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);
		//Prepare test data
		Map<String,double> data = new HashMap<String,double>();
		data.put("f1", 10.0);
		data.put("f2", 20.0);
		data.put("f3", 30.0);
		//Execute test method
		Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});
		//Output Result
		logger.debug(data);
		logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);
	}

Test Results

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

Summary

That's all about the example of dynamic compilation and execution code of Java dynamic compilation in this article. I hope it will be helpful to everyone. Those who are interested can continue to refer to this site:

Share dynamic compilation and loading code in java programming

Example code of edit distance problem in Java dynamic programming

Detailed explanation of references and dynamic proxy implementation in Java

If there is anything lacking, please leave a message to point it out. Thank you friends for your support to this site!

Statement: The content of this article is from the network, the copyright belongs to the original author, the content is contributed and uploaded by Internet users spontaneously, this website does not own the copyright, has not been manually edited, nor does it assume relevant legal liability. If you find any suspected copyright content, please send an email to: notice#oldtoolbag.com (when sending an email, please replace # with @ to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the suspected infringing content.)

You may also like