Class version (Java)

Java major and minor version

https://docs.oracle.com/javase/specs/jvms/se18/html/jvms-4.html#jvms-4.1-200-B.2

Notes:

(i) For a class file whose major_version is 56 or above, the minor_version must be 0 or 65535 (if it depends on preview features).

(**) For a class file whose major_version is between 45 and 55 inclusive, the minor_version may be any value.

(ii) When JDK 1.2 introduced support for major version 46, the only minor version supported under that major version was 0. Later JDKs continued the practice of introducing support for a new major version (47, 48, ..., 55) but supporting only a minor version of 0 under the new major version.

(iii) JDK 1.1 supported versions 45.0 through 45.65535 inclusive.

(iv) JDK 1.0.2 supported versions 45.0 through 45.3 inclusive.

major minor Java_SE

62 (i) 18

61 (i) 17

60 (i) 16

59 (i) 15

58 (i) 14

57 (i) 13

56 (i) 12

55 0 11

54 0 10

53 0 9

52 0 8

51 0 7

50 0 6

49 0 5.0

48 0 1.4

47 0 1.3

46 0 1.2

45 (iii) 1.1

45 (iv) 1.0.2

Class version recursively

find . -type f -exec file -- {} +

./cat/exceptions/MyException.class: compiled Java class data, version 49.0 (Java 1.5)

./cat/model/MyFile.class: compiled Java class data, version 49.0 (Java 1.5)

./cat/model/MyDTO.class: compiled Java class data, version 49.0 (Java 1.5)

Javap version checker

$ javap -verbose MyFile.class | grep version

$ javap -verbose *.class | grep version

minor version: 0

major version: 49

Class version checker

ClassVersionChecker.sh

#!/bin/bash


# Compile w/:

# javac ClassVersionChecker.java



java ClassVersionChecker > ClassVersionChecker.txt


echo See result in file ClassVersionChecker.txt



ClassVersionChecker.java

import java.io.*;

import java.util.ArrayList;

import java.util.Iterator;


/**

* It prints Java class version numbers.<br>

* Shamelessly inspired on:<br>

* http://www.rgagnon.com/javadetails/java-0544.html<br>

*

* Check the class version<br>

* The first 4 bytes are a magic number, 0xcafebabe, to identify a valid class file then the next 2

* bytes identify the class format version (major and minor).<br>

*/

public class ClassVersionChecker {


/**

* Entry point.

*

* @param args If no argument is provided then it loops all .class files in the directory and

* subdirectories;<br>

* else only the specified .class file or files are treated.<br>

*/

public static void main(String[] args) throws IOException {

if (args.length == 0) {

ArrayList < File > files = new ArrayList < File > ();

fillFilesClass("./", files);

File fi;

for (Iterator < File > i = files.iterator(); i.hasNext();) {

fi = i.next();

if (fi.getName().endsWith(".class")) {

checkClassVersion(fi);

} else {

// ignore file (not a .class one)

}

}

} else {

for (int i = 0; i < args.length; i++) {

checkClassVersion(args[i]);

}

}

}


private static void checkClassVersion(final File f) throws IOException {

DataInputStream in = new DataInputStream(new FileInputStream(f));


int magic = in .readInt();

if (magic != 0xcafebabe) {

System.out.println(f.getName() + " is not a valid class!");;

}

int minor = in .readUnsignedShort();

int major = in .readUnsignedShort(); in .close();


// System.out.println(f.getName() + ": " + major + "." + minor + " (" +

// getJavaPlatformVersion(major, minor) + ")");

System.out.println(major + "." + minor + "\t(" + getJavaPlatformVersion(major, minor) + ")" +

"\t\t" + f.getName());

}


private static void checkClassVersion(String fileName) throws IOException {

final File f = new File(fileName);

checkClassVersion(f);

}


/*- */

private static void fillFilesClass(final String directoryName, final ArrayList < File > files) {

final File directory = new File(directoryName);

// get all the files from a directory

File[] fList = directory.listFiles();

for (File file: fList) {

if (file.isFile()) {

if (file.getName().endsWith(".class")) {

files.add(file);

} else if (file.getName().endsWith(".jar") || file.getName().endsWith(".war")) {

System.out.println(">>>>>>>> UNPROCESED ARCHIVE >>>>>>>>\t " + file.getName());

} else {

// Nothing, not interested in this kind of file

}


} else if (file.isDirectory()) {

fillFilesClass(file.getAbsolutePath(), files);

}

}

}


/*- Thanks to https://stackoverflow.com/questions/14676407/list-all-files-in-the-folder-and-also-sub-folders */

private static void listf(String directoryName, ArrayList < File > files) {

File directory = new File(directoryName);

// get all the files from a directory

File[] fList = directory.listFiles();

for (File file: fList) {

if (file.isFile()) {

files.add(file);

} else if (file.isDirectory()) {

listf(file.getAbsolutePath(), files);

}

}

}


/*- */

private static String getJavaPlatformVersion(final int major, int minor) {

String ret;


if (major == 45) {

ret = "Java 1.1 or 1.0.2";

} else if (major == 46) {

ret = "Java 1.2";

} else if (major == 47) {

ret = "Java 1.3 ";

} else if (major == 48) {

ret = "Java 1.4 ";

} else if (major == 49) {

ret = "Java 5.0 ";

} else if (major == 50) {

ret = "Java 6 ";

} else if (major == 51) {

ret = "Java 7 ";

} else if (major == 52) {

ret = "Java 8 ";

} else if (major == 53) {

ret = "Java 9 ";

} else if (major == 54) {

ret = "Java 10";

} else if (major == 55) {

ret = "Java 11";

} else if (major == 56) {

ret = "Java 12";

} else if (major == 57) {

ret = "Java 13";

} else if (major == 58) {

ret = "Java 14";

} else if (major == 59) {

ret = "Java 15";

} else if (major == 60) {

ret = "Java 16";

} else if (major == 61) {

ret = "Java 17";

} else if (major == 62) {

ret = "Java 18";

} else {

ret = "Unkown";

}


return ret;

}


}