Why am I getting this exception when trying to generate an .exe with Launch4J?

201 Views Asked by At

I have a functioning JAR that uses some resources from an external directory and others from itself (using "getResourceAsStream", they are all images). The program consists on a GUI created with JavaFX FXML (along the library "Controls FX") that make queries to a SQLite Database. When I try to run the .exe file that Launch4J suppossedly created "successfully", 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).

Things I have tried:

  • Including the libraries in the classpath in Launch4J. Same exception.

  • Changing the minimum and maximum JRE versions. Same exception.

  • 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 "getResourceAsStream" to get the image from within the JAR). It does work, so the problem must be somewhere.

  • 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.

  • 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.

  • Getting the images from an external directory, also using "getResourceAsStream". Same as before: the exception just shows up in another point of the code.

  • Using Jar2Exe instead. The exe is generated as well, but it doesn't run.

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).

Thanks in advance.

Stack trace in Launch4J:

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.<init>(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

The relevants part of the code are:

  1. The enum that contains the paths within the jar file:
public static enum RUTAS_DENTRO_DE_JAR {
        TIPOS("métodosCompartidos/iconosTipos"),
        // More paths
        public String ruta;
        RUTAS_DENTRO_DE_JAR(String cadena) {
            ruta = cadena;
        }
  1. The part where the method to fill up ArrayList with images is called.
private static ArrayList<Image> ICONOS_TIPOS = new MétodosCompartidos().AsignarImágenesJAR(constantes.RUTAS_DENTRO_DE_JAR.TIPOS.ruta, MétodosCompartidos.class);
           
  1. The method that gets the images and return the ArrayList (it uses another method: "ObtenerNombresDirectorioJAR" that return all the filenames from the specific JAR directory indicated by the first paramether, starting by the class define by the second paramether).
public static ArrayList<Image> AsignarImágenesJAR(String ruta, Class clase) throws IOException {
       ArrayList<String> ArrayNombres = ObtenerNombresDirectorioJAR(ruta, clase);
       ArrayList<Image> ArrayImágenes = new ArrayList<>();

       /**
        * Rellenamos ArrayImágenes con las imágenes
        */
       try {
           for (int i = 0; i < 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;
   }
  1. The point in which the exception is thrown: another method that tries to set the image for a button (second line). "constantes.IMAGENES.TIPOSG.Comunes" is the reference to the enum that makes easier to access the ArrayList previously created.
c.ImagenesBoton = constantes.IMÁGENES.TIPOSG.Comunes;
c.ImagenBotón.setImage(c.ImagenesBoton.get(0));
0

There are 0 best solutions below