0

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));
  • 1
    ArrayIndexOutOfBoundsException cannot be directly caused by launch4j and such. Only indirectly, which means your question cannot be answered without providing more details. The likely cause is that you've corrupted your jar file or otherwise caused the getResourceAsStream call to return something else. You'd have to paste that code as well as the actual stack trace to get anywhere. Note that 'get images from an external directory with getResourceAsStream' is not possible and therefore doesn't make sense which suggests the problem lies there - you do not appear to fully understand what it does. – rzwitserloot Oct 22 '20 at 00:36
  • https://stackoverflow.com/questions/61531317/how-do-i-determine-the-correct-path-for-fxml-files-css-files-images-and-other – kleopatra Oct 22 '20 at 07:07
  • You're totally right. I actually used the class "File" to get the images from the external directory. I don't know what I was thinking about when I wrote that bit. Sorry about that. I don't quite understand how it's possible that a jar file that runs perfectly on its own gets corrupted when it's converted into an .exe. Also, if the code within the.exe is the same (I am assuming that, I don't actually know), why would the method return something else? I'll copy the stack trace generated by Launch4J in a bit to see if it can clarify something, as well as the relevant portions of the code. – Setito Maraña Oct 22 '20 at 13:07

0 Answers0