Determining what is the API for the JDK turns out to be a non-trivial problem. At some level, the "ground truth" is provided by the compiler and the libraries it uses. The libraries include rt.jar and similar jar files that come with a Java installation. However, that means that if those files are different (e.g. different vendors) then the API can be different. In this case, we use the Oracle jar files.
Adding to the difficulty is that the library jar files contain implementations of types that are there solely to support the JDK implementation (e.g. types in the com.sun package and subpackages) and are not intended to be used by Java developers. Such types should not really be considered part of the API.
Given that Java developers will make decisions about what types they can used based on what's documented in the "API Specification" JavaDoc pages, those pages perhaps represent the most authoritative source of what the API is. For the purposes of this exercise, the files that make up the JavaDoc pages will be used to identify the API contents.
The API consists of the types, and the accessible members of those types. Such members are any that are non-private, since such members could be used by any Java developer.
The identification of the api version is done from bytecode, meaning any symbols lost in the compilation process (e.g. constants of primitive type) won't be recorded.
It seems unlikely two JRE versions will differ only on existence of a constant so this shouldn't be a problem (in fact this assumption can be checked)
The version recorded is the earliest that would allow the system to be compiled. The system may in fact have been written against a later version, but just so happened to not use anything specific to the later version.
The identification of the API is a heuristic. There is nothing stopping a developer from using the classes in com.sun that appear in the deployed jar files, in which case the results of the process described above may vary.
Some system may have been written against one JRE version but later recompiled with a later JRE version. This can mean some symbols appearing in the bytecode that indicate a later version of the JRE is needed than is really the case. For example, the class org.apache.tools.ant.taskdefs.optional.ejb.EjbJar is distributed in ant-1.2, and it's compiled form contains a reference to java.util.AbstractList, despite there being not reference to this in the source code.