Java 在类.forName(…)加载的jar上使用getResourceAsStream
现在,在我开始之前,我对Java还不熟悉,我有点陷入了困境 我有一个系统,可以将jar文件中的类以插件的形式加载到我的应用程序中:Java 在类.forName(…)加载的jar上使用getResourceAsStream,java,class,jar,Java,Class,Jar,现在,在我开始之前,我对Java还不熟悉,我有点陷入了困境 我有一个系统,可以将jar文件中的类以插件的形式加载到我的应用程序中: URLClassLoader loader = new URLClassLoader(urlList); // urlList is a 1 slice URL[] with a single URL to a jar file in it Class<?> toolClass = Class.forName(className, true, loade
URLClassLoader loader = new URLClassLoader(urlList);
// urlList is a 1 slice URL[] with a single URL to a jar file in it
Class<?> toolClass = Class.forName(className, true, loader);
// className is a String with the main class name in the jar
。。。除非它总是返回null。我一直在关注有关此功能的示例和其他论坛帖子等,但它们似乎都不符合我的具体情况:
编辑:以下是我正在使用的函数: 加载jar文件:
public void loadPlugin(File jar)
{
try {
URL[] urlList = new URL[1];
urlList[0] = jar.toURI().toURL();
URLClassLoader loader = new URLClassLoader(urlList);
String className = null;
className = findClassInZipFile(jar); // This just walks the zip file looking for the class
if (className == null) {
return;
}
JarFile jf = new JarFile(jar);
Manifest manifest = jf.getManifest();
Attributes manifestContents = manifest.getMainAttributes();
Map pluginInfo = new LinkedHashMap();
pluginInfo.put("version", manifestContents.getValue("Version"));
pluginInfo.put("compiled", manifestContents.getValue("Compiled"));
pluginInfo.put("jarfile", jar.getAbsolutePath());
Class<?> toolClass;
try {
toolClass = Class.forName(className, true, loader);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
Tool tool = (Tool) toolClass.newInstance();
// If the setInfo method doesn't exist we don't care.
try {
tool.setInfo(pluginInfo);
} catch (Exception blah) {
}
plugins.put(className, tool);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
jar文件如下所示:
0 Fri Jun 28 16:52:32 BST 2013 META-INF/
140 Fri Jun 28 16:52:30 BST 2013 META-INF/MANIFEST.MF
0 Fri Jun 28 16:52:32 BST 2013 uecide/
0 Fri Jun 28 16:52:32 BST 2013 uecide/app/
0 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/
1880 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/ExportToMPLABX.class
2754 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/test.txt
正如所发现的,问题是新类加载器首先委托给父类加载器,父类加载器正在查找类 选项:
- 确保当前类加载器没有您试图加载的类
- 在构造新的
时,指定父类加载器引用(可能是URLClassLoader
?)null
/
开头!您的示例中没有/
,这可能是您的问题所在here@fge:这是不正确的。如果使用Class.getResourceAsStream()
从根开始,而不是从类的包开始,则它们必须以/
开始。如果使用ClassLoader.getResourceAsStream()
,则它们不能以/
开头。在示例代码中,这个是什么?它与创建URLClassLoader的对象是同一个对象,还是从jar加载的类的实例?@Majenko:您是否仔细检查了this.getClass().getClassLoader()
是否返回了您期望的类加载器?有可能它正在委托给类中的另一个类。forName…对URLClassLoader的父类加载器使用null会导致它无法找到类。@Majenko:这很有趣-这表明它在查找jar文件时出现了问题。嗯,我想这是值得调试的。我想我会坚持在加载时将加载程序传递给类。我想我没有多余的大脑来思考这个问题。
public void run() {
try {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("uecide/app/tools/test.txt");
if (in == null) {
System.err.println("FAIL!!!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
0 Fri Jun 28 16:52:32 BST 2013 META-INF/
140 Fri Jun 28 16:52:30 BST 2013 META-INF/MANIFEST.MF
0 Fri Jun 28 16:52:32 BST 2013 uecide/
0 Fri Jun 28 16:52:32 BST 2013 uecide/app/
0 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/
1880 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/ExportToMPLABX.class
2754 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/test.txt