javaeclipsejarexecutable-jarrunnable-jar

Why does my manually built runnable jar respond with "Error: Could not find or load main class" when the class exists?


This is one of those error messages that comes up a lot, but none of the question/answers address this particular situation.

Why would one file work, and the other, seemingly identical file not work?

Here's a snip of the code that I'm using. Not the full implementation, just the interesting bit:

    ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
    for (int i = 0; i < fileList.length; i++) {
        InputStream in = new FileInputStream(fileList[i]);
        String absoluteFileNameString = fileList[i].getAbsolutePath();
        if (baseDirectory != null && baseDirectory.length() > 0 && absoluteFileNameString.length() > (baseDirectory.length() + 1) ) {
            absoluteFileNameString = absoluteFileNameString.substring(baseDirectory.length() + 1);
        }
        out.putNextEntry(new ZipEntry(absoluteFileNameString));
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        out.closeEntry();
        in.close();
    }
    out.close();

Here is the output showing that one works and the other doesn't:

C:\Users\Owner\git\runnablejarbuilder\RunnableJarBuilder>java -jar RunnableJarBuilder.zip
Error: Could not find or load main class com.rjb.test.HelloRun
Caused by: java.lang.ClassNotFoundException: com.rjb.test.HelloRun

C:\Users\Owner\git\runnablejarbuilder\RunnableJarBuilder>java -jar RunnableJarBuilderIDE.zip
Hello Runnable Jar!

Below is a screen shot (the only way to capture what Windows explorer was telling me: the files were exactly duplicates of each other):

jar files expanded by Windows explorer show as identical and windows command prompt shows one works and other does not


Solution

  • After analyzing the zip files using zipdump, I realized my code was using backslashes (\) as a path separator, but ZipEntry expected a forward slash (/). This was my non-working file:

    C:\Users\Owner\git\runnablejarbuilder\RunnableJarBuilder\zipdump>C:\Users\Owner\AppData\Local\Programs\Python\Python38-32\python.exe zipdump.py RunnableJarBuilder.zip
            75 ( 97.3%)  2024-11-18 12:27:10  106e3e9c [NOLFH] META-INF/MANIFEST.MF
          7831 ( 48.9%)  2024-11-18 12:27:10  a30be143 [NOLFH] com\rjb\test\BuildJarFromClassFiles.class
          4601 ( 53.4%)  2024-11-18 12:27:10  0742ac06 [NOLFH] com\rjb\test\ClasspathReader.class
           561 ( 62.2%)  2024-11-18 12:27:10  d38480b3 [NOLFH] com\rjb\test\HelloRun.class
          6525 ( 50.6%)  2024-11-18 12:27:10  364411d0 [NOLFH] com\rjb\test\JarUpdater.class
    

    And this was the working one, which the IDE created:

    C:\Users\Owner\git\runnablejarbuilder\RunnableJarBuilder\zipdump>C:\Users\Owner\AppData\Local\Programs\Python\Python38-32\python.exe zipdump.py RunnableJarBuilderIDE.zip
            75 ( 97.3%)  2024-11-18 12:25:54  106e3e9c [NOLFH] META-INF/MANIFEST.MF
          4601 ( 53.4%)  2024-11-18 10:44:42  0742ac06 [NOLFH] com/rjb/test/ClasspathReader.class
          7831 ( 48.9%)  2024-11-18 12:23:00  a30be143 [NOLFH] com/rjb/test/BuildJarFromClassFiles.class
           561 ( 62.2%)  2024-11-18 09:02:48  d38480b3 [NOLFH] com/rjb/test/HelloRun.class
          6525 ( 50.6%)  2024-11-18 09:46:12  364411d0 [NOLFH] com/rjb/test/JarUpdater.class
    

    I fixed the problem by replacing all the backslashes with forward slashes in the path name:

    //REPLACE THIS LINE
    //String absoluteFileNameString = fileList[i].getAbsolutePath();
    
    //WITH THIS LINE - Never use backslashes in zip file entries!!
    //String absoluteFileNameString = fileList[i].getAbsolutePath().replace("\\","/");
    // or better, suggested by DuncG
    String absoluteFileNameString = fileList[i].getAbsolutePath().replace(File.separatorChar,"/");
    
    

    This might come up on Windows especially, and may be less of a problem on Linux.