Fabio Hellmann
Erfahrenes Mitglied
Hi zusammen,
ich versuche zur Zeit einen ClassLoader zu schreiben, der Klassen aus einer Jar-Datei laden kann, die innerhalb einer Jar-Datei liegt.
Die Struktur einer solchen Jar-Datei kann wie folgt aussehen:
Bei meinem Beispiel, stellen die Dateien Jar1-3 eine Library (z.B. commons-io, etc.) dar. Diese Libaray - oder nur eine bestimmte Klasse daraus - will ich nun in die Laufzeitumgebung laden. Das ist schwieriger als es vielleicht klingt.
Ich hab mir erstmal ein JUnit-Test dafür angelegt:
Vielleicht hat jemand von euch ja einen genialen Einfall dazu. Würde mich freuen. 
ps.: Um zu überprüfen, dass die Klasse/Jar nicht schon vorher geladen wurde, habe ich der VM folgenden Parameter '-verbose:class' übergeben. Dadurch bekommt man alle geladenen/geöffneten Klassen/Jars angezeigt.
Gruß
Fabio
ich versuche zur Zeit einen ClassLoader zu schreiben, der Klassen aus einer Jar-Datei laden kann, die innerhalb einer Jar-Datei liegt.
Die Struktur einer solchen Jar-Datei kann wie folgt aussehen:
Code:
+ Jar
# package/package/package
# package/package
# package/package/package/package
# META-INF/
# Jar1
# Jar2
# Jar3
Ich hab mir erstmal ein JUnit-Test dafür angelegt:
Java:
public class JarClassLoaderTest extends TestCase
{
private static final File jarFile = new File("./Tests/Test.jar");
private final URL jarFileUrl;
private final JarURLConnection con;
/**
* @throws Exception
*/
public JarClassLoaderTest() throws Exception {
jarFileUrl = new URL("jar:file:" + jarFile.getAbsolutePath() + "!/");
con = (JarURLConnection) jarFileUrl.openConnection();
con.connect();
System.out.println("Connected to JarFile="+jarFileUrl.getPath());
}
/** @throws Exception */
public void testLoadJars() throws Exception {
final URLJarFile j = (URLJarFile) con.getContent();
System.out.println(j.getName());
final List<JarEntry> jarFiles = filterJarFiles(j.entries());
for(final JarEntry jarEntry : jarFiles) {
System.out.println(jarEntry.getName());
if(jarEntry.getName().startsWith("commons-io")) {
final URL innerJarFileUrl = new URL("jar:"+jarFileUrl.getPath()+jarEntry.getName());
System.out.println(innerJarFileUrl);
final ClassLoader cl = new URLClassLoader(new URL[] {innerJarFileUrl}, this.getClass().getClassLoader());
final Class<?> loadClass = Class.forName("org.apache.commons.io.IOUtils", true, cl);
}
}
}
/**
* @param entries
* @return
*/
private List<JarEntry> filterJarFiles(final Enumeration<JarEntry> entries) {
final List<JarEntry> jarList = new ArrayList<JarEntry>();
while(entries.hasMoreElements()) {
final JarEntry je = entries.nextElement();
final String name = je.getName();
if(name.endsWith(".jar")) {
jarList.add(je);
}
}
return jarList;
}
}

ps.: Um zu überprüfen, dass die Klasse/Jar nicht schon vorher geladen wurde, habe ich der VM folgenden Parameter '-verbose:class' übergeben. Dadurch bekommt man alle geladenen/geöffneten Klassen/Jars angezeigt.
Gruß
Fabio