# keine Bilder in .jar-Datei (java)



## Moucho (29. Sep 2011)

Hallo zusammen, 

Ich habe ein kleines Problem mit den Bildern beim erzeugen einer Jar-Datei.
Ich habe ein Projekt (kleines Spiel) in Java mit Eclipse geschrieben.

Das Spiel ist soweit fertig und (von Eclipse aus) funktioniert alles einwandfrei.

Jetzt habe ich eine Jar-Datei erzeugt. Sie lässt sich auch starten, alles funktioniert, bis auf, dass keine Bilder angezeigt werden.
Die Bilder  sind im Ordner „Skin“, der im Ordner „Images“ ist und dieser wiederum im Ordner „resourcen“, wobei der Ordner „resourcen“ im Package Explorer in Eclipse im Ordner „src“ ist.

In sämtlichen Forum lese ich, dass ich getResource() zum zugreifen auf die Bilder verwenden muss, bei mir sieht es also in etwa jetzt so aus:


```
java.net.URL url = <Class-name>.class.getResource("resourcen/Images/Skin/bildname.png");
bildtitel = new ImageIcon(url);
```

Hier bekomme ich jedoch immer den folgenden Fehler:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at […].init([…].java:131)

Caused by: java.lang.NullPointerException
	at javax.swing.ImageIcon.<init>(Unknown Source)

Die Bilder sind alle bei mir static, damit ich über <Klassenname>.<Bildname> die Bilder bekomme (ohne get-set-methoden). und das ist gewollt, da ich die Klasse als "Konstanten-Klasse" verwenden möchte, da die Bilder in mehreren Klassen "abgefragt/ drauf zugegriffen" werden.
Also kann ich auch schlecht die Methode getResource() über getClass() aufrufen.
und damit ich die Bilder nicht jedes Mal neu in den jeweiligen Klassen deklarieren muss, halt eben diese "Konstanten-Klasse". Zu dem kann man im Spiel den Skin wechseln, und das kann ich mit einer einzigen Methode in dieser "Konstanten-Klasse" erreichen.

Gibt es denn eine Lösung die Bilder in der Jar-Datei anzuzeigen ohne dass ich auf das "static" verzichten muss?

Vielen Dank im Voraus


----------



## Michael... (29. Sep 2011)

In dem jar-File gibt es entsprechende Enitäten wie 
	
	
	
	





```
resourcen/Images/Skin/bildname.png
```
?
Problier es mal mit einem Slash vor resourcen:

```
<Class-name>.class.getResource("/resourcen/Images/Skin/bildname.png");
```
da es ja auch davon abhängt, wo die Klasse im Package aufgehängt ist.


----------



## Moucho (29. Sep 2011)

Danke für deine Antwort,

der Fehler kommt aber beim kompilieren, also wenn ich das programm unter eclipse ausführen möchte, da hat es ja noch nichts mit der JAR zu tun.

Ich hatte immer diese Variante (die beim ausführen von Eclipse funktioniert):


```
public static ImageIcon bildname;
[...]
public static void setSkin(){
bildname = new ImageIcon("resourcen/Images/Skin/bildname.png");
}
```

Bei dieser Variante werden die Bilder (von der JAR-Datei gestartet) aber nicht angezeigt

und wenn ich das mit dieser Variante mache

```
<Class-name>.class.getResource("/resourcen/Images/Skin/bildname.png");
```

(mit oder ohne / am Anfang des Pfades) bekomme ich die Exceptions (s.o.)


----------



## theuserbl (29. Sep 2011)

Moucho5 hat gesagt.:


> Danke für deine Antwort,
> 
> der Fehler kommt aber beim kompilieren, also wenn ich das programm unter eclipse ausführen möchte, da hat es ja noch nichts mit der JAR zu tun.
> 
> ...



Also normalerweise kombiniert man beides:


```
public static ImageIcon bildname;
[...]
public static void setSkin(){
bildname = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
}
```

