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

Exemple de code de compilation et d'exécution dynamique en Java

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 introduce a simple example to show how to use JavaCompiler to dynamically compile Java code.

1. Get JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

Get the JDK provided Java compiler, 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);
//Définir les paramètres de compilation
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 references other code, we need to set the path of the referenced code to-If not, the compilation will fail.

3. Execution

//The class name to be loaded
String className = "xxx.xxx.xxx";
//Get class loader
ClassLoader classLoader = XXX.class.getClassLoader();
//Charger la classe
Class<?> cls = classLoader.loadClass(className);
//Call method name
String methodName = "execute";
//Type array of method parameters
Class<?>[] paramCls = {...};
//Obtenir la méthode
Method method = cls.getDeclaredMethod(methodName , paramCls);
//Créer une instance de classe
Object obj = cls.newInstance();
//Paramètres de méthode
Object[] params = {...};
//Appeler la méthode
Object result = method.invoke(obj, params);

Quatre, code complet

//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();
	}
	/**
   * Obtenir le chemin d'accès au fichier 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;
	}
	/**
   * Compiler les fichiers java
   * @param ops 编译参数
   * @param files Fichiers à compiler
   */
	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("Compiler le fichier Java :" + file);
			}
		}
		catch(Exception e) {
			logger.error(e);
		}
		finally{
			if(manager!=null){
				try {
					manager.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
   * Générer le fichier java
   * @param file Nom du fichier
   * @param source java代码
   * @throws Exception
   */
	private static void ecrireFichierJava(String file,String source)throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("Ecrire le code source 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) {
			lancer e;
		}
		finally{
			if(bw!=null){
				bw.close();
			}
		}
	}
	/**
   * Charger la classe
   * @param name Nom de la classe
   * @return
   */
	private static Class<?> charger(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;
	}
}

Cinquième, 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");
		//Définir les paramètres de compilation
		ArrayList<String> ops = new ArrayList<String>();
		ops.add("-Xlint:unchecked");
		//Compilé le code, retourner la classe
		Class<?> cls = ClassUtil.loadClass("/com/even/test/Sum.java",sb.toString(),"com.even.test.Sum",ops);
		//Préparer les données de test
		Map<String,double> data = new HashMap<String,double>();
		data.put("f1", 10.0);
		data.put("f2", 20.0);
		data.put("f3", 30.0);
		//Exécuter la méthode de test
		Object result = ClassUtil.invoke(cls, "calculate", new Class[]{Map.class}, new Object[]{data});
		//Résultat de la sortie
		logger.debug(data);
		logger.debug("(30*f1+20*f2+50*f3)/100 = "+result);
	}

Résultat du test

16:12:02.860 DEBUG com.even.tools.ClassUtil - Écrire le code source Java à : .../classes//com/even/test/Sum.java
16:12:03.544 DEBUG com.even.tools.ClassUtil - Compiler le fichier Java :.../classes//com/even/test/Sum.java
16:12:03.545 DEBUG com.even.tools.ClassUtil - Charger la classe [com.even.test.Sum] par 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

Résumé

Voici tous les contenus de ce tutoriel sur l'exécution dynamique du code de compilation Java, j'espère qu'ils vous seront utiles. Les amis intéressés peuvent continuer à consulter notre site :

Partage de la compilation et du chargement dynamique de code en programmation Java

Exemple de code d'un problème de distance d'édition dans la programmation dynamique Java

Explication détaillée de l'implémentation de la référence et de l'agent dynamique en Java

Nous vous remercions de vos commentaires et suggestions. Merci à nos amis pour leur soutien à ce site !

Déclaration : le contenu de cet article est来源于网络,appartient à ses auteurs respectifs, le contenu est apporté par les utilisateurs d'Internet de manière volontaire et est téléchargé spontanément. Ce site ne détient pas de droits de propriété, n'a pas été traité par l'éditeur humain et ne assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de droits d'auteur, vous êtes invité à envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)

Vous pourriez aussi aimer