classgraph: Scanning on LinuxKit doesn't work when scan root is not root directory of a jarfile

https://github.com/lukehutch/fast-classpath-scanner/blob/c07698e2b7dea93b102b35f04f369bf5e911b789/src/main/java/io/github/lukehutch/fastclasspathscanner/scanner/RelativePath.java#L224

The line indicated is getting null from nestedJarHandler, when then is wrapped and throw as an IOException. This is preventing matching classes from being processed for a jar.

2018-01-23T18:52:34.862+0000    FastClasspathScanner    -- Searching for "Class-Path:" entries within manifest files
2018-01-23T18:52:34.874+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/localedata.jar
2018-01-23T18:52:34.874+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/sunjce_provider.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/sunpkcs11.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/cldrdata.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/zipfs.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/sunec.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/jfxrt.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/nashorn.jar
2018-01-23T18:52:34.877+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/jaccess.jar
2018-01-23T18:52:34.878+0000    FastClasspathScanner    ---- Ignoring JRE jar: /usr/java/jdk1.8.0_131/jre/lib/ext/dnsns.jar
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ---- Could not canonicalize path: /acceptance-1.22-SNAPSHOT.jar!/BOOT-INF/classes
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------ java.io.IOException: Exception while getting jarfile jar:file:/acceptance-1.22-SNAPSHOT.jar!/BOOT-INF/classes
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.RelativePath.getFile(RelativePath.java:223)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.RelativePath.exists(RelativePath.java:290)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.RelativePath.isValidClasspathElement(RelativePath.java:313)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.Scanner$1.processWorkUnit(Scanner.java:235)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.Scanner$1.processWorkUnit(Scanner.java:224)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.utils.WorkQueue.runWorkLoop(WorkQueue.java:182)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.utils.WorkQueue$1.call(WorkQueue.java:147)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.utils.WorkQueue$1.call(WorkQueue.java:144)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at java.lang.Thread.run(Thread.java:748)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------ Caused by: java.lang.NullPointerException
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  at io.github.lukehutch.fastclasspathscanner.scanner.RelativePath.getFile(RelativePath.java:208)
2018-01-23T18:52:34.880+0000    FastClasspathScanner    ------  ... 11 more

This has been seen using 2.9.5 or later releases. 2.9.4 is a version that does not have this problem.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 59 (29 by maintainers)

Commits related to this issue

Most upvoted comments

@ncoe Sure, that will do it. Although digging into this issue uncovered two other issues so far, so we’re making progress 😃

It looks like 2.21 is still working.

You’re welcome @lukehutch, I tested both 2.20.2 and 2.21 on Linux (no Windows) and both are working great. Thanks for the fix and new feature.

I can poke at it on monday

I can provide more details of what is happening with this issue. FastClasspathScanner is not seeing classes that are located in a Spring Boot self-executable jar within BOOT-INF/classes and is dependent on which Java version is being used. I have verified this is an issue from 2.9.5 through the master branch.

Specifically, in NestedJarHandler.java line #181, within fastclasspathscanner there’s the following code:

final ZipEntry childZipEntry = parentZipFile.getEntry(childPath);

Depending on which version of Java you are using you may or may not get back a childZipEntry with a trailing / (on Linux).

If it doesn’t return back with a trailing / then the next section of code at NestedJarHandler #191 will get skipped since it doesn’t think that BOOT-INF/classes is a directory because it’s missing the trailing slash (expected BOOT-INF/classes/).

// Make sure path component is a file, not a directory (can't unzip directories)
if (childZipEntry.isDirectory()) {
    if (log != null) {
        log.log(nestedJarPath,
                              "Child path component " + childPath + " in jarfile " + bareParentJarFile
                                  + " is a directory, not a file -- using as scanning root");
    }
    // Add directory path to parent jarfile root relative paths set
    parentJarfileAndRootRelativePaths.getValue().add(childPath);
    // Return parent entry
    return parentJarfileAndRootRelativePaths;
} 

For more details on ZipEntry returning a trailing slash (/), see the following link.

http://www.oracle.com/technetwork/java/javase/8u144-relnotes-3838694.html?printOnly=1

One option would be to always ensure there’s a trailing slash no matter which version of Java is being used.

We are also hoping this fix can make it in for the 3.0 release.

Thanks.

-Mike- Mike Gardiner

@ncoe better “Is this it?” than “Why has my bug sat in the bugtracker for 2 years and nobody has even commented on it?”! I try to be as responsive as possible with FCS, due to frustration with how few software projects out there do the same…

I committed a unit test for this, with a Spring Boot “fully executable jar”, produced the same way you describe, using the same Maven config lines. It has the same sort of Bash code prepended to it. The test passes on my machine. There must be something different about your jar or your Java environment. When you do build a test jar, you could just rename it to src/test/resources/spring-boot-fully-executable-jar.jar, overwriting the one in the most recent patch above, and hopefully that will be enough to trigger the test failure.

thats fine, life happens. mostly i want to stop this process as it can get out of hand. https://www.youtube.com/watch?v=TYM4QKMg12o