spotify / missinglink

Build time tool for detecting link problems in java projects
Apache License 2.0
144 stars 27 forks source link

Unsupported class file major version 59 when loading org.bouncycastle:bcprov-jdk15on:1.68 #124

Closed augi closed 3 years ago

augi commented 3 years ago

We are getting Unsupported class file major version 59 exception when the project contains a dependency on org.bouncycastle:bcprov-jdk15on:1.68.

It looks like the issue is that missinglink tries to load classes from META-INF.

com.spotify.missinglink.MissingLinkException: Could not load META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$EdDSA.class from /root/.cache/coursier/v1/https/artifactory/artifactory/repo1.maven.org-maven2/org/bouncycastle/bcprov-jdk15on/1.68/bcprov-jdk15on-1.68.jar
    at com.spotify.missinglink.ArtifactLoader.loadFromJar(ArtifactLoader.java:73)
    at com.spotify.missinglink.ArtifactLoader.load(ArtifactLoader.java:54)
    at com.spotify.missinglink.ArtifactLoader.load(ArtifactLoader.java:42)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.fileToArtifact$1(MissingLinkPlugin.scala:208)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$constructArtifacts$3(MissingLinkPlugin.scala:211)
    at scala.collection.immutable.List.map(List.scala:297)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.constructArtifacts(MissingLinkPlugin.scala:211)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.loadArtifactsAndCheckConflicts(MissingLinkPlugin.scala:121)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$configSettings$1(MissingLinkPlugin.scala:72)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$configSettings$1$adapted(MissingLinkPlugin.scala:61)
    at scala.Function1.$anonfun$compose$1(Function1.scala:49)
    at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
    at sbt.std.Transform$$anon$4.work(Transform.scala:68)
    at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
    at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
    at sbt.Execute.work(Execute.scala:291)
    at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
    at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 59
    at org.objectweb.asm.ClassReader.<init>(ClassReader.java:195)
    at org.objectweb.asm.ClassReader.<init>(ClassReader.java:176)
    at org.objectweb.asm.ClassReader.<init>(ClassReader.java:162)
    at org.objectweb.asm.ClassReader.<init>(ClassReader.java:283)
    at com.spotify.missinglink.ClassLoader.readClassNode(ClassLoader.java:96)
    at com.spotify.missinglink.ClassLoader.load(ClassLoader.java:73)
    at com.spotify.missinglink.ArtifactLoader.loadFromJar(ArtifactLoader.java:68)
    at com.spotify.missinglink.ArtifactLoader.load(ArtifactLoader.java:54)
    at com.spotify.missinglink.ArtifactLoader.load(ArtifactLoader.java:42)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.fileToArtifact$1(MissingLinkPlugin.scala:208)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$constructArtifacts$3(MissingLinkPlugin.scala:211)
    at scala.collection.immutable.List.map(List.scala:297)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.constructArtifacts(MissingLinkPlugin.scala:211)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.loadArtifactsAndCheckConflicts(MissingLinkPlugin.scala:121)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$configSettings$1(MissingLinkPlugin.scala:72)
    at ch.epfl.scala.sbtmissinglink.MissingLinkPlugin$.$anonfun$configSettings$1$adapted(MissingLinkPlugin.scala:61)
mattnworb commented 3 years ago

I am not super familiar with the format here, but I think that the specific error message comes from metadata in the META-INF/MANIFEST.MF file for org.bouncycastle:bcprov-jdk15on:1.68. Here is what I found after downloading the artifact from https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on/1.68:

$ unzip -c bcprov-jdk15on-1.68.jar META-INF/MANIFEST.MF | grep --line-number -C 1 edec/SignatureSpi$EdDSA
2631-
2632:Name: org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$Ed
2633- 25519.class
--
--
4399-Name: META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric
4400: /edec/SignatureSpi.class
4401-SHA-256-Digest: 4pFp/tAj7g9Vn/ZXFesC6oDeyF+RIN8FAyangajSPKQ=

$ unzip -l bcprov-jdk15on-1.68.jar | grep versions/15
        0  12-21-2020 18:15   META-INF/versions/15/
        0  12-21-2020 18:15   META-INF/versions/15/org/
        0  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/
        0  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/
        0  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/
        0  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/
        0  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/
      385  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$EdDSA.class
      395  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$X448.class
      393  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$Ed25519.class
      523  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$X448.class
      389  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$Ed448.class
     1340  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/BC11XDHPrivateKey.class
     8197  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi.class
     1348  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/BC15EdDSAPrivateKey.class
      529  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$X25519.class
      448  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$EdDSA.class
      397  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$Ed448.class
      526  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$Ed448.class
      399  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$X25519.class
      445  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$XDH.class
     6593  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi.class
      396  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$EdDSA.class
     4986  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi.class
     1570  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/BC15EdDSAPublicKey.class
      401  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$Ed25519.class
     1421  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/BC11XDHPublicKey.class
      392  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyFactorySpi$XDH.class
      532  12-21-2020 18:15   META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/KeyPairGeneratorSpi$Ed25519.class

So I think maybe the question might be why this artifact has class files under a META-INF/versions/15 path, which appear to be compiled with Java 15?

the hex 3b here is "major version 59":

$ unzip -p bcprov-jdk15on-1.68.jar META-INF/versions/15/org/bouncycastle/jcajce/provider/asymmetric/edec/SignatureSpi$EdDSA.class | xxd | head
00000000: cafe babe 0000 003b 00d2 0a00 0200 0307  .......;........

I think this is more of an issue with the bouncycastle packaging and asm than something with missinglink.

mattnworb commented 3 years ago

ah, the META-INF/versions/15 stuff is because it is a multi-release JAR file

$ unzip -p bcprov-jdk15on-1.68.jar META-INF/MANIFEST.MF | grep Multi-Release
Multi-Release: true
augi commented 3 years ago

Yeah, exactly! The JAR seems to be valid. The question is how these JARs should be handled 🤔 Btw. we were running the build on AdoptOpenJDK11. Maybe it wouldn't fail when running on JDK15 but it would still be nice not to fail when running on JDK11.

Maybe it would make sense to just ignore classes from META-INF/versions that cannot be parsed because of unsupported version, or something like this 🤔

mattnworb commented 3 years ago

It has been a long time since I have looked at the relevant code in missinglink, but I think this logic probably needs updating to deal with multi-release JARs, since it expects that every entry in the jar/zip file that ends in .class should be loaded:

https://github.com/spotify/missinglink/blob/0d2d4ab7d88c240ad49c83b35c174c0926564fd4/core/src/main/java/com/spotify/missinglink/ArtifactLoader.java#L59-L68