Avatar billede theill Nybegynder
20. juli 2000 - 16:17 Der er 11 kommentarer og
1 løsning

Class (re)loading med JDK1.2

Jeg har kaempe problemer med at faa mine klasser til at reloade paa den maade, jeg oensker.

Mit problem er, at jeg har en klasse A, der bruger en statisk (package protected) variabel 'var1' i klasse B, fx:

package com.da.lige;
class A
{
  public A()
  {
    System.out.println("Hello " + B.var1);
  }
}


package com.da.lige;
class B
{
  static String var1 = "Eksperten!";
 
}


Godt, nu er det saadan, at jeg vil goere det muligt, at reloade mine klasser mens jeg koerer mit lille Java proggy. Problemet er, at jeg paa ingen maade kan faa JVM til at forstaa, at min klasse A tilhoerer samme pakke som klasse B, saa jeg kan ikke faa lov til at bruge 'var1', hvis jeg reloader klasse A.

Det kan jo ikke vaere meningen ... eller er det mig, der har misforstaaet hele begrebet? Jeg har forsoegt med mange (laes: rigtig mange) implementeringer af ClassLoader klassen, men det er ikke lykkedes mig at faa det til at virke (uden at loade *alle* klasser i en given pakke og det er jeg ikke interesseret i!).

Et eksempel paa min mest simple ClassLoader, kan se ud som flg:

public class FrameworkClassLoader extends ClassLoader
{
  private byte[] loadClassData(String classname)
  {
    FileInputStream fis = null;
    ByteArrayOutputStream baos = null;
    try
    {
        String filename = classname.replace('.', '/') + ".clazz";
        fis = new FileInputStream(filename);
        baos = new ByteArrayOutputStream();
        byte buf[] = new byte[4092];
        for(int i = 0; (i = fis.read(buf)) != -1; )
        {
            baos.write(buf, 0, i);
        }
       
        return baos.toByteArray();
    }
    catch(Exception e)
    {
        ;
    }
    finally
    {
        if (fis != null)
        {
            try
            {
                fis.close();
            }
            catch (IOException ioe)
            {
                ;
            }
        }
       
        if (baos != null)
        {
            try
            {
                baos.close();
            }
            catch(IOException ioe)
            {
                ;
            }
        }
    }
   
    return null;
   
  } // > private byte[] loadClassData(String classname)


  public Class findClass(String name)
    throws ClassNotFoundException
  {
   
    byte[] data = loadClassData(name);
    if (data != null)
    {
        return cl = defineClass(name, data, 0, data.length);
    }
   
    throw new ClassNotFoundException(name);
   
  } // > public Class findClass(String name)

}


Jeg har rippet en masse fra ovenstaaende, men den burde virke (bemaerk, at det skal koere paa JDK1.2 og derfor ikke har brug for de forskellige loadClass() implementeringer, som det var tilfaeldet i < JDK1.2).

Jeg proever, at loade en given '.clazz' fil fra min lokale disk. Naar jeg har laest den kalder jeg 'defineClass', der parser klasser og goer den tilgaengelig.

I en anden klasse kalder jeg saa min klasse-loader, cacher allerede loadede klasser, etc.

Naa, men det var nok snak, nu er mit spoergsmaal saa:

  * Skal man absolut loade alle klasser i en pakke for
    at faa en ClassLoader til at kende til package
    variabler?

