Question

Do any of you know of a tool that will search for .class files and then display their compiled versions?

I know you can look at them individually in a hex editor but I have a lot of class files to look over (something in my giant application is compiling to Java6 for some reason).

Was it helpful?

Solution

Use the javap tool that comes with the JDK. The -verbose option will print the version number of the class file.

> javap -verbose MyClass
Compiled from "MyClass.java"
public class MyClass
  SourceFile: "MyClass.java"
  minor version: 0
  major version: 46
...

To only show the version:

WINDOWS> javap -verbose MyClass | find "version"
LINUX  > javap -verbose MyClass | grep version

OTHER TIPS

It is easy enough to read the class file signature and get these values without a 3rd party API. All you need to do is read the first 8 bytes.

ClassFile {
    u4 magic;
    u2 minor_version;
    u2 major_version;

For class file version 51.0 (Java 7), the opening bytes are:

CA FE BA BE 00 00 00 33

...where 0xCAFEBABE are the magic bytes, 0x0000 is the minor version and 0x0033 is the major version.

import java.io.*;

public class Demo {
  public static void main(String[] args) throws IOException {
    ClassLoader loader = Demo.class.getClassLoader();
    try (InputStream in = loader.getResourceAsStream("Demo.class");
        DataInputStream data = new DataInputStream(in)) {
      if (0xCAFEBABE != data.readInt()) {
        throw new IOException("invalid header");
      }
      int minor = data.readUnsignedShort();
      int major = data.readUnsignedShort();
      System.out.println(major + "." + minor);
    }
  }
}

Walking directories (File) and archives (JarFile) looking for class files is trivial.

Oracle's Joe Darcy's blog lists the class version to JDK version mappings up to Java 7:

Target   Major.minor Hex
1.1      45.3        0x2D
1.2      46.0        0x2E
1.3      47.0        0x2F
1.4      48.0        0x30
5 (1.5)  49.0        0x31
6 (1.6)  50.0        0x32
7 (1.7)  51.0        0x33
8 (1.8)  52.0        0x34
9        53.0        0x35

On Unix-like

file /path/to/Thing.class

Will give the file type and version as well. Here is what the output looks like:

compiled Java class data, version 49.0

If you are on a unix system you could just do a

find /target-folder -name \*.class | xargs file | grep "version 50\.0"

(my version of file says "compiled Java class data, version 50.0" for java6 classes).

Yet another java version check

od -t d -j 7 -N 1 ApplicationContextProvider.class | head -1 | awk '{print "Java", $2 - 44}'

In eclipse if you don't have sources attached. Mind the first line after the attach source button.

// Compiled from CDestinoLog.java (version 1.5 : 49.0, super bit)

enter image description here

Maybe this helps somebody, too. Looks there is more easy way to get JAVA version used to compile/build .class. This way is useful to application/class self check on JAVA version.

I have gone through JDK library and found this useful constant: com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION. I do not know since when it is in JAVA JDK.

Trying this piece of code for several version constants I get result below:

src:

System.out.println("JAVA DEV       ver.: " + com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION);
System.out.println("JAVA RUN     v. X.Y: " + System.getProperty("java.specification.version") );
System.out.println("JAVA RUN v. W.X.Y.Z: " + com.sun.deploy.config.Config.getJavaVersion() ); //_javaVersionProperty
System.out.println("JAVA RUN  full ver.: " + System.getProperty("java.runtime.version")  + " (may return unknown)" );
System.out.println("JAVA RUN       type: " + com.sun.deploy.config.Config.getJavaRuntimeNameProperty() );

output:

JAVA DEV       ver.: 1.8.0_77
JAVA RUN     v. X.Y: 1.8
JAVA RUN v. W.X.Y.Z: 1.8.0_91
JAVA RUN  full ver.: 1.8.0_91-b14 (may return unknown)
JAVA RUN       type: Java(TM) SE Runtime Environment

In class bytecode there is really stored constant - see red marked part of Main.call - constant stored in .class bytecode

Constant is in class used for checking if JAVA version is out of date (see How Java checks that is out of date)...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top