Toon posts:

[Java] LinkageError

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met een soort van plugin systeem in Java. Daarvoor wil ik alle classes uit een bepaalde package of directory dynamisch aan kunnen maken, maar ik weet niet welke classes er in die package of directory staan. Ik heb eerst gekeken of ik alle classes uit een package op kon vragen met reflection, maar om een of andere rede krijg ik dat niet voor elkaar. In de documentatie van de klasse java.lang.Package staat nergens een methode om de klassen uit die package op te vragen.
Daarna heb ik geprobeerd om alle .class bestanden uit een directory te laden, en de naam van die klassen als String terug te geven. Dit lukt aardig, behalve in één geval.

Stel, je hebt klasse a en b. Klasse a extends b, en ze staan beide in de directory die geladen moet worden. Deze directory staat ook in het classpath.
Ik vraag de lijst van alle bestanden op, en krijg de volgende array terug:
File[] files = {a.class, b.class};
(nou ja, ik hoop dat jullie snappen wat ik bedoel)
Ik doorloop het array, en laad eerst klasse a in. Als ik daarna klasse b in wil laden, krijg ik de volgende foutmelding:
java.lang.LinkageError: duplicate class definition: b

De code die het laden van de bestanden regelt:
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
public String[] getClasses(){
    if (classes != null){
      return classes;
    }
    File[] files = pluginDirectory.listFiles();
    StringVector classVector = new StringVector();
    for (int i = 0; i < files.length; i++){
      File file = files[i];
      String fileName = file.getAbsolutePath();
      if (fileName.toLowerCase().endsWith(".class")){
        byte[] bytes = new byte[(int)file.length()];
        try {
          FileInputStream fis = new FileInputStream(file);
          fis.read(bytes);
          Class newClass = defineClass(null, bytes, 0, bytes.length);
          classVector.add(newClass.getName());
        }
        catch (IOException ex) {
        }
        catch (ClassFormatError ex) {
        }
      }
    }
    classes = classVector.toStringArray();
    return classes;
  }


Ik kan die foutmelding wel afvangen, en doorgaan met de volgende, maar dan mis ik dus die klasse in de lijst.
Een kant en klare oplossing is niet nodig (mag wel overigens :)), maar een hint om verder te komen is meer dan welkom.

  • SWfreak
  • Registratie: Juni 2001
  • Niet online
Het lijkt erop dat als "a extends b", dat dan b automatisch geladen wordt als a geladen wordt. Dit is op zich logisch. Het zou fijn zijn als je de naam van de klasse die je wil laden kon achterhalen, dan kon je checken of een klasse met die naam reeds geladen was. Dit zal waarschijnlijk wel te achterhalen zijn dmv de filenaam. Je kunt dan dmv java.lang.ClassLoader.findClass() check of ie er al is. Voorkomt dit het probleem?

Verwijderd

Topicstarter
Probleem opgelost.
De naam van het bestand is inderdaad te gebruiken om te achterhalen of een klasse geladen moet worden of niet, maar dan op een iets andere manier. De naam van het bestand is namelijk de naam van de klasse met ".class" erachter, maar de naam van het package waar het .class bestand in zit, is niet te achterhalen. Aangezien toch alle .class bestanden uit die directory geladen moeten worden, moet er gekeken worden of er een bestand in die directory staan dat overeen komt met de naam van de klasse. Stukje code wat erbij hoort:
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
  public Class loadClass(String name) throws ClassNotFoundException{
    File[] files = pluginDirectory.listFiles();
    for (int i = 0; i < files.length; i++){
      if (!skipFile(files[i])){
        String fileName = files[i].getName();
        if ( (name + ".class").endsWith(fileName)) {
          skipFiles.add(files[i].getAbsolutePath());
          try {
            FileInputStream fis = new FileInputStream(files[i]);
            byte[] bytes = new byte[ (int) files[i].length()];
            fis.read(bytes);
            Class returnValue = defineClass(null, bytes, 0, bytes.length);
            classes.add(returnValue.getName());
            return returnValue;
          }
          catch (ClassFormatError ex) {
          }
          catch (IOException ex) {
          }
          catch (LinkageError ex) {}
        }
      }
    }
    return super.loadClass(name);
  }

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Uhm wat ga je doen bij anonymous inner classes (bijv actionlisteners?)

  • SWfreak
  • Registratie: Juni 2001
  • Niet online
Glimi schreef op 24 June 2003 @ 12:01:
Uhm wat ga je doen bij anonymous inner classes (bijv actionlisteners?)
Hehe, dies wel grappig ja. Maar wat ik me nu bedenk is dat als een class/file geladen wordt en dan ook kennelijk meteen dependent classes geladen wordt, dan is het helemaal niet erg dat een linkage error optreed. Deze klasse is immers toch al geladen. Dus Java doet al een heleboel voor je :)