2010-12-13 4 views
2

Ich verteile Code an meine Erstsemester-Programmierer, die ein ZIP-Archiv ihrer Hausaufgaben in Eclipse erstellen. Für die Zuweisung N erstelle ich eine Hauptmethode in der Klasse hwN.Submitter, die eine Bibliotheksmethode foo.Submit.zip() aufruft. Ich verteile das Hauptprogramm und die Bibliothek in einer ausführbaren JAR. foo ist ziemlich stabil, aber gelegentlich ändert es sich. Die Bibliothek ist in der JAR-Datei jeder Hausaufgabe enthalten.Superseding-Klassen aus JARs Früher in Classpath

Angenommen, ein Student fügt die Eclipse-Build-Datei von hw1 zu Eclipse hinzu. Ich ändere dann die API von foo.Submit für hw2 und verteile seine JAR. Da hw2.submitter später im Build-Pfad hinzugefügt wird, wird foo.submit aus der hw1-JAR geladen, die die Methode seit der Änderung der API nicht enthält.

Nun habe ich anscheinend ein paar Möglichkeiten: A) Sag meinen Schülern, dass sie alte JARs löschen sollen, B) Sag meinen Studenten, den Build-Pfad neu zu ordnen, oder C) schreibe meinen eigenen Klassenlader. Ich mag A nicht, weil es für sie nützlich ist, die JARs auf alten Hausaufgaben zu betreiben. Ich mag B nicht, weil sie Programmierer des ersten Semesters sind. Und ich kann C nicht zur Arbeit bringen.

Ich habe mit URLClassLoader herum gespielt, aber der Elternklassenlader findet zuerst die Klassen in den alten JARs. Wie kann ich diese alten JARs ersetzen oder den übergeordneten Klassenlader außer Kraft setzen?

+1

Ist es wirklich notwendig, ihnen Code zum Einreichen einer Zip-Datei zur Verfügung zu stellen? Sie sind in einer Programmierklasse. Sie sollten in der Lage sein, eine Zip-Datei zu erstellen und sie dann irgendwo auf einen Server zu stellen (oder sie über eine Kurswebseite hochzuladen). –

+0

Ich glaube, Sie haben den ersten Semesterteil verpasst. Ich kann sie sicherlich bitten, dies zu tun, aber sie werden Dateien weglassen, Verzeichnisse einschließen, rar oder 7zip usw. Der Übermittler tut auch mehr als nur komprimieren. – kaerimasu

+0

Der konventionelle Weg, um solche Konflikte zu lösen (es ist eine hässliche Konvention, aber trotzdem ...) ist, das Paket der Bibliotheksklasse zu ändern. – CurtainDog

Antwort

2

Okay, etwas mehr herum stochern, konnte ich eine Lösung finden. Dies ist der Klassenlader ich kam mit:

package speccheck; 

import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLClassLoader; 

/** 
* Create a class loader which favors speccheck.* classes from the JAR 
* associated with the homework. 
*/ 
public class LatestSpecCheckClassLoader extends URLClassLoader { 
    /** 
    * Create a loader which checks $(pwd)/bin/speccheck_TAG_DO_NOT_SUBMIT.jar 
    * first for speccheck.* classes 
    * 
    * @param tag 
    * Homework tag, like "hw4" or "pre2". 
    * @throws MalformedURLException 
    */ 
    public LatestSpecCheckClassLoader(String tag) throws MalformedURLException { 
    super(new URL[]{new URL("file://" + System.getProperty("user.dir") + "/bin/" + tag + "/speccheck_" + tag + "_DO_NOT_SUBMIT.jar")}); 
    } 

    @Override 
    public Class<?> loadClass(String name) throws ClassNotFoundException { 
    // Check for cached. 
    Class<?> loadedClass = findLoadedClass(name); 
    if (loadedClass != null) { 
     return loadedClass; 
    } 

    // If the class is in the speccheck package, do not delegate to parent 
    // loader. Check in the URLs registered with this loader instead. 
    try { 
     if (name.startsWith("speccheck.")) { 
     loadedClass = findClass(name); 
     } 
    } catch (ClassNotFoundException e) { 
    } 

    // If still not found, then let's defer. 
    if (loadedClass == null) { 
     return super.loadClass(name); 
    } 

    return loadedClass; 
    } 
} 

Hut ab vor Alex Miller für ein funktionierendes Beispiel.

Verwandte Themen