Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What version of javac built my jar?

Tags:

java

jar

People also ask

How can I tell what version of Java a compiled class is?

In Java, we can use javap -verbose className to print out the class information. D:\projects>javap -verbose Test Classfile /D:/projects/Test. class Last modified 16 Apr 2019; size 413 bytes MD5 checksum 8679313dc0728e291898ad34656241cb Compiled from "Test.


A jar is merely a container. It is a file archive ā la tar. While a jar may have interesting information contained within it's META-INF hierarchy, it has no obligation to specify the vintage of the classes within it's contents. For that, one must examine the class files therein.

As as Peter Lawrey mentioned in comment to the original question, you can't necessarily know which JDK release built a given class file, but you can find out the byte code class version of the class file contained in a jar.

Yes, this kinda sucks, but the first step is to extract one or more classes from the jar. For example:

$ jar xf log4j-1.2.15.jar

On Linux, Mac OS X or Windows with Cygwin installed, the file(1) command knows the class version.

$ file ./org/apache/log4j/Appender.class
./org/apache/log4j/Appender.class: compiled Java class data, version 45.3

Or alternatively, using javap from the JDK as @jikes.thunderbolt aptly points out:

$ javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45

For Windows environments without either file or grep

> javap -v ./org/apache/log4j/Appender.class | findstr major
 major version: 45

FWIW, I will concur that javap will tell a whole lot more about a given class file than the original question asked.

Anyway, a different class version, for example:

$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0

The class version major number corresponds to the following Java JDK versions:

  • 45.3 = Java 1.1
  • 46 = Java 1.2
  • 47 = Java 1.3
  • 48 = Java 1.4
  • 49 = Java 5
  • 50 = Java 6
  • 51 = Java 7
  • 52 = Java 8
  • 53 = Java 9
  • 54 = Java 10
  • 55 = Java 11
  • 56 = Java 12
  • 57 = Java 13
  • 58 = Java 14

You can't tell from the JAR file itself, necessarily.

Download a hex editor and open one of the class files inside the JAR and look at byte offsets 4 through 7. The version information is built in.

http://en.wikipedia.org/wiki/Java_class_file

Note: As mentioned in the comment below,

those bytes tell you what version the class has been compiled FOR, not what version compiled it.


Here is Java's way to find this information.

Windows: javap -v <class> | findstr major
Unix: javap -v <class> | grep major

For example:
> javap -v Application | findstr major   major version: 51


There is no need to unpack the JAR (if one of the class names is known or is looked up e.g. using 7zip), so on Windows the following would be sufficient:

javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major

The Java compiler (javac) does not build jars, it translates Java files into class files. The Jar tool (jar) creates the actual jars. If no custom manifest was specified, the default manifest will specify which version of the JDK was used to create the jar.


Since I needed to analyze fat jars I was interested in the version of each individual class in a jar file. Therefore I took Joe Liversedge approach https://stackoverflow.com/a/27877215/1497139 and combined it with David J. Liszewski' https://stackoverflow.com/a/3313839/1497139 class number version table to create a bash script jarv to show the versions of all class files in a jar file.

usage

usage: ./jarv jarfile
 -h|--help: show this usage

Example

jarv $Home/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar

java 1.4 org.apache.log4j.Appender
java 1.4 org.apache.log4j.AppenderSkeleton
java 1.4 org.apache.log4j.AsyncAppender$DiscardSummary
java 1.4 org.apache.log4j.AsyncAppender$Dispatcher
...

Bash script jarv

#!/bin/bash
# WF 2018-07-12
# find out the class versions with in jar file
# see https://stackoverflow.com/questions/3313532/what-version-of-javac-built-my-jar

# uncomment do debug
# set -x

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'  
red='\033[0;31m'  
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}

#
# error
#
#   show an error message and exit
#
#   params:
#     1: l_msg - the message to display
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error: $l_msg" 1>&2
  exit 1
}

#
# show the usage
#
usage() {
  echo "usage: $0 jarfile"
  # -h|--help|usage|show this usage
  echo " -h|--help: show this usage"
  exit 1 
}

#
# showclassversions
#
showclassversions() {
  local l_jar="$1"
  jar -tf "$l_jar" | grep '.class' | while read classname
  do
    class=$(echo $classname | sed -e 's/\.class$//')
    class_version=$(javap -classpath "$l_jar" -verbose $class | grep 'major version' | cut -f2 -d ":" | cut -c2-)
    class_pretty=$(echo $class | sed -e 's#/#.#g')
    case $class_version in
      45.3) java_version="java 1.1";;
      46) java_version="java 1.2";;
      47) java_version="java 1.3";;
      48) java_version="java 1.4";;
      49) java_version="java5";;
      50) java_version="java6";;
      51) java_version="java7";;
      52) java_version="java8";;
      53) java_version="java9";;
      54) java_version="java10";;
      *) java_version="x${class_version}x";;
    esac
    echo $java_version $class_pretty
  done
}

# check the number of parameters
if [ $# -lt 1 ]
then
  usage
fi

# start of script
# check arguments
while test $# -gt 0
do
  case $1 in
    # -h|--help|usage|show this usage
    -h|--help) 
      usage
      exit 1
      ;;
    *)
     showclassversions "$1"
  esac
  shift
done 

you can find Java compiler version from .class files using a Hex Editor.

Step 1: Extract .class files from jar file using a zip extractor

step 2: open .class file with a hex editor.(I have used notepad++ hex editor plugin. This plugin reads file as binary and shows it in hex) You can see below. enter image description here

Index 6 and 7 gives major version number of the class file format being used. https://en.wikipedia.org/wiki/Java_class_file

Java SE 11 = 55 (0x37 hex)

Java SE 10 = 54 (0x36 hex)

Java SE 9 = 53 (0x35 hex)

Java SE 8 = 52 (0x34 hex),

Java SE 7 = 51 (0x33 hex),

Java SE 6.0 = 50 (0x32 hex),

Java SE 5.0 = 49 (0x31 hex),

JDK 1.4 = 48 (0x30 hex),

JDK 1.3 = 47 (0x2F hex),

JDK 1.2 = 46 (0x2E hex),

JDK 1.1 = 45 (0x2D hex).