Hvis der er nogen der har noget sample kode til JDK1.2 klasseloading, saa vil jeg meget gerne have det. Det er meningen, at mit program skal kunne:

    1. Loade en helt ny (ukendt for JVM) klasse
    2. Reloade en eksisterende klasse
    3. Genbruge en eksisterende klasse, hvis den
      ikke har vaeret modificeret (det styrer
      jeg ved at fyre en traad af, der hvert X.
      minut tjekker alle timestamp paa filer
      hvor jeg har cached klasser; findes filen
      modificeret, sletter jeg den fra cachen
      og den vil saa blive reloadet ved naeste
      request paa den.


Jeg haaber, der er nogle der kan hjaelpe med dette problem, for jeg har virkelig brugt lang tid paa det efterhaanden og jeg synes ikke rigtig, jeg kommer meget videre med det.


Paa forhaand tak..
Avatar billede lbhansen Nybegynder
22. juli 2000 - 16:06 #1
JDK har en udemærket cache struktur, så hvorfor ikke bruge.
Class klasse = Class.forName(\"filnavn\");
MyClass mc = ( MyClass )klasse.newInstance();
Avatar billede theill Nybegynder
22. juli 2000 - 16:13 #2
Fordi en klasse kaldt med \'Class.forName\' bliver loadet via SystemClassLoaderen og det goer, at jeg ikke kan faa lov til at reloade den klasse :o(

Problemet er netop, at det skal vaere muligt at loade en klasse, der er blevet aendret paa runtime.
Avatar billede lbhansen Nybegynder
22. juli 2000 - 19:33 #3
Har du prøvet at loade klasse A + klasse B. Hvis du laver en instans af klassen B, vil denne også blive loaded automatisk af JVM, og så mangler du alligevel den funktionalitet, som du vil få ved at implementere din egen classloader. Udover det vil det så ikke være pænere at lave variablen private, og lave en tilgangsmetode til den fra klasse B. NB! hvorfor dette krav med at kunne se om en klasse er modificeret eller ej.
Avatar billede theill Nybegynder
22. juli 2000 - 19:44 #4
Nej, det er jo derfor, jeg har en .clazz extension paa mine class-filer, jeg ikke vil have, skal loades _automatisk_ af JVM\'en.
Avatar billede lbhansen Nybegynder
22. juli 2000 - 19:56 #5
Så er det jo et minimumskrav at du også loader klasse B, for JVMen finder den ikke
Avatar billede theill Nybegynder
22. juli 2000 - 21:51 #6
Ja, det er sandt. Jeg loader skam ogsaa begge klasser selv, men mit problem er, at jeg gerne vil kunne reloade klasse A *uden* at reloade klasse B (hvis den ikke har aendret sig).

Hvis jeg reloader klasse A, mister den \'forbindelsen\' til klasse B og det er kun muligt for mig, at faa klasse A til at kende package protectede variabler i klasse B, hvis jeg *samtidigt* loader klasse B -- det er jeg imidlertigt ikke interesseret i.
Avatar billede lbhansen Nybegynder
23. juli 2000 - 10:48 #7
Jeg har desværre ingen idé til løsningen, men kommer der en dag, hvor du finder svaret, vil jeg da være meget interesseret i løsningen.

med venlig hilsen lars
lars.hansen@framfab.dk
Avatar billede theill Nybegynder
23. juli 2000 - 12:38 #8
Okay, jeg skal nok sende dig en mail, hvis jeg finder en god loesning paa problemet.

Alligevel tak for dit forsoeg.
Avatar billede kobojt Nybegynder
22. august 2000 - 12:10 #9
Det svarer selvfølgelig ikke dit spørgsmål, men har du overvejet at poste dette opslag hos java.sun.com ?
Eksperten er et fedt site, men på java området er sun bedre.

Kobojt
Avatar billede theill Nybegynder
12. oktober 2000 - 14:07 #10
Uha -- jeg proevede dette inden jeg postede til eksperten, men jeg fik intet svar. Jeg proevede ogsaa diverse newsgroups uden resultat :-(
Avatar billede lbhansen Nybegynder
12. oktober 2000 - 20:14 #11
Jeg har siddet for nylig og implementeret det. Min forklaring er at, JVMen kan kun se at klasser relaterer sammen hvis de kommer fra den samme classloader. De kan altså ikke dele variable på tværs af classloader. NB! Hvis du vil have en rigtig god classloader, så prøv at kigge på den der er implementeret i ApacheJServ!
Avatar billede theill Nybegynder
12. oktober 2000 - 22:07 #12
Jeg har givet dig pointene, selvom det ikke helt var det svar, jeg oenskede ;o)

Problemet er nemlig, at det faktisk *er* min loader, der loader begge klasserne. Det er dog alligevel ikke muligt at reloade en klasse der allerede er loadet en gang (uden at lave en ny classeloader -> reload alle klasser). Jeg ville have en \'RELOAD this specific class using that classloader\' metode ...

Jeg har tjekket Tomcats ClassLoader ud ... men ikke JServ, saa den kigger jeg paa nu -- tak for hjaelpen lbhansen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester