title: Why am I getting this exception when trying to generate an .exe with Launch4J?
body: <p>I have a functioning JAR that uses some resources from an external directory and others from itself (using &quot;getResourceAsStream&quot;, they are all images). The program consists on a GUI created with JavaFX FXML (along the library &quot;Controls FX&quot;) that make queries to a SQLite Database.  When I try to run the .exe file that Launch4J suppossedly created &quot;successfully&quot;, it throws an ArrayIndexOutOfBoundsException, refering to the line in which I try to assign an image from an ArrayList to a button (the button is the normal one included in FX).</p>
  <p>Things I have tried:</p>
  <ul>
  <li><p>Including the libraries in the classpath in Launch4J. Same exception.</p>
  </li>
  <li><p>Changing the minimum and maximum JRE versions. Same exception.</p>
  </li>
  <li><p>Creating an .exe from a JAR of a diferent project using the same building properties and a similar image storage (an ArrayList filled up by a static enum that uses &quot;getResourceAsStream&quot; to get the image from within the JAR). It does work, so the problem must be somewhere.</p>
  </li>
  <li><p>Making sure that the ArrayList is filled with images before it tries to access it (the index of the image is 0). I mean, the JAR works perfectly, but I still had to double check. It is filled when I run it in Netbeans or as a JAR, but oddly enough, Launch4J doesn't print my message before showing the exception.</p>
  </li>
  <li><p>Trying to access the image by a relative path instead of from the ArrayList in which it should be stored. The exception changes and now it points to a different class in which I also try to access an image stored in an ArrayList. If I get that image by a relative path as well, the exception moves to a different point.</p>
  </li>
  <li><p>Getting the images from an external directory, also using &quot;getResourceAsStream&quot;. Same as before: the exception just shows up in another point of the code.</p>
  </li>
  <li><p>Using Jar2Exe instead. The exe is generated as well, but it doesn't run.</p>
  </li>
  </ul>
  <p>To summarize: all the exceptions seem to be related with images obtention, which somehow doesn't work when it implies accessing a resource inside the JAR stored inside an ArrayList, but only for this specific project (it worked in a different one) and in an .exe (it works in Netbeans and in the JAR).</p>
  <p>Thanks in advance.</p>
  <p>Stack trace in Launch4J:</p>
  <pre><code>Executing: C:\Users\Setito\Desktop\DAM\Proyecto_fin_de_grado\PVZHeroes-Stats\PVZHeroes-Stats.exe
  Exception in Application start method
  java.lang.reflect.InvocationTargetException
      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 com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
      at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
      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 sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
  Caused by: java.lang.RuntimeException: Exception in Application start method
      at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
      at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
      at java.lang.Thread.run(Unknown Source)
  Caused by: javafx.fxml.LoadException: 
  file:/C:/Users/Setito/Desktop/DAM/Proyecto_fin_de_grado/PVZHeroes-Stats/PVZHeroes-Stats.exe!/pvzheroes/clases/FXMLDocument.fxml
  
      at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
      at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
      at pvzheroes.clases.PVZHeroesStats.start(PVZHeroesStats.java:28)
      at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
      at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
      at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
      at java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
      at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
      at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
      at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
      ... 1 more
  Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
      at java.util.ArrayList.rangeCheck(Unknown Source)
      at java.util.ArrayList.get(Unknown Source)
      at pvzheroes.clases.inicializaciónComponentes.ConfigurarBotón(inicializaciónComponentes.java:98)
      at pvzheroes.clases.inicializaciónComponentes.&lt;init&gt;(inicializaciónComponentes.java:59)
      at pvzheroes.clases.FXMLDocumentController.initialize(FXMLDocumentController.java:584)
      at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
      ... 17 more
  Exception running application pvzheroes.clases.PVZHeroesStats
  
  </code></pre>
  <p>The relevants part of the code are:</p>
  <ol>
  <li>The enum that contains the paths within the jar file:</li>
  </ol>
  <pre><code>public static enum RUTAS_DENTRO_DE_JAR {
          TIPOS(&quot;métodosCompartidos/iconosTipos&quot;),
          // More paths
          public String ruta;
          RUTAS_DENTRO_DE_JAR(String cadena) {
              ruta = cadena;
          }
  </code></pre>
  <ol start="2">
  <li>The part where the method to fill up ArrayList with images is called.</li>
  </ol>
  <pre><code>private static ArrayList&lt;Image&gt; ICONOS_TIPOS = new MétodosCompartidos().AsignarImágenesJAR(constantes.RUTAS_DENTRO_DE_JAR.TIPOS.ruta, MétodosCompartidos.class);
             
  </code></pre>
  <ol start="3">
  <li>The method that gets the images and return the ArrayList (it uses another method: &quot;ObtenerNombresDirectorioJAR&quot; that return all the filenames from the specific JAR directory indicated by the first paramether, starting by the class define by the second paramether).</li>
  </ol>
  <pre><code>public static ArrayList&lt;Image&gt; AsignarImágenesJAR(String ruta, Class clase) throws IOException {
         ArrayList&lt;String&gt; ArrayNombres = ObtenerNombresDirectorioJAR(ruta, clase);
         ArrayList&lt;Image&gt; ArrayImágenes = new ArrayList&lt;&gt;();
  
         /**
          * Rellenamos ArrayImágenes con las imágenes
          */
         try {
             for (int i = 0; i &lt; ArrayNombres.size(); i++) {
                 Image imagen = new Image(MétodosCompartidos.class.getResourceAsStream(ArrayNombres.get(i)));
                 ArrayImágenes.add(imagen);
             }
         } catch (NullPointerException e) {
             new DiálogoGenérico(constantes.TIPOS_DIÁLOGO.SIN_FONDOS.Cadena);
             System.exit(0);
         }
         return ArrayImágenes;
     }
  </code></pre>
  <ol start="4">
  <li>The point in which the exception is thrown: another method that tries to set the image for a button (second line). &quot;constantes.IMAGENES.TIPOSG.Comunes&quot; is the reference to the enum that makes easier to access the ArrayList previously created.</li>
  </ol>
  <pre><code>c.ImagenesBoton = constantes.IMÁGENES.TIPOSG.Comunes;
  c.ImagenBotón.setImage(c.ImagenesBoton.get(0));
  </code></pre>