我试图将从外部jar加载的类实例添加到要执行的作业列表中,但是似乎我在使用类加载器时遇到问题。
这是我正在使用的代码:
private ConcurrentSkipListSet<ISchedulerJob> load(String externalPluginPath) {
ConcurrentSkipListSet<ISchedulerJob> listJobs = new ConcurrentSkipListSet<>();
final File loc = new File(externalPluginPath);
// Add files with filter
final File[] flist = loc.listFiles((File file) -> file.getPath().toLowerCase().endsWith(".jar"));
// return if there are no files to load
if (flist == null)
return null;
final List<JarFile> jars = new ArrayList<>();
for (File jar : flist) {
try {
JarFile jarFile = new JarFile(jar);
jars.add(jarFile);
} catch (IOException ex) {
ex.printStackTrace();
}
}
// Files to Url
URL[] urls;
try {
urls = FileUtils.toURLs(flist);
} catch (IOException ex) {
urls = new URL[0];
}
final URLClassLoader ucl = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
jars.stream().map((jar) -> jar.entries()).forEach((e) -> {
while (e.hasMoreElements()) {
try {
JarEntry je = (JarEntry) e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
String className = je.getName().replace(".class", "");
className = className.replace('/', '.');
Class<?> cls = ucl.loadClass(className);
if (ISchedulerJob.class.isAssignableFrom(cls)) {
listJobs.add((ISchedulerJob) cls.newInstance());
}
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
}
});
try {
ucl.close();
} catch (IOException ex) {
ex.printStackTrace();
}
for (JarFile jarFile : jars) {
try {
jarFile.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
jars.clear();
return listJobs;
}
基本上,当代码到达以下行时:
if (ISchedulerJob.class.isAssignableFrom(cls)) {
它返回false,并且不允许我将实例添加到集合中。如果无论如何我尝试添加它,即使被实例化的类确实实现了该接口,也会得到ClassCastException。 最奇怪的是,此代码可在同事计算机上运行,而该计算机正在Windows上执行。在我的机器(这是Fedora)上,它根本无法工作。
在这种情况下有什么区别?