0

There are many questions on stackoverflow about this, but the solution is going on .m2 Maven folder and deleting the jar files. That is not a great solution: sometimes there are 10 corrupted jars and I need to manually search for themone by one. In Spring with 65 dependencies on the project that's a nightmare.

Reading ZIP file gives an 'invalid LOC header' Exception

Invalid LOC header(bad signature)

https://kingring.wordpress.com/2014/01/27/solve-maven-compile-error-invalid-loc-header-bad-signature/

I am mostly an Eclipse user, but actually using all major IDE's (Intellij and Netbeans). We are in 2019 and there is no plugin or tool that detects that kind of corrupted jars and replacing them with fresh new ones?

In Eclipse you can try to force Maven to redownload dependencies, but not replacing the corrupted jars.

This is very serious problem, because every once in a while, I'm loosing 30 minutes fixing corrupted jars.

Please suggest me some kind of solution, if there is.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
  • 1
    According to my calendar, we're still in 2018; maybe if you wait a year, the problem will be sorted. But joking aside, I think I've only ever had this problem once. If you get this so regularly, you may want to check the quality of your internet connectivity or your harddrive for bad sectors. – Mark Rotteveel Oct 10 '18 at 18:04
  • @MarkRotteveel Well you are right but i need an after catastrophy happened solution. ::) An Early Christmas present. – GOXR3PLUS Oct 10 '18 at 18:08
  • 1
    @GOXR3PLUS I started working on a tool (with GUI and pom-drag-and-drop and all that) after I saw your question ... it's really just procrastination, I should be working actually. But did you see https://stackoverflow.com/a/44891133/3182664 ? There's not sooo much to do for such a tool that goes beyond some things that can be done with the standard toolbox... – Marco13 Oct 10 '18 at 21:22
  • 1
    Well, I may have set different priorities here... The result is at https://github.com/javagl/DependencyCleaner . It resolves the specific dependencies of one POM file and shows their status in a UI, allowing to delete the invalid JARs and refresh them from Maven Central. I just hacked this down in a few hours, so it may have bugs or flaws or not work at all for you, but maybe someone finds it useful. For me, it was a chance to look at programmatic Maven dependency resolution and stuff... – Marco13 Oct 12 '18 at 17:58
  • @Marco13 O my boyyy Marco that's fantastic, wish that UI was in JavaFX instead of Swing so i contribute, definitely i will use your tool :) – GOXR3PLUS Oct 12 '18 at 18:06
  • 1
    A first step of "refactoring"/"extension" of this tool would be to more cleanly separate the model and the view, so that it's easier to plug a JavaFX UI on top of it. (It shouldn't be sooo hard right now, but I'm using some of my own Swing libs whose functionality might not be available out-of-the-box in JavaFX). The next step would be to offer the option to just scan the whole local `m2` folder, of course. I've basically prepared/considered that, but not implemented it yet. – Marco13 Oct 13 '18 at 12:53
  • @Marco13 Great, you think of continuing your awesome project :)? I mean what will happen when swing is not in Java anymore :( – GOXR3PLUS Oct 13 '18 at 14:24

1 Answers1

1

I suspect my approach may not be what you want, but it's fairly trivial to create an app that tries to instantiate a java.util.jar.JarFile() for each *.jar file in the Maven repository.

If there is a problem with that instantiation just capture the name of the jar file and the exception and log it. Obviously you should not be getting any exceptions, so for testing I did a binary edit on a real Jar file just to test the code.

This code was written for Windows. Since it accesses the file system it might need tweaking for other platforms, but apart from that you only need to modify the string specifying the name of the Maven Repository in main():

package jarvalidator;

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.jar.*;
import java.util.stream.*;

public class JarValidator {

    public static void main(String[] args) throws IOException {
        Path repositoryPath = Path.of("C:\\Users\\johndoe\\.m2");

        if (Files.exists(repositoryPath)) {
            JarValidator jv = new JarValidator();
            List<String> jarReport = new ArrayList<>();
            jarReport.add("Repository to process: " + repositoryPath.toString());
            List<Path> jarFiles = jv.getFiles(repositoryPath, ".jar");
            jarReport.add("Number of jars to process: " + jarFiles.size());
            jarReport.addAll(jv.openJars(jarFiles));
            jarReport.stream().forEach(System.out::println);
        } else {
            System.out.println("Repository path " + repositoryPath + " does not exist.");
        }
    }

    private List<Path> getFiles(Path filePath, String fileExtension) throws IOException {
        return Files.walk(filePath)
                .filter(p -> p.toString().endsWith(fileExtension))
                .collect(Collectors.toList());
    }

    private List<String> openJars(List<Path> jarFiles) {
        int badJars = 0;
        List<String> messages = new ArrayList<>();

        for (Path path : jarFiles) {
            try {
                new JarFile(path.toFile()); // Just dheck for an exception on instantiation.
            } catch (IOException ex) {
                messages.add(path.toAbsolutePath() + " threw exception: " + ex.toString());
                badJars++;
            }
        }
        messages.add("Total bad jars = " + badJars);
        return messages;
    }
}

This is the output from running the code:

run:
Repository to process: C:\Users\johndoe\.m2
Number of jars to process: 4920
C:\Users\johndoe\.m2\repository\bouncycastle\isoparser-1.1.18.jar threw exception: java.util.zip.ZipException: zip END header not found
Total bad jars = 1
BUILD SUCCESSFUL (total time: 2 seconds)
skomisa
  • 16,436
  • 7
  • 61
  • 102
  • Well you made the start now i will make it a real app with UI for JavaFX. Thank you sir. – GOXR3PLUS Oct 11 '18 at 04:43
  • Or even an Eclipse Plugin... never written before... though :) – GOXR3PLUS Oct 11 '18 at 04:45
  • 1
    Well even at best it's not a true solution. Presumably you really want to be alerted at the time a bad JAR gets created, and this approach does not do that. But it is straightforward, and it works. – skomisa Oct 11 '18 at 04:52
  • 1
    @GOXR3PLUS Using Java's WatchService API may be the way to go. You could get notified when JARs are added to folders in the Repository, and process those notifications in almost-real-time. [Here's a tutorial](https://howtodoinjava.com/java8/java-8-watchservice-api-tutorial/). – skomisa Oct 11 '18 at 05:07