我正在尝试使用包含String对象和我创建的自定义类的构造函数实例化动态加载的类(使用自定义类加载器)。
我已经在项目之外重新创建了该问题,这是假定A.class
已经在目标文件夹中。
主要方法:
public class simplifiedMainMethod {
static boolean propagate = false;
static Class<?> projectActions = null;
static Object oInstance;
public static void main (String[] args)
{
String projectName = "A";
String baseUrl = "https://www.google.com/";
simplifiedReport reporter = new simplifiedReport();
try
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Reloader r = new Reloader(cl);
if (propagate)
Thread.currentThread().setContextClassLoader(r);
projectActions = r.loadClass("autobots_framework."+projectName);
Constructor<?> c = projectActions.getConstructor(String.class, simplifiedReport.class);
oInstance = c.newInstance(baseUrl, reporter);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
simplifiedReport.java:
public class simplifiedReport
{
public simplifiedReport()
{
}
public void testMethod()
{
System.out.println("Hello World");
}
}
A.java
:
public class A
{
public A(String testString, simplifiedReport testReport)
{
System.out.println(testString);
testReport.testMethod();
}
}
这是我正在使用的CustomClassLoader
:
public class ClassLoaderCompiler
{
public ClassLoaderCompiler()
{}
public static boolean compileCode(String fileDirectory, String projectName) throws IOException
{
JavaCompiler compiler = new EclipseCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(fileDirectory));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
try
{
task.call();
fileManager.close();
return true;
}
catch(Exception e)
{
fileManager.close();
return false;
}
}
public static void moveClassFile(String projectName)
{
try
{
Files.deleteIfExists(new File(System.getProperty("user.dir")+"/target/classes/autobots_framework/"+projectName+".class").toPath());
Files.deleteIfExists(new File(System.getProperty("user.dir")+"/target/classes/autobots_framework/L_"+projectName+".class").toPath());
if (Files.exists(Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/"+projectName+".class")))
{
Path temp = Files.move (Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/"+projectName+".class"),Paths.get(System.getProperty("user.dir")+"/target/classes/autobots_framework/"+projectName+".class"));
Path tempLocator = Files.move (Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/L_"+projectName+".class"),Paths.get(System.getProperty("user.dir")+"/target/classes/autobots_framework/L_"+projectName+".class"));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* adapted from http://stackoverflow.com/a/3971771/7849
*/
class Reloader extends ClassLoader {
static URL url;
ClassLoader orig;
Reloader(ClassLoader orig) {
this.orig = orig;
}
@Override
public Class<?> loadClass(String s) {
return findClass(s);
}
@Override
public Class<?> findClass(String s) {
try {
byte[] bytes = loadClassData(s);
return defineClass(s, bytes, 0, bytes.length);
} catch (IOException ioe) {
try {
return super.loadClass(s);
} catch (ClassNotFoundException ignore) {
ignore.printStackTrace(System.out);
}
ioe.printStackTrace(System.out);
return null;
}
}
private byte[] loadClassData(String className) throws IOException {
try {
/*
* get the actual path using the original classloader
*/
Class<?> clazz = orig.loadClass(className);
url = clazz.getResource(clazz.getSimpleName() + ".class");
/*
* force reload
*/
File f = new File(url.toURI());
int size = (int) f.length();
byte buff[] = new byte[size];
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
dis.readFully(buff);
dis.close();
return buff;
} catch (Exception ex) {
throw new IOException(ex);
}
}
}
结果是我收到此错误:
java.lang.NoSuchMethodException: autobots_framework.A.<init>(java.lang.String, autobots_framework.simplifiedReport)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getConstructor(Unknown Source)
我认为这是由于参数不匹配所致,因此为了确认我尝试查找构造函数在隐式寻找的内容:
for (Constructor c : projectActions.getDeclaredConstructors())
{
System.out.print(c.toGenericString());
}
产生此结果:
public autobots_framework.A(java.lang.String,autobots_framework.simplifiedReport)
令人沮丧的看起来很像我在这里放的东西:
Constructor<?> c = projectActions.getConstructor(String.class, simplifiedReport.class);
oInstance = c.newInstance(baseUrl, reporter);
我知道这与我的课程有关,因为当我在构造函数中省略simplifiedReport
并仅用String.class
实例化它时,我就成功了。我在课堂上缺少什么修饰语来实现这项工作?
这是我应用程序的全部功能,可以动态编译代码,然后实例化它们以运行自定义代码和方法。