最近做项目,有个需求需要实现动态类加载,通过尝试成功解决了该问题,记录下来,以便未来碰到此类问题有一个参考.
package com.demo;
public class Person {
protected String name;
protected String job;
public Person(String name, String job) {
super();
this.name = name;
this.job = job;
}
public void introduction() {
System.out.println("my name is " + name + ",job is " + job);
}
}
package com.demo;
import com.demo.Person;
public class Teacher extends Person {
public Teacher(String name, String job) {
super(name, job);
}
}
package com.demo;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class Runner {
public static final String JAVA_SUFFIX = ".java";
public static final String CLASS_SUFFIX = ".class";
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Exception {
String path = "d:/test/";
String compileDir = "d:/test/classes/";
String javaName = "Person";
compileAlone(path, compileDir, javaName);
String clazzName = "com.demo.Person";
Class clazz = loadClas(compileDir, clazzName);
System.out.println("load class name: " + clazz.getName());
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
Object person = declaredConstructor.newInstance("张三", "医生");
Method method = clazz.getDeclaredMethod("introduction");
method.invoke(person);
System.out.println("======================");
javaName = "Teacher";
compile(path, compileDir, javaName);
clazz = loadClas(compileDir, clazzName);
declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
person = declaredConstructor.newInstance("王五", "教师");
method = clazz.getDeclaredMethod("introduction");
method.invoke(person);
}
public static void compileAlone(String path, String compileDir, String javaName) {
File f = new File(compileDir);
if (!f.exists()) {
f.mkdirs();
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<String> options = new ArrayList<String>();
options.add("-d");
options.add(compileDir);
String javaPath = Paths.get(path, javaName + JAVA_SUFFIX).toFile().getPath();
options.add(javaPath);
int compilerResult = compiler.run(null, null, null, options.toArray(new String[options.size()]));
System.out.println(compilerResult == 0 ? "compile success" : "compile fail");
}
public static void compile(String path, String compileDir, String javaName) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<String> options = new ArrayList<String>();
options.add("-d");
options.add(compileDir);
options.add("-cp");
options.add(compileDir);
String javaPath = Paths.get(path, javaName + JAVA_SUFFIX).toFile().getPath();
options.add(javaPath);
int compilerResult = compiler.run(null, null, null, options.toArray(new String[options.size()]));
System.out.println(compilerResult == 0 ? "compile success" : "compile fail");
}
@SuppressWarnings({ "resource", "rawtypes" })
public static Class loadClas(String compileDir, String clazzName) throws Exception {
URL[] urls = new URL[] { new URL("file:" + compileDir) };
URLClassLoader loader = new URLClassLoader(urls);
Class clazz = loader.loadClass(clazzName);
System.out.println("load class success");
return clazz;
}
public static Class loadClass3(String compileDir, String clazzName) throws Exception {
ClassLoader classLoader = Person.class.getClassLoader();
URL[] urls = new URL[] { new URL("file:" + compileDir) };
URLClassLoader loader = new URLClassLoader(urls, classLoader);
Class<?> clazz = loader.loadClass(clazzName);
return clazz;
}
}