现在,在我开始之前 - 我是 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, loader);
// className is a String with the main class name in the jar
一切都很好,很花哨 - 我可以在加载的类中调用方法,一切正常。
现在,我希望能够在该 jar 文件中存储各种资源,并让类能够访问它们。我一直在查看 getResourceAsStream(),它看起来应该是正确的方法:
InputStream in = this.getClass().getClassLoader().getResourceAsStream("path/to/my/test.txt");
... 除了它总是返回 null。我一直在盯着关于这个功能的例子和其他论坛帖子等,但似乎没有一个适合我的具体情况:
- jar 文件在运行时使用 URLClassLoader 加载。
- jar 文件不在类路径中。
那么我在这些情况下尝试做的事情是否真的可行,或者我是否必须求助于手动解压 jar 文件以获取资源? (老实说,我宁愿不这样做。)
编辑:以下是我正在使用的函数:
加载一个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());
}
}
结果类中的函数:
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();
}
}
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
最佳答案
正如所发现的,问题是新的类加载器首先委托(delegate)给父类加载器,它正在寻找类。
选项:
- 确保当前的类加载器不有您要加载的类
- 在构造新的
URLClassLoader
时指定父类加载器引用(可能是null
?)
关于java - 在 Class.forName(...) 加载的 jar 上使用 getResourceAsStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17368986/