Edit: Nachtrag: _setSkin()_ sollte nicht static sein.

Edit2: _bildname_ sollte auch nicht static sein.

In statischen Methoden kann man getResource() nicht aufrufen. Daher solltest Du irgendwie Dein Programm umschreiben, so daß Du das Bild nicht aus einer statischen Methode draus liest.


```
public ImageIcon bildname;
[...]
public void setSkin(){
bildname = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
}
```


----------



## Moucho (29. Sep 2011)

```
public static ImageIcon bildname;
[...]
public static void setSkin(){
bildname = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
}
```

genau so hatte ich das auch gemeint, nur nicht mehr explizit hingeschrieben 



theuserbl hat gesagt.:


> Edit: Nachtrag: _setSkin()_ sollte nicht static sein.
> 
> Edit2: _bildname_ sollte auch nicht static sein.
> 
> In statischen Methoden kann man getResource() nicht aufrufen. Daher solltest Du irgendwie Dein Programm umschreiben, so daß Du das Bild nicht aus einer statischen Methode draus liest.




Aber genau das war ja auch meine Frage, ob es irgend ein Weg gibt, so dass ich das static beibehalten kann. 
Das Projekt ist halt ein bisschen größer, 29 Klassen insgesammt (ohne die eigenen Exceptions), und dementsprechend oft greif ich auf die Bilder zu. 

