Eigener ClassLoader

Status
Nicht offen für weitere Antworten.
B

bananenkasper

Gast
Hallo zusammen,

Ich möchte zur Laufzeit class-Files / jar-Files lesen und diese dann als "Plugin" im Hauptprogramm nutzen.
Nutze ich zum Laden der class-Files z.B. URLClassLoader wird, soweit ich das verstanden habe, immer erst der ClassPath durchsucht.
Wenn mein class-File jetzt zufällig den selben Namen hat wie eine Systemklasse wird die Falsche geladen.
Wie kann ich einen ClassLoader realisieren, der nur in einem bestimmten Verzeichnis sucht und den definierten ClassPath ausser Acht lässt?
 

0x7F800000

Top Contributor
reicht es nicht im Konstruktor die speziellen URL's zu übergeben, wo er suchen soll? Wenn du nur genau den Ordner mit den Plugins angibst, dann entsteht dadurch doch keine Verwechslungsgefahr, oder????:L
 

Der Müde Joe

Top Contributor
hab da grad noch was auf der Platte...sollte eigentlich funktionieren..
aber ?? Keine Garantie...lang ists her...
[HIGHLIGHT="Java"]import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;


public class JarClassLoader extends ClassLoader {

private JarResource jarResource;

public JarClassLoader(String jarName) {
jarResource = new JarResource(jarName);
}

@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, true);
}

@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> result;
// ist vielleicht schon im CP
try {
result = super.findSystemClass(name);
System.out.println("Klasse im Classpath gefunden");
return result;
} catch (ClassNotFoundException e) {
System.out.println("Klasse nicht im Classpath");
}
// lade von der Resource
byte[] classBytes = jarResource.getResource(formatClassUrl(name));
if (classBytes == null) {
throw new ClassNotFoundException("Klasse nicht in der jar");
}
result = defineClass(name, classBytes, 0, classBytes.length);
if (result == null) {
throw new ClassFormatException();
}
if (resolve) {
resolveClass(result);
}
return result;
}

private static final String formatClassUrl(String jarName) {
String result = jarName.replace('.', '/');
return result + ".class";
}

public static void main(String[] args) throws ClassNotFoundException, Exception,
IllegalAccessException {
JarClassLoader loader = new JarClassLoader(
"/main/Development/sourcen/spring-framework-2.5.6/lib/dom4j/dom4j-1.6.1.jar");
Class<?> clazz = loader.loadClass("org.dom4j.XPath");
Class<?> clazz2 = loader.loadClass("org.dom4j.util.NodeComparator");
System.out.println(clazz);
System.out.println(clazz2);
Object nc = clazz2.newInstance();
System.out.println(nc);
}
}
[/HIGHLIGHT]

[HIGHLIGHT="Java"]import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;

