2013. február 12., kedd

Külső JAR-ok betöltése

Elkezdtem építeni a PubSearch 2-t, és a JavaFX Scene Builder, illetve az FXML technológia kipróbálása után (zseniális cuccok!!!) nekiláttam a leglényegesebb mechanikának: a külső JAR-ok betöltésének.

Napokig szenvedtem azzal, hogy miért nem működik a dolog teljesen. Külső JAR-ból class betöltés még ment URLClassLoader-rel, de a cast-olás már nem. Akármit csináltam, nem akarta cast-olni egy interfészre, amit az osztály meg is valósít, és nem értettem.



Ma, ismét hosszú guglizás után, már nem is tudom hányadik kulcsszókombinációval és hányadik találati oldalon, de megleltem a probléma okát és innen egyből rájöttem a megoldásra: http://stackoverflow.com/questions/2591779/cast-across-classloader.

Ugyanis az interfész és a külső class két külön class loader által lett betöltve, és class loader-eken közti cast-olás nem lehetséges, mert az osztályokat a teljes nevükön kívül a class loader-ük is azonosítja.

Ma korábban találtam egy tippet, hogy az URLClassLoader-nek meg lehet adni parent class loader-t. Én eddig a system class loader-t próbáltam, de a fenti linken olvasottak alapján rájöttem, hogy az URLClassLoader-t azon class loader alá kell rendelni, amelyik betöltötte az interfészemet. És működik! :-)

Példa kód:
String c = "betoltendo.Osztaly";
URL u = new File("c:/jar/fajl/helye/betoltendo.jar").toURI().toURL();
URLClassLoader cl = new URLClassLoader(new URL[]{u}, Interfeszem.class.getClassLoader());
Class<? extends Interfeszem> clazz = (Class<? extends Interfeszem>) Class.forName(c, true, cl);
Interfeszem i = clazz.newInstance();
System.out.println(i.adjEgyStringet());
Egy másik példában láttam, és tényleg így is a logikus: az interfészt is érdemes külön projektbe, JAR-ba tenni, ami később a főprogram lib könyvtárában kap helyet.

2 megjegyzés:

Richard O. Legendi írta...

Ezt értékelni fogod akkor :-)

http://geekandpoke.typepad.com/geekandpoke/2010/12/the-geekpoke-pattern-tip-of-the-week.html

juzraai írta...

Igen, pontosan, "csak egy maradhat" :D