How can I verify all class files and Jar files used in my app are compiled for Java 8?
Asked Answered
C

2

2

I'm using Java 11 and targeting Java8 but finding some libraries I'm depending on are not being compiled for running in Java 8.

Is there a command that can look at an uber jar, and report all of the versions of Java that are being used within it?

I searched and found the answer for Java6 (see below) dated 2014 so I'm looking for a newer version of that answer or the answer to the uber jar question above.

This is the link

Charily answered 20/3, 2023 at 20:16 Comment(2)
Example that you provided is ok, simply upgrade m-enforcer-p and extra-enforcer-rules to the latest version - and of course change maxJdkVersion what you needArrant
Run your test suite with Java 8.Reinwald
C
1

This answer is credited to the article Guide to Find the Java .class Version which says the following (reproduced for posterity):

A class file has the major version in the 7th and 8th byte of a file, and the hexdump command shown next can print the version.

hexdump -s 7 -n 1 -e '"%d"' Sample.class
52  <<< Means the class file is compiled for Java8 runtime

The version is a number that maps to a Java version. A partial list is shown below, a more complete list is in the Baeldung article listed above.

Java Release   Class Major Version    Hex Value
JAVA SE 17             61                0x3d
JAVA SE 11             55                0x37
JAVA SE 8              52                0x34

Another way to get this information is to use the javap command shown next:

javap -verbose Sample | grep major
  major version: 55

The docs for the java class file are at https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html (provided by @Thorbjørn Ravn Andersen in previous answer)

Charily answered 22/3, 2023 at 12:59 Comment(0)
N
3

There are at least two ways you can tell if a given library is compatible with Java 8:

I did the latter in a similar situation many years ago. Today for a shaded jar (which I believe is just all the classes combined into a single jar file) I would probably just write a small program that read the jar as a zip file and for each entry named something ending in .class inspected the byte stream for that entry to see what the version number is for that file.

That said, that is not what I would recommend you do. It solves the immediate problem at hand, but what would really benefit you long term is to test your program!

So write up some tests. A few unit tests for each library you use that verifies it behaves as you expect (junit is fine for this) and then run it with your target Java! Any modern IDE can be told to add a specific JVM and use it for your tests. Docker is very useful to have full control of your execution environment. If you use Github you can use GitHub actions to test this automatically even.

This will benefit you in several ways. You are told if for any reason an API breaks when upgrading to newest version. You know that your code runs as intended on the target platform. You document for the future you why you use this library and what you expect it to do.

Nordgren answered 21/3, 2023 at 6:29 Comment(4)
I like your answer, but I'm not sure how to implement it. For example, how can I in a unit test get a list of all of the maven dependencies (direct and indirect). Most of the libraries I'm using I did not write, other developers in the company have written and published them to NEXUS (maven repo). I can't add unit tests to their code. Also for the "Read the docs" I wasn't sure what you meant. What is the concept to be learned in the documentation? Or maybe a link to an article. Just curious.Charily
Your code should not know anything about maven. Your code should say something like Given this object, how does it behave if I call it like this? Do I get back what I need? This should work for your target JVM to validate that things are as you expect them to be, Incidentally it will also catch if the library is not compatible with your jvm.Reinwald
And “read the documentation” means what it says. Read the documentation for the library you want to use. It usually explicitly says what it requires from the jvm.Reinwald
I found a solution and posted it. Thank's for your answer as it provided a different perspective on the larger problem and addressing the larger problem systemically.Charily
C
1

This answer is credited to the article Guide to Find the Java .class Version which says the following (reproduced for posterity):

A class file has the major version in the 7th and 8th byte of a file, and the hexdump command shown next can print the version.

hexdump -s 7 -n 1 -e '"%d"' Sample.class
52  <<< Means the class file is compiled for Java8 runtime

The version is a number that maps to a Java version. A partial list is shown below, a more complete list is in the Baeldung article listed above.

Java Release   Class Major Version    Hex Value
JAVA SE 17             61                0x3d
JAVA SE 11             55                0x37
JAVA SE 8              52                0x34

Another way to get this information is to use the javap command shown next:

javap -verbose Sample | grep major
  major version: 55

The docs for the java class file are at https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html (provided by @Thorbjørn Ravn Andersen in previous answer)

Charily answered 22/3, 2023 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.