public final class JarResource {

private Map<String, Long> classSizes = new HashMap<String, Long>();

private Map<String, byte[]> jarContent = new HashMap<String, byte[]>();

private String jarFileName;

public JarResource(String jarFileName) {
this.jarFileName = jarFileName;
init();
}

public byte[] getResource(String name) {
return jarContent.get(name);
}

private void init() {
try {
File file = new File(jarFileName);
if (!file.exists()) {
throw new FileNotFoundException();
}
JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> enu = jarFile.entries();
while (enu.hasMoreElements()) {
JarEntry entry = enu.nextElement();
classSizes.put(entry.getName(), entry.getSize());
}
jarFile.close();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
JarInputStream jis = new JarInputStream(bis);
JarEntry entry = null;
while ((entry = jis.getNextJarEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
long size = entry.getSize();
if (size < 0) {
size = classSizes.get(entry.getName());
}
byte[] buffer = new byte[(int) size];
int offset = 0;
while ((size - offset) > 0) {
int chunk = jis.read(buffer, offset, (int) size - offset);
if (chunk == -1) {
break;
}
offset += chunk;
}
jarContent.put(entry.getName(), buffer);
}
} catch (NullPointerException e) {
System.out.println("done.");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
[/HIGHLIGHT]
 
B

bananenkasper

Gast
Hmmm, dabei muss ich aber auch immer den vollständigen Namen der Klasse / jar kennen, die ich laden will.
("org.dom4j.XPath").

Wenn ich jetzt aber einen Plugin-Ordner habe, der Klassen / jars enthält, deren Namen ich zur Laufzeit nicht kenne?
Lässt sich aus dem Dateinamen irgendwie der Klassenname ("org.dom4j.XPath") ableiten?
 

Der Müde Joe

Top Contributor
>Wenn ich jetzt aber einen Plugin-Ordner habe, der Klassen / jars enthält, deren Namen ich zur Laufzeit nicht kenne?

Naja...den Ordner musst du kennen. Somit kannst du dir auch alle Files darin Listen lassen. Jars kannst du dann mit der JarResource einlesen. In der Map sind dann alle Entries..sprich alle Files. Mit einigen Modifikationen sollte es Möglich sein, einfach alle .class Files im jar zu finden und über der JarClassLoader zu laden.
 
B

bananenkasper

Gast
>Wenn ich jetzt aber einen Plugin-Ordner habe, der Klassen / jars enthält, deren Namen ich zur Laufzeit nicht kenne?

Naja...den Ordner musst du kennen. Somit kannst du dir auch alle Files darin Listen lassen. Jars kannst du dann mit der JarResource einlesen. In der Map sind dann alle Entries..sprich alle Files. Mit einigen Modifikationen sollte es Möglich sein, einfach alle .class Files im jar zu finden und über der JarClassLoader zu laden.

Ja, soweit so gut!
Das Problem ist
<code>
Class<?> clazz = loader.loadClass("org.dom4j.XPath");
</code>

"loadClass() will den vollständig qualifizierenden Namen. Also paket.hans.peter.Klasse.
Das ist aber von Jar zu Jar unterschiedlich...
 

Der Müde Joe

Top Contributor
>Das ist aber von Jar zu Jar unterschiedlich

Der FQN sollte über den Pfad zu erhalten sein. Die Methode formatClassUrl macht dabei eigentlich nix anderes als aus com.hans.peter.Klasse ein com/hans/peter/Klasse umzuwandeln, so wie es auch in der FileStruktur sein sollte.

EDIT:
Du solltes natürlich den umgekehrten weg machen, sprich von File im Jar zum FQN ;-)
 
Zuletzt bearbeitet:

Wildcard

Top Contributor
Wenn du es mit PlugIns ernst meinst, dann würde ich die zu einem entsprechenden Framework wie OSGi raten. Sehr einfache Dinge lassen sich zwar noch mit einem URLClassLoader erledigen, aber sobald es ein wenig komplexer wird bekommst du Probleme mit der Klassensichtbarkeit innerhalb der Classloading Hierarchie.
Die einzelnen PlugIns Classloadertechnisch von einander zu isolieren ist ebenfalls nicht ganz trivial selbst zu implementieren.
 
B

bananenkasper

Gast
>Das ist aber von Jar zu Jar unterschiedlich

Der FQN sollte über den Pfad zu erhalten sein. Die Methode formatClassUrl macht dabei eigentlich nix anderes als aus com.hans.peter.Klasse ein com/hans/peter/Klasse umzuwandeln, so wie es auch in der FileStruktur sein sollte.

EDIT:
Du solltes natürlich den umgekehrten weg machen, sprich von File im Jar zum FQN ;-)

Das werde ich mal ausprobieren...

Wenn du es mit PlugIns ernst meinst, dann würde ich die zu einem entsprechenden Framework wie OSGi raten. Sehr einfache Dinge lassen sich zwar noch mit einem URLClassLoader erledigen, aber sobald es ein wenig komplexer wird bekommst du Probleme mit der Klassensichtbarkeit innerhalb der Classloading Hierarchie.
Die einzelnen PlugIns Classloadertechnisch von einander zu isolieren ist ebenfalls nicht ganz trivial selbst zu implementieren.

OSGi hab ich mir grad mal angeschaut....
Sieht recht kompliziert aus...
Wenn ich bei jedem Plugin noch gucken muss, dass ich das Jar richtig baue (Manifestfile apassen etc.) wirds schon suboptimal.
Die Plugins sollen so einfach wie möglich zu schreiben sein.
(Ich selbst werde die wenigsten schreiben, das machen andere)
Am Besten eine Klasse schreiben die Interface >Plugin< implementiert, in ein Jar packen, läuft!
So hatte ich mir das vorgestellt...
 

Wildcard

Top Contributor
OSGi hab ich mir grad mal angeschaut....
Sieht recht kompliziert aus...
Das täuscht.
Wenn ich bei jedem Plugin noch gucken muss, dass ich das Jar richtig baue (Manifestfile apassen etc.) wirds schon suboptimal.
Darum kümmern sich IDEs wie Eclipse (Eclipse basiert selbst auch auf OSGi).
Die Plugins sollen so einfach wie möglich zu schreiben sein.
(Ich selbst werde die wenigsten schreiben, das machen andere)
Am Besten eine Klasse schreiben die Interface >Plugin< implementiert, in ein Jar packen, läuft!
Du musst dir darüber klar werden was alles möglich sein soll. Spätestens wenn deine PlugIns Bibliotheken verwenden wollen kommst du an die Grenzen dessen was du ohne sehr gut durchdachtes Classloading/Dependency/Deployment Konzept überhaupt noch handeln kannst.
Wenn das für dich kein Thema ist, mach wie du es für richtig hälst. Wenn deine Anforderungen über die Basics hinausgehen, tue dir den Gefallen kein eckiges Rad neu zu erfinden.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Eigener ClassLoader wird nicht immer verwendet Allgemeine Java-Themen 3
G JavaDocu in eigener Bibliothek Allgemeine Java-Themen 2
HarleyDavidson Eigener PropertyChangeListener funktioniert einfach nicht Allgemeine Java-Themen 3
T Datei öffnen mit eigener Applikation.exe Allgemeine Java-Themen 4
D Arraylist eigener Klasse an iReport übergeben Allgemeine Java-Themen 7
K Jar mit eigener JRE ausliefern Allgemeine Java-Themen 13
G eigener PropertyChangedListener Allgemeine Java-Themen 2
S OOP ClassCastException bei casting von eigener Klasse aus Iterator Allgemeine Java-Themen 3
V Serialisierung von Instanz eigener Klasse Allgemeine Java-Themen 5
N Vergleich eigener Klassen Allgemeine Java-Themen 5
T Vererbung Eigener Datentyp: Betriebsmittel Allgemeine Java-Themen 2
J Erste Schritte Kommerzielle nutzung eigener Javaapplets auf der Homepage Allgemeine Java-Themen 2
B Probleme mit eigener equals Methode Allgemeine Java-Themen 18
Kr0e Eigener Updatemechanismus Allgemeine Java-Themen 7
J Mein eigener Messenger und dessen Probleme Allgemeine Java-Themen 48
S Profiler-Funktionen in eigener Applikation nutzen..? Allgemeine Java-Themen 5
R Eigener Comparator Allgemeine Java-Themen 2
T Zeit von einem Server/Webseite auslesen und in eigener GUI anzeigen Allgemeine Java-Themen 6
V Probleme mit eigener Hashmap Allgemeine Java-Themen 10
R Eigener Assoziativ-Speicher Allgemeine Java-Themen 7
T CP Problem: Webstart + Logging properties file + eigener Handler Allgemeine Java-Themen 7
P eigener Klassenname Allgemeine Java-Themen 4
D Eigener Key bei AES Verschlüsselung Allgemeine Java-Themen 4
T enums - eigener startwert Allgemeine Java-Themen 5
P eigener Thread für einen JButton Allgemeine Java-Themen 32
F Checkbox in JTable , eigener Cellrenderer -wie gehts weiter? Allgemeine Java-Themen 2
A JRE auf eigener Seite verlinken oder zum Download anbieten? Allgemeine Java-Themen 13
E Wie: Eigener Listener, eigenes Event (möglichst einfach) Allgemeine Java-Themen 29
G eigener logger mittels classe (dynamische logfilename) log4j Allgemeine Java-Themen 15
D Eigener Maven2 Plugin Server? Allgemeine Java-Themen 3
I RSA - Eigener Quelltext Allgemeine Java-Themen 4
M eigener LautstärkeRegler schädlich für soundkarte? Allgemeine Java-Themen 4
K JTree plus eigener FileLoader Allgemeine Java-Themen 2
L Problem mit eigener, abgeleiteter Klasse Allgemeine Java-Themen 2
S Eigener Editor Allgemeine Java-Themen 7
L Eigener Onlinestunden- Zähler / Problemchen Allgemeine Java-Themen 2
L Classpath Zur Laufzeit bestimmte Klassen in Classloader hinzufügen? Allgemeine Java-Themen 4
L Eigenener ClassLoader wirft java.lang.NoClassDefFoundError Allgemeine Java-Themen 0
D Classloader ohne Package Allgemeine Java-Themen 10
N Klasse via ClassLoader laden Allgemeine Java-Themen 2
D ClassLoader für Variablen einer Klasse setzen Allgemeine Java-Themen 24
K [Refactoring] ClassLoader Verzeichnis durchsuchen lassen Allgemeine Java-Themen 7
schlingel Webstart/Applet Problem - Classloader-Bug Allgemeine Java-Themen 7
M Security Manager für bestimmte Klassen/Classloader? Allgemeine Java-Themen 3
hdi ClassLoader / Constructor Call intern Allgemeine Java-Themen 11
C inteface not visible from classloader Allgemeine Java-Themen 2
M jdbc treiber (h2) mit eigenem ClassLoader laden Allgemeine Java-Themen 4
MQue ClassLoader Pfad ausgeben Allgemeine Java-Themen 6
S Problem mit ClassLoader.getSystemResource !! Allgemeine Java-Themen 3
V Image laden - URL über ClassLoader ermitteln Allgemeine Java-Themen 2
E Wieder mal der Classloader Allgemeine Java-Themen 6
F ClassLoader und "Cache" Allgemeine Java-Themen 2
MQue ClassLoader Allgemeine Java-Themen 5
N ClassLoader - Laden von Bytecode aus einer Datenbank Allgemeine Java-Themen 6
P Klasse über eigenen Classloader laden: SecurityException Allgemeine Java-Themen 11
N Classpath mit ClassLoader künstlich erweitern Allgemeine Java-Themen 2
P System.getProperty zu Classloader Allgemeine Java-Themen 21
G Classloader Problem Allgemeine Java-Themen 10
M Bibliotheksname zur Laufzeit ermitteln (Classloader) Allgemeine Java-Themen 7
MQue ClassLoader Allgemeine Java-Themen 18
G Problem mit URL classloader Allgemeine Java-Themen 10
S classloader + jar + resourcen in dem jar Allgemeine Java-Themen 4
F mit classloader klassen ausserhalb *.jar einlesen Allgemeine Java-Themen 4
G Font mittels ClassLoader in .jar wirft NotFoundException Allgemeine Java-Themen 10
P Kompilerfehler: at java.lang.ClassLoader.loadClassInternal(U Allgemeine Java-Themen 16
T ClassLoader und Zugriff auf unbekannte Klassen Allgemeine Java-Themen 5
C ClassLoader - dymisches Laden von JDBC Drivers Allgemeine Java-Themen 3
R Problem mit Classloader Allgemeine Java-Themen 2
D Programm mit eigenem ClassLoader funktioniert nicht Allgemeine Java-Themen 12
K Problem mit ClassLoader - Laden von Resourcen aus Jar's Allgemeine Java-Themen 14
C Problem mit ClassLoader Allgemeine Java-Themen 2
T Brauche Hilfe bei ClassLoader Allgemeine Java-Themen 2
G cachender ClassLoader u.v.m. Allgemeine Java-Themen 5
G ClassLoader Allgemeine Java-Themen 3
R ClassLoader funktioniert in Verbindung mit JAR-Datei nicht Allgemeine Java-Themen 8

Ähnliche Java Themen

Neue Themen


Oben