Announcement

Collapse
No announcement yet.

JAR findet Klassen nicht

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • JAR findet Klassen nicht

    Hallo liebe Entwickler,

    folgender Sachverhalt, welcher droht mich in den Wahnsinn zu treiben.
    Ich habe ein Tool entwickelt, welches bei Programmstart dynamisch Algorithmen einliest.
    Dabei suche ich in einem gewissen Package "de.kuebelkasten.routing.core.algorithms", was unter Eclipse auch wunderbar funktioniert.

    Nun soll man aber, um das Programm ausführen zu können, kein Eclipse nutzen. Schon alleine weil der Quellcode nicht öffentlich sein soll

    Lasse ich mir nun eine ausführbare jar erstellen, so findet er eben dieses Package nicht mehr.

    Vielleicht seh ich den Fehler auch selber gerade nicht.

    Hier mal noch etwas Code für besseres Verständnis:

    Code:
    // alle unterordner für algorithmen finden und anschliessend durchsuchen
    String mainAlgorithmResource = "/de/kuebelkasten/routing/core/algorithms/"; // hier müssen alle Algorithmen liegen
    final AlgorithmSet installedAlgorithms = new AlgorithmSet(); // hier werden alle Algorithmen abgelegt
    		
    // wir suchen ausgehend von unserem aktuellen Instanzstandpunkt
    final URL algorithmURL = getClass().getResource(mainAlgorithmResource);
    final File directory = new File(algorithmURL.getFile());
    		
    for (String dirContent : directory.list()) {
    // sind auf ein Verzeichnis gestossen, welches weiter durchsucht werden muss
    if (!dirContent.endsWith(".class")) {
    	final URL algorithmDirectoryURL = getClass().getResource(mainAlgorithmResource + dirContent);
    	final File algorithmDirectoryFile = new File(algorithmDirectoryURL.getFile());
    	for (String algorithmFile : algorithmDirectoryFile.list()) {
    //...
    }
    }
    }
    Ach ja. Der Fehler kommt in der ersten foreach-Schleife, bei directory.list() in Form einer NullpointerException, obwohl directory selber nicht null ist.

    Stacktrace sagt Folgendes:

    Code:
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
    Hoffe jemand hat eine schnelle Lösung parad. Danke schon mal
    Zuletzt editiert von kuebelkasten; 26.10.2010, 07:26.

  • #2
    Lasse ich mir nun eine ausführbare jar erstellen, so findet er eben dieses Package nicht mehr.
    Hast du mal ins JAR geschaut, was dort abgelegt wird? Des Weiteren kann auf Klassen in einem JAR nicht mit FILE zugegriffen werden, da diese nicht im Filesystem liegen
    Schon alleine weil der Quellcode nicht öffentlich sein soll
    Jedes class-File lässt sich durch decompilieren wieder in ein .java verwandeln.
    Christian

    Comment


    • #3
      Schon mal Danke für die schnelle Antwort.
      Vielleicht verhelf ich Dir ja noch zu Deinem 10.000 Post

      Hast du mal ins JAR geschaut, was dort abgelegt wird? Des Weiteren kann auf Klassen in einem JAR nicht mit FILE zugegriffen werden, da diese nicht im Filesystem liegen
      Wie meinst Du das, ins jar geschaut? Dort sind die Packages als Unterordner drin und eben auch die ganzen Klassen.
      Wie kann ich denn dann darauf zugreifen, wenn nicht über File?

      Comment


      • #4
        Das JAR ist eine ZIP-Datei.....

        Schau dir mal

        Class.forName

        an. Das Durchsuchen wirst du mit den ZIP-klassen machen müssen

        Allerdings ist mir unklar, warum du alle Klassen von Hand laden willst.....
        Christian

        Comment


        • #5
          Das JAR ist eine ZIP-Datei.....
          Das war mir schon klar, ich wusste nur nicht, was Du mit reinschauen gemeint hast

          Class.forName kann ich nicht anwenden, da ich vorher nicht weiß wie die Klassen genau heißen.

          Allerdings ist mir unklar, warum du alle Klassen von Hand laden willst.....
          Das Programm soll Plugin-basiert sein. Quasi soll man unabhängig vom Kern weitere Algorithmen entwickeln und einfach in dieses Package legen können und fertig.

          Aber, wenn Du schon so fragst, gibt es denn eine bessere, sinnvollere oder elgeantere Lösung?

          Comment


          • #6
            Das Programm soll Plugin-basiert sein. Quasi soll man unabhängig vom Kern weitere Algorithmen entwickeln und einfach in dieses Package legen können und fertig.
            Naja, aber um das nachher zu nutzen muss das Programm ja compiliert und die neuen Klassen in das JAR gepackt werden....

            Unabhängig wäre es ja nur, wenn du dein JAR hättest und die zusätzlichen Klassen außerhalb des JAR liegen und dann eingebunden werden.
            Christian

            Comment


            • #7
              Naja, aber um das nachher zu nutzen muss das Programm ja compiliert und die neuen Klassen in das JAR gepackt werden....

              Unabhängig wäre es ja nur, wenn du dein JAR hättest und die zusätzlichen Klassen außerhalb des JAR liegen und dann eingebunden werden.
              Demnach müsste man ja extra noch eine Anwendung schreiben, in welcher man nur die Algorithmen entwickeln kann. Das ist aber nicht mehr mein Ziel/Aufgabe.
              Ich möchte eben am Ende ein einzige jar haben, welche aber die ollen Algorithmen findet -.-

              Comment


              • #8
                ServiceLoader

                Es gibt in Java einen Mechanismus, um services automatisch zu laden. Den ServiceLoader(http://download.oracle.com/javase/6/...iceLoader.html)
                Vielleicht kannst Du damit was anfangen.
                http://www.winfonet.eu

                Comment


                • #9
                  Ich habs jetzt so geregelt, dass ich meine Algorithmen in ein eigenes jar packe und dieses dann in die ausführbare jar mit rein tu.

                  Aber wie kann ich darauf zugreifen, wenn das jar im Root des anderen jar liegt?

                  Ich muss es immer erst in den Unterordner kopieren, in welchem auch die Klasse ist, welche das jar auslesen soll. Es soll aber aus dem Wurzelverzeichnis gelesen werden.
                  Muss ich da irgendwas in der Manifest-Datei erweitern/ändern, dass er das da auch sucht?

                  Hab auch schon versucht, die jar (mit den Algorithmen) im Eclipse als Referenced Library anzugeben. Der Effekt bleibt aber der Gleiche. Er findet das jar nicht im Rootverzeichnis...

                  Noch jemand eine Idee?

                  Edit: Habs nun nochmal so gemacht, dass ich es als Referenced Library macht. Jetzt findet der zwar die jar, wirft mir aber eine ClassCastException und ich hab - mal wieder - keine Ahnung wieso
                  Zuletzt editiert von kuebelkasten; 28.10.2010, 16:54.

                  Comment


                  • #10
                    Muss ich da irgendwas in der Manifest-Datei erweitern/ändern, dass er das da auch sucht?
                    Beispiel für zwei JARs im Verzeichnis lib:

                    Class-Path: lib/jl1.0.1.jar lib/mail.jar
                    Christian

                    Comment


                    • #11
                      ClassCast Exception

                      ClassCastExceptions fliegen dann, wenn Du im Code versuchst, einen Typen in einen anderen Typen umzuwandeln, der nicht kompatibel ist. Das passiert i.d.R bei einem sog. Downcast. Also, wenn Du als Referenz eine Oberklasse zu fassen hast und diese Referenz in eine Unterklasse konvertieren willst, die nicht kompatibel ist. Folgender (ziemlich unnütze) Code zur Verdeutlichung:
                      Code:
                      /* Instanz vom Typ Integer in einer Referenzvariablen vom Typ Object gespeichert.
                      Object ist eine Oberklasse von Integer. Geht also gut. */
                      Object myObj = Integer.valueOf(1);
                      
                      /* Legaler downcast einer Referenz vom Typ Object zu einer Unterklasse */
                      Integer myInt = (Integer) myObj; 
                      
                      /* Versuch eine Referenz auf Object (in Wirklichkeit ein Integer) zu String
                      downzucasten. Verboten, ClassCastException fliegt */
                      String illegal = (String) myObj;
                      Ohne Deine genaue Klassenstruktur zu kennen, würde ich mal annehmen, dass Du alle Deine Algorithmen von einer gemeinsamen Basisklasse oder einem gemeinsamen Interface ableitest und dann beim downcast zu einem falschen Algorithmus castest, vielleicht so:
                      Code:
                      /* BasisAlgorithmus ist die gemeinsame Oberklasse. */
                      BasisAlgorithmus algo = new SinusAlgorithmus();
                      
                      /* Illegaler Cast, ClassCastException fliegt. */
                      CosinusAlgorithmus cosinusAlgo = (CosinusAlgorithmus) algo;
                      Gruß ngomo
                      http://www.winfonet.eu

                      Comment


                      • #12
                        Also, ich machs jetzt anders...

                        Das mit dem casten kann nicht sein. Alle Klassen sind von AbstractAlgorithm abgeleitet.

                        Ich will es nun folgendermaßen machen, komme da aber mal wieder nicht weiter.
                        Ich will das Programm als ausführbare jar haben. In dieser jar hab ich ein Package ... .algorithms. ...

                        In diesem Package hat jeder Algorithmus sein eigenes Unterpackage

                        ... .algorithms.aodv. ... ... . algorithms.dsdv. ... und so weiter.

                        In jedem einzelnen Unterpackage muss eine Klasse vorhanden sein, welche von AbstractAlgorithm erbt.

                        Unter Eclipse durchsuche ich einfach alle Unterordner von algorithms. Wenn ich auf eine Klasse stosse, welche eine abgeleitete Klasse von AbstractAlgorithm ist, dann erstelle ich eine neue Instanz mit newInstance().

                        Unter eclipse klappt das alles auch wunderbar, weil es ja auf Dateiebene geht, was aber im jar so nicht möglich ist.

                        Packe ich die Algorithmen in algorithmen jar und lege die mit ins runnable jar, findet der Sausack das nicht.

                        So suche ich danach:

                        PHP Code:
                                    String codeSource this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
                                    
                        JarFile algorithmJar = new JarFile(codeSource "algorithms.jar"); // als Jar laden wir das 
                        java.io.FileNotFoundException: .\algorithms.jar (Das System kann die angegebene Datei nicht finden).

                        Wie find ich nun das jar im jar bzw. kann ich im jar einfach die Unterordner durchsuchen?

                        In der MANIFEST.MF steht unter Rscr-Class-Path: ./ algorithms.jar. Daran kanns also nicht scheitern...

                        Mit
                        PHP Code:
                        Class.forName(... .algorithms. ... AODVAlgorithm); 
                        kann ich die Klasse laden was auch schön und gut ist. Leider weiß ich nicht wie die Algorithmen heißen. Also, ich weiß das schon, aber das Programm soll das dynamisch machen und den Namen anhand der Paket-Struktur basteln.

                        Ich hab schon stundenlang gesucht und nichts gefunden. Ich verzweifel noch und seh einfach nicht den Fehler.

                        Hoffentlich hat noch jemand eine gute Idee für mich.

                        // EDIT
                        Ich hab soeben rausgefunden, dass der nicht im jar (also dem ausführbaren jar) sucht, sondern eine Ebene höher im Dateisystem.
                        Exportiere ich das runnable jar auf meinen Desktop namens Routing.jar und suche dann nach der algorithms.jar, so sucht der unter C:\Users\kuebelkasten\Desktop\algorithms.jar und nicht in Routing.jar.

                        Ich weiß nicht mehr weiter und zünd' hier bald alles an
                        Zuletzt editiert von kuebelkasten; 01.11.2010, 23:05.

                        Comment


                        • #13
                          Das Durchsuchen wirst du mit den ZIP-klassen machen müssen
                          - ermitteln wo das JAR läuft
                          - mit ZIP das JAR öffnen
                          - durchsuchen
                          - ClassForName...

                          Wie gesagt, ist dein Vorgehen wenig sinnvoll, da du bei weiteren neuen Algo-Klassen immer das JAR neu bauen musst. Insowern weisst du dann auch die Klassennamen
                          Zuletzt editiert von Christian Marquardt; 02.11.2010, 07:46.
                          Christian

                          Comment

                          Working...
                          X