# Alle geladenen jars ermitteln (mit WebStart)



## MichaelW (2. September 2008)

Hallo zusammen,
ich habe folgendes Problem.
Ein Klasse ermittelt versch. Infos über alle Jar-Files in meinem Projekt. Dieses Vorgehen funtkioniert soweit als Desktop-App., weil man über *System.getProperty("java.class.path");* den gesamten Classpath scannen und jede einzelne Jar-Datei einlesen kann.
Nun möchte ich aber die ganze App. über WebStart anbieten. Der Aufruf *System.getProperty("java.class.path");* offenbart mit leider nicht alle jars die im jnlp File angegeben sind (nur die deploy.jar).
Könntet ihr mir bitte weiterhelfen wie ich an die geladenen jar Dateien über WebStart rankommen?
Hatte jemand schon das selbe Problem?

Schonmal Danke für eure Antworten.

Grüße
Micha


----------



## MichaelW (2. September 2008)

Nochmal etwas anders erklärt:
Ich brauche eine einfach Liste von allen Ressourcen (jars) die mit WebStart geladen worden sind. (ähnlich dem Tool "javaws -viewer")
Die Liste sollte den vollen Pfad zu den jars enthalten, denn wie oben beschrieben möchte ich die jars einlesen (mit der Klasse JarFile).

Danke & Gruß
miwur


----------



## Thomas Darimont (2. September 2008)

Hallo,

eine Möglichkeit "alle" Jars die in einer Java Anwendung verwendet werden aufzulisten wäre über Instrumentation möglich:

Siehe hierzu:
http://www.tutorials.de/forum/java/...entierten-klassen-und-durch-osgi-bundles.html

Bzw:

```
/**
package de.tutorials;

import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author Tom
 * 
 */
public class ListAllLoadedJars {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        
        //hier laden wir eine Klasse über einen URLClassLoader dynamisch um zu zeigen,
       // das man mit dieser Methode auch jars findet die nicht beim Start der      //Anwendung    im Classpath waren
        URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:///D:/eclipse/3.4-sdk/eclipse/configuration/org.eclipse.osgi/bundles/173/1/.cp/lib/scala-library.jar")});
        System.out.println(classLoader.loadClass("scala.ScalaObject"));
        
        Set<URI> uris = new TreeSet<URI>();
        for (Class<?> clazz : InstrumentationProvider.getInstrumentation()
                .getAllLoadedClasses()) {
            CodeSource codeSource = clazz.getProtectionDomain().getCodeSource();
            if (null != codeSource) {
                uris.add(codeSource.getLocation().toURI());
            }
        }
        System.out.println(uris);
    }
}
```

Ausgabe:

```
C:\>java -javaagent:listJars.jar -cp . de.tutorials.ListAllLoadedJars
interface scala.ScalaObject
[file:/C:/listJars.jar, file:/D:/eclipse/3.4-sdk/eclipse/configuration/org.eclipse.osgi/bundles/173/1/.cp/lib/scala-library.jar]
```

Bei Klassen die vom jars geladen werden die im Bootclasspath -> 

```
(System.out.println(ManagementFactory.getRuntimeMXBean().getBootClassPath());)
```
liegen:

```
C:\Program Files\Java\jdk1.6.0_10\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_10\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_10\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.6.0_10\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_10\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_10\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_10\jre\classes
```
ist die Code source null.

Für alle anderen Klassen die "nackt" oder in Jars verpackt im normalen Classpath liegen

```
System.out.println(ManagementFactory.getRuntimeMXBean().getClassPath());
```
Solltest du eine entsprechende CodeSource sehen.

Gruß Tom


----------



## MichaelW (3. September 2008)

Erstmal Danke für den Tipp.

Das funktioniert nun bei mir wenn ich die App. über die command line starte.
Wie mache ich das ganze dann über WebStart, also wie rufe ich den agent auf?

Gibt es noch eine andere Möglichkeit?
Kommt man eig. irgendwie an die jnlp Datei direkt ran? Das man diese im Notfall selbst auslesen kann?
Oder gibts evlt. was in der JNLP API?

Danke & Grüße
Michael


----------



## Thomas Darimont (3. September 2008)

Hallo,

zur Laufzeit liegt das javaws.jar im Classpath. Dort findest du eine API zur Interaktion mit der Webstart Umgebung. 
So kannst du dir alle referenzierten Jar Ressources anzeigen lassen:

```
import com.sun.javaws.jnl.JARDesc;
import com.sun.jnlp.JNLPClassLoaderUtil;

StringBuilder locations = new StringBuilder();
		for(JARDesc jarDesc : JNLPClassLoaderUtil.getInstance().getLaunchDesc().getResources().getLocalJarDescs()){
			locations.append(jarDesc.getLocation().toString()+"\n");
		}
```
ist aber Sun interne API .... eine andere Möglichkeit wäre das JNLP File selbst zu Parsen...

Gruß Tom


----------



## MichaelW (4. September 2008)

Hi Tom,

der Ansatz hört sich vielversprechend an. Danke...

Leider scheitert es bei mir, weil ich die Klasse com.sun.jnlp.JNLPClassLoaderUtil nicht finden kann. Lediglich die Klasse com.sun.jnlp.JNLPClassLoader.
Brauche ich noch zusätzlich eine lib?

//Edit:
Ok, es klappt auch mit der Klasse JNLPClassLoader.
Mein Vorgehen ist nun so:
Ich hol mir alle Jars mit der oben beschriebenen Methode, cache sie mir selbst in mein deployment-cache-verzeichnis und öffne die jars dann mit JarFile.
Das speichern der Jars erzeugt schon eine Menge overhead... Sind ungeährt so 100 Jar files...
Kommt man denn nicht irgendwie an die schon gecachten jars dran? WebStart lädt beim Start der App. sich ja schon alles in den Cache.

Gruß
Micha


----------



## MichaelW (5. September 2008)

So, ich hab noch einen ähnlichen Ansatz gefunden (auf: http://lists.trolltech.com/qt-jambi-interest/2007-06/thread00003-0.html)


```
for (JARDesc jd : jarDescs) {

      URL location = jd.getLocation();
      String version = jd.getVersion();

      try {
        DiskCacheEntry dce = DownloadProtocol.getResource(location, version,
            DownloadProtocol.JAR_DOWNLOAD, true, null);
        this.classpath.add(dce.getFile().getAbsolutePath());

      } catch (JNLPException e) {
      }
}
```

Leider bekomme ich beim Ausführen mit WebStart folgende Exception:
java.lang.NoClassDefFoundError: com/sun/javaws/cache/DownloadProtocol

In Eclipse (unter Java 1.5) wird aber alles ordnungsgemäß gefunden...

Hatte jemand schonmal ein solches Problem?

Danke & Gruß
Micha


----------



## MichaelW (12. September 2008)

Hi zusammen,

erstmal vorweg... "Kann mir denn keiner helfen?"

Gibt es eig. keine JavaDoc zu dem Paket com.sun.javaws? Ich find überhaupt nix...

Gruß
Micha


----------



## takidoso (15. September 2008)

Hi,
ein java.lang.NoClassDefFoundError
klingt für mich so, als wäre der Klassenpfad nicht auf diese Klasse eingestellt.
schau doch mal Deine Umgebung an, ob Du da nicht den Klassenpfad noch erweitern musst.


----------

