Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[Java] URLClassLoader pakt niet nieuwste file

Pagina: 1
Acties:

  • Enfer
  • Registratie: Februari 2004
  • Laatst online: 10-10 13:28
Hey :) Ik ben nu bezig om voor mijn IRC-bot in een dynamische classloader te maken, zodat ik de bot niet hoef te restarten om wijzigingen te kunnen testen.

Ik doet door middel van een object opnieuw inladen, waarvoor ik eerst de gecompileerde klasse op probeer te halen..
Maar op de een of andere manier krijg ik bij het ophalen nooit de nieuwe versie van een .class bestand, maar altijd de versie die in de map stond wanneer ik het programma startte. (Terwijl ik 100% zeker de bestanden compileer en dus verander)

Ik maak gebruik van de volgende URLClassLoader
Java:
1
2
3
4
5
6
7
8
9
10
11
    public void herLaad(){
        try
        {
            URLClassLoader clsLoader = new URLClassLoader(new URL[]{new URL("file:/" + "./")});
            Class c = clsLoader.loadClass("Factory");
            factory = null;
            factory = (Factory)c.newInstance();
            factory.setBot( this );
        }
        catch(Exception e){ e.printStackTrace(); } 
    }


Weet iemand waarom dit is, en hoe dit op valt te lossen? Ikzelf heb al wel de search gebruikt, maar er kwam weinig bruikbare topics voor mij uit. Ook heb ik al gegoogled op de URLClassloaders maar ook daar kon ik geen oplossing vinden..

(Is het een probleem qua cashing o.i.d)?

  • RayNbow
  • Registratie: Maart 2003
  • Nu online

RayNbow

Kirika <3

Het zou mogelijk hieraan kunnen liggen:
[...]
It is important that the reloadable class not be on the classpath. Otherwise, the class will be loaded by some parent of the new class loader rather than by the new class loader itself. Once this happens, the class cannot be reloaded.
[...]

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


  • momania
  • Registratie: Mei 2000
  • Laatst online: 30-11 19:29

momania

iPhone 30! Bam!

Je moet idd altijd de class zelf laden, ook bij het opstarten. Aangezien je nu te maken hebt met een parent classloader die de class al heeft geladen :)

Volgens mij kan je trouwens ook via de current/parent classloader deze class wel opnieuw laden. Ipv door zelf een classloader aan te maken en het daamee te doen.
Van de factory instantie die je hebt kan je z'n class loader ophalen en het met die opnieuw laden. Moet je wel zorgen dat de nieuwe class in een aparte directory oid aan het begin van je classpath staat.

Puur theorie hoor, of het werkt moet je even zelf mee gaan prutsen ;)

Neem je whisky mee, is het te weinig... *zucht*


  • Enfer
  • Registratie: Februari 2004
  • Laatst online: 10-10 13:28
Even een (grote) schop.

Ik heb dit probleem weer opgepakt, en heb het nog eens kritisch bekeken.

De situatie die ik nu heb is alsvolgt:
Een standaard ingeladen library, die erft van ReloadableClass, en een nieuwe library die ik dus tijdens het runnen van het programma wil vervangen met de oude library. Ook deze nieuwe library erft van ReloadableClass, zodat er geen verwarring bij java ontstaat over class-types e.d. De standaard ingeladen klasse library staat in een package library, en de in te laden library staat 1 map hoger dan de classpath, in een mapje dir.

Ik heb er voor gezorgt dat de library mooi buiten de classpath staat, netjes in een mapje directory. Maar het probleem is nu dat ik telkens een Exception krijg die ik niet vat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java.lang.NoClassDefFoundError: Library (wrong name: library/Library)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at factory.Botje.reload(Botje.java:54)


Ik heb hierop al gegoogled maar meestal kwamen er beginners vragen uit. Dit zette mij aan het denken en toen controleerde ik of de class wel gevonden werd door de classloader.
Java:
1
 System.out.println( cl.findResource( "Library.class" ) );

Print netjes de correcte uri uit naar de in te laden klasse.

Hieronder de code van het reloaden
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void reload(){
        // Get the directory (URL) of the reloadable class
        URL[] urls = null;
        try {
            // Convert the file object to a URL
            File dir = new File(System.getProperty("user.dir")
                    +File.separator+"dir"+File.separator);
            URL url = dir.toURI().toURL();
            //System.out.println( url.toString() );
            urls = new URL[]{url};
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        
        try {
            // Create a new class loader with the directory
            URLClassLoader cl = new URLClassLoader(urls);
        
            // Load in the class
            System.out.println( cl.findResource( "Library.class" ) );
            
            Class<?> cls = cl.loadClass( "Library" );
            
            //ReloadableClass newL = (ReloadableClass)l.newInstance();
            
        
            // Create a new instance of the new class
            ReloadableClass myObj = (Library)cls.newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


Ik kom er eventjes niet meer uit waarom deze exceptie nou gegooid word. Ook op de java forums / google kunnen ze mij niet helpen, dus ik hoop dat jullie dat wel kunnen.

Dus hoe los ik dit probleem op..

  • paulh
  • Registratie: Juli 1999
  • Laatst online: 28-11 15:14
Bij een NoClassDefFoundError kan die class loader meestal wel de class zelf vinden maar niet een class die in de te laden class gebruikt wordt. Dus check even welke objecten je in je Library class nog meer gebruikt die eventueel vindbaar zouden moeten zijn.

[ZwareMetalen.com] - [Kom in aktie tegen de CO2 maffia]


  • Enfer
  • Registratie: Februari 2004
  • Laatst online: 10-10 13:28
Ah dat zou best eens het probleem kunnen zijn..
In mijn Library gebruik ik daarvan namelijk 2 objecten:
import factory.Botje;
import factory.ReloadableClass;

Deze zijn wel zichtbaar vanuit de plek waar de loader gemaakt word zeg maar, maar dus niet vanuit buiten waar de 'nieuwe' libraty zit. Het loaden word namelijk gedaan in (factory.)Botje, ik weet niet of je die dus weer op de een of andere manier moet meegeven aan die classloader?

( Er zijn nog een hele hoop andere imports, maar die komen rechtstreeks uit de java api dus die lijken mij niet echt boeiend om te vermelden, dat moet wel goed gaan ;) )

Bij het compilen van de Library buiten classpath kon ik het classpath gewoon als argument meegeven, en dan werkte het..
Maar hoe gaat dat nu in zijn werk? Aangezien je niet kunt importen van buiten je classpath.

Edit:


er zat dus een fout in de nieuwe library, waar nog boven stond package librabry;

Maargoed nu komt de volgende error opdagen:
java.lang.ClassCastException: Library cannot be cast to library.Library

Dit komt op de volgende regel
ReloadableClass myObj = (library.Library)cls.newInstance();

Hij kan dus niet naar casten naar de library.. Terwijl het toch wel 2 dezeflde soort klassen zijn. Kan het zijn dat java dat niet door heeft, en je dat moet aangeven?

[ Voor 60% gewijzigd door Enfer op 03-10-2007 22:28 ]


  • Enfer
  • Registratie: Februari 2004
  • Laatst online: 10-10 13:28
Oke het is nu dus opgelost..
Met vele dank voor prototype uit #devschuur ( irc.tweakers.net dus ) :Y)
Klaarblijkelijk moeten de oude library, en de nieuwe te laden library BUITEN de classpath staan, ik dacht alleen de nieuwe..
En het casten is ook gelukt door er een interface omheen te zetten, zodat je kunt instantieren aan de hand van het interface ;)
Pagina: 1