d.h. ich müsste extrem viel ändern... :-(
gibt es denn wirklich keinen anderen weg?


----------



## fix (29. Sep 2011)

Hast du mal versucht die Bilder über die Console einzufügen?

$ jar vuf slider.jar ordner/image.jpg

So gings bei mir dann immer.


----------



## L-ectron-X (29. Sep 2011)

Vielleicht hilft das: Grafikdateien laden und anzeigen ? Byte-Welt Wiki


----------



## theuserbl (29. Sep 2011)

Moucho5 hat gesagt.:


> Aber genau das war ja auch meine Frage, ob es irgend ein Weg gibt, so dass ich das static beibehalten kann.
> Das Projekt ist halt ein bisschen größer, 29 Klassen insgesammt (ohne die eigenen Exceptions), und dementsprechend oft greif ich auf die Bilder zu.
> 
> d.h. ich müsste extrem viel ändern... :-(
> gibt es denn wirklich keinen anderen weg?



Du darfst es dann nur nicht in setSkin() schreiben.
Jedes Programm beginnt mit der statischen Methode main(). Und somit kann man auch von jeder statischen Methode aus Objekte erstellen, dessen Methoden man nutzt.

Zum Beispiel folgende Klasse erstellen:


```
public class Res {
  private ImageIcon img;

  public Res() {
  }

  public ImageIcon getImg() {
    img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
  }
}
```

Dann kann man das Programm folgendermaßen abändern:


```
public static ImageIcon bildname;
[...]
public static void setSkin(){
  Res myRes = new Res();
  bildname = myRes().getImg();
}
```

Das ganze jetzt aber ohne gewähr, da ich es jetzt ohne zu testen geschrieben habe. Müßte aber eigentlich so funktionieren.

Grüße
theuserbl


----------



## Moucho (29. Sep 2011)

fix hat gesagt.:


> $ jar vuf slider.jar ordner/image.jpg



kannst du das genauer erklären? habe über die konsole noch nie bilder in JARs eingefügt...



			
				L-ectron-X hat gesagt.:
			
		

> Vielleicht hilft das: Grafikdateien laden und anzeigen ? Byte-Welt Wiki


die machen das auch nur mit getClass().getResource(), voraussetzung also, kein static ;(


----------



## Moucho (29. Sep 2011)

theuserbl hat gesagt.:


> Du darfst es dann nur nicht in setSkin() schreiben.
> Jedes Programm beginnt mit der statischen Methode main(). Und somit kann man auch von jeder statischen Methode aus Objekte erstellen, dessen Methoden man nutzt.
> 
> Zum Beispiel folgende Klasse erstellen:
> ...



danke, ich probiere des dann mal aus


----------



## fix (1. Okt 2011)

Wenn du Windows hast -> Start -> cmd -> ins Java Verzeichnis wechseln (wo deine javac.exe usw... liegt) und dort dann "$ jar vuf slider.jar ordner/image.jpg" eingeben und das Bild wird im jar eingefügt.


----------



## Moucho (2. Okt 2011)

fix hat gesagt.:


> Wenn du Windows hast -> Start -> cmd -> ins Java Verzeichnis wechseln (wo deine javac.exe usw... liegt) und dort dann "$ jar vuf slider.jar ordner/image.jpg" eingeben und das Bild wird im jar eingefügt.


"Der Befehl "$" ist entweder falsch geschrieben oder konnte nicht gefunden werden."

Und zur anderen Varianten:

```
public class Res {
  public ImageIcon img;
 
  public Res() {
  }
 
  public  void setSkin(){
   img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
  }

  public ImageIcon getImg() {
    return img;
  }
}
```


```
public class Constants {
[...]
public static ImageIcon bildname;
public static Res myRes = new Res();

static {	
		setSkin();
	}

public static void setSkin(){		
		myRes().setSkin();		
		bildname = myRes().getImg();
}
```

Dann kommt wieder folgender Fehler:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at [...]init(Frame.java:131)
	at [...].<init>(Frame.java:85)
	at [...].main(Main.java:13)
Caused by: java.lang.NullPointerException
	at javax.swing.ImageIcon.<init>(Unknown Source)
	at [...].myRes.setSkin(myRes.java:71)
	at [...].myRes.<init>(myRes.java:39)
	at [...].Constants.<clinit>(Constants.java:35)
	... 3 more


----------



## L-ectron-X (2. Okt 2011)

Moucho hat gesagt.:


> Exception in thread "main" java.lang.ExceptionInInitializerError
> at [...]init(Frame.java:131)
> at [...].<init>(Frame.java:85)
> at [...].main(Main.java:13)
> ...



Sagt doch schon ziemlich viel aus, oder? Dein Bild kann nicht gefunden werden. Damit enthält das ImageIcon-Objekt nichts (null) und es wird eine NullPointerException geworden.

Zum $:
Lass es einfach mal weg.


----------



## Moucho (2. Okt 2011)

Ok, es liegt in dieser Zeile:

```
img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
```

Denn ich habe vor und nach dieser Zeile eine Ausgabe geschrieben:


```
System.out.println("Test 1");
img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
System.out.println("Test 2");
```

Beim Ausführen:

*Test 1*
Exception in thread "main" java.lang.ExceptionInInitializerError
at [...]init(Frame.java:131)
at [...].<init>(Frame.java:85)
at [...].main(Main.java:13)
Caused by: java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(Unknown Source)
at [...].myRes.setSkin(myRes.java:71)
at [...].myRes.<init>(myRes.java:39)
at [...].Constants.<clinit>(Constants.java:35)
... 3 more 

Was ist denn da falsch, und warum bekomme ich ein "java.lang.ExceptionInInitializerError" -Exception ?
java.lang.ExceptionInInitializerError: Signalisiert, dass ein Fehler oder eine Exception innerhalb einer statischen Initialisierung aufgetreten ist. Als Folge davon wird eine Exception dieser Klasse ausgelöst und die Ausführung des Programms beendet.


----------



## theuserbl (2. Okt 2011)

Versuch es auch noch mal so:
	
	
	
	





```
System.out.println("Test 1");
img = new ImageIcon(this.getClass().getResource("resourcen/Images/Skin/bildname.png"));
System.out.println("Test 2");
```

Und achte dadrauf, daß der Pfad genau mit dem Namen existiert (Groß - und Kleinschreibung des Pfads beachten).
Setzte den Code in eine Java-Datei, die sich im Hauptpfad befindet (ohne package).

Grüße
theuserbl


----------



## theuserbl (2. Okt 2011)

Stimmt, den ersten Slash mußt Du weglassen.

Ich bin mir nicht sicher, aber ich glaube, daß wenn Du

```
img = new ImageIcon(this.getClass().getResource("resourcen/Images/Skin/bildname.png"));
```
von einer Klasse im Hauptpfad aufrufst, dann wird did Datei "resourcen/Images/Skin/bildname.png" gesucht.
Ist Deine Klasse in einem Unterpfad (z.B. "package myPackge"), dann wird in einem Unterpfad gesucht (z.B. "myPackage/resourcen/Images/Skin/bildname.png").

Will man von jedem beliebigen Klasse jeden beliebigen Unterpfads aus, das Bild laden können, gibt es noch folgende Möglichkeit:

```
img = new ImageIcon(this.getClass().getClassLoader().getResource("resourcen/Images/Skin/bildname.png"));
```

Bei letzterem wird alles hergenommen, was sich im Classpath an der Stelle befindet. Auf diese Weise kannst Du auch auf Bilder zugreifen, die Teil des JRE sind und nicht Teil deiner Jar-Datei.


----------



## Moucho (2. Okt 2011)

Das getClass().getResource() haut bei mir irgend wie nicht hin.
Folgendes liefert kein Fehler, alles geht, nur im Jar werden keine Bilder angezeigt:

```
img = new ImageIcon("resourcen/Images/Skin/bildname.png");
```

Und sobalt ich mit getClass().getResorce() arbeite, kommt wieder dieser java.lang.ExceptionInInitializerError und der java.lang.NullPointerException, wobei der Nullpointer halt in dieser Zeile auftritt

```
img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
```

Der Pfad ist richtig geschrieben.
habe jetzt alle Vorschläge ausprobiert, aber immer bekomme ich die Exceptions ;(

```
img = new ImageIcon(this.getClass().getResource("/resourcen/Images/Skin/bildname.png"));
```


```
img = new ImageIcon(this.getClass().getResource("resourcen/Images/Skin/bildname.png"));
```


```
img = new ImageIcon(this.getClass().getClassLoader().getResource("resourcen/Images/Skin/bildname.png"));
```


```
img = new ImageIcon(this.getClass().getClassLoader().getResource("/resourcen/Images/Skin/bildname.png"));
```


----------



## theuserbl (2. Okt 2011)

Ok, ich habe mir nun mal die Mühe gemacht, es selber zu testen.
Folgendes funktioniert bei mir:

Res.java:
	
	
	
	





```
import java.awt.*;
import javax.swing.*;

public class Res {
  public Icon img;
 
  public Res() {
  }
 
  public void setSkin(){
    img = new ImageIcon(this.getClass().getResource("resourcen/Images/Skin/bildname.png"));
  }
 
  public Icon getImg() {
    return img;
  }
}
```

Constants.java:
	
	
	
	





```
import javax.swing.*;

public class Constants {

  public static Icon bildname;
 
  static {    
    setSkin();
  }
 
  public static void setSkin(){
    Res myRes = new Res();
    myRes.setSkin();
    bildname = myRes.getImg();
  }
}
```

(Um es zu testen) Main.java:
	
	
	
	





```
import javax.swing.*;

public class Main {

  public static void main(String[] args) {
    JFrame f = new JFrame("Test Programm");
    JPanel p = new JPanel();
    JButton b = new JButton();
    b.setIcon(Constants.bildname);
    p.add(b);
    f.add(p);
    f.pack();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}
```

(Datei für den Mata-Datei Inhalt) meta.txt:
	
	
	
	





```
Main-Class: Main
```
Wichtig ist hierbei, daß die Datei meta.txt mit einer leeren  Zeile endet. Sie solltze somit mindestens zwei Zeilen haben, wobei in der ersten Zeile "Maiin-Class: Main" steht und die zweit Zeile leer ist.

Erstellen der Jar-Datei unter Linux/Unix:
	
	
	
	





```
jar cvfm Test.jar meta.txt Constants.class Res.class Main.class resourcen/Images/Skin/bildname.png
```

Unter Windows wäre es der Befehl:
	
	
	
	





```
jar cvfm Test.jar meta.txt Constants.class Res.class Main.class resourcen\Images\Skin\bildname.png
```

Ok, habe nun Icon statt ImageIcon am Ende verwendet. Hoffe das ist kein Problem für Dich.

Grüße
theuserbl


----------



## theuserbl (3. Okt 2011)

@Moucho:
Auch wenn es Dich nun etwas wundern wird, so muß ich Dir doch auch danken.

Das reine "static" als Methode oder was das auch immer ist, habe ich zwar schon öfters bei erzeugtem Code von Decompilern und so gesehen, aber mir nie richtig Gedankn drum gemacht. Vor allem, weil diese Methode gewöhnlich auch leer ist.

Und nun bin ich doch sehr überracht, daß ein
	
	
	
	





```
b.setIcon(Constants.bildname);
```
funktioniert, obwohl zuvor keine Zeile 
	
	
	
	





```
Constants.setSkin();
```
 geschriben wurde. Und alles liegt am 
	
	
	
	





```
static {    
  setSkin();
}
```
das ich zuvor garnicht richtig kannte.

Grüße
theuserbl


----------



## Moucho (3. Okt 2011)

Danke für deine Mühe!

Ich habe dein Code zu 100% so kopiert, die Unterordner alle im Projekt hinzugefügt, aber der Error bzw Exception kommt bei mir wieder, also hat das mit dem code doch an sich nichts zu tun, wenn es ja bei dir funktioniert ???:L

Ich versteh die (Java-)Welt nicht mehr ;(

Zeilen identisch mit deinem code:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at Main.main(Main.java:9)
Caused by: java.lang.NullPointerException
	at javax.swing.ImageIcon.<init>(Unknown Source)
	at Res.setSkin(Res.java:11)
	at Constants.setSkin(Constants.java:13)
	at Constants.<clinit>(Constants.java:8)
	... 1 more


----------



## Moucho (3. Okt 2011)

theuserbl hat gesagt.:


> @Moucho:
> Auch wenn es Dich nun etwas wundern wird, so muß ich Dir doch auch danken.
> 
> Das reine "static" als Methode oder was das auch immer ist, habe ich zwar schon öfters bei erzeugtem Code von Decompilern und so gesehen, aber mir nie richtig Gedankn drum gemacht. Vor allem, weil diese Methode gewöhnlich auch leer ist.
> [...]



*drücke den nichtvorhandenen "gefällt mir Button"*


----------



## theuserbl (3. Okt 2011)

Habe die Datei Test.jar nun mal hier zum runterladen drangehangen.
Funktioniert sie?

Werde mal eben den Rechner neu starten und auf WinXP das ganze testen.


----------



## theuserbl (3. Okt 2011)

Bei mir funktiniert es unter WindowsXP genauso wie unter Linux: Ohne Probleme.

Habe nun noch mal für Windows-User die Datei TestPrg.zip erstellt. Da sind alle Dateien noch mal drin. Und die Datei compile.bat.
Dort mußt Du nur die erste Zeile umändern auf das Bin-Verzeichnis von Deinem JDK.

Und lade bitte die erzeugte Test.jar dann hoch.
Und was ist mit der Test.jar die ich hochgeladen habe. Funktioniert sie bei Dir?

Grüße
theuserbl


----------



## Moucho (3. Okt 2011)

WUHU es klappt :toll:

habe deine Jar ausprobiert und die ging ohne probleme, also habe ich aus meinem Programm (welches ich von dir kopiert habe) auch eine jar erzeugt und siehe da, es hat geklappt.

Und mein Projekt funktioniert auch als Jar, allerdings nicht wenn ich es bei eclipse ausführe, da kommt halt dieser Nullpointer, warum auch immer ???:L

Danke an euch alle 
besonders an dir, theuserbl :applaus:


----------

