apidiff - compare different versions of an API
apidiff [options]
The apidiff command reads source, class and HTML files
that provide different versions of an API, compares corresponding
declarations in the different versions and writes out an HTML report.
The comparison includes:
javadoc toolapidiff provides different groups of options, to
specify:
All options have a long form, beginning with --. Some
options may have a single-letter form, beginning with just
-. For those options that take an argument, the value may
be separated from the option name by either white space or ‘=’. In
general, as is common with most JDK tools, if an option is repeated, the
rule is “last one wins”. This rule is modified for the options that
specify the APIs to be compared, such that “last one wins” only applies
within the group of API-specific options used to define each API.
To see detailed information about how the options are processed, use
--verbose options.
To specify each of the APIs to be compared, use the
--api name option followed by a series of
API-specific options that apply to that API.
The API-specific options must at least include options to find the source or class files for the declarations to be compared. The options should also define the location of the generated documentation if that is to be included in the comparison. (When comparing the API documentation, it is not enough to just specify the location of that documentation.)
Note that the API-specific options for each API are separate and distinct from the API-specific options for any other API.
--api nameSpecifies a name for the API and sets the current API for use by the API-specific
options that immediately follow this option. The name will appear in the
generated reports when identifying any differences. If the generated
report will be publicly shared, it is recommended that the name should
be reasonably meaningful to any readers. A longer, more descriptive
label may also be given with the --label option.
The option, and the API-specific options that follow, should be provided for each API to be compared.
The order in which the --api options first appear on the
command line determines the order in which any differences are reported.
It is recommended to specify the options in chronological order, from
the oldest version of the API to the most recent version of the API.
--api-directory
directoryjavadoc command for the API.
--jdk-build
directorySpecifies a directory containing a JDK build from which to infer
values for various options. The builds can either be for default-named
configurations in separate repositories or work areas, or for
differently named configurations in the same repository. (To create
different configurations within the same JDK repository, use the
--with-conf-name option when running
sh ./configure to create the configuration.)
It is a matter of personal preference whether to use separate repositories or separate configurations within a single repository for the instances of the API to be compared.
make.make.When using this option, it should not be necessary to give any
additional javac-like options, like
--module-path or --release.
For example,
--jdk-build
repository/build/configuration-name--jdk-build /Users/Duke/jdk-dev/build/macosx-aarch64--jdk-build /Users/Duke/jdk-dev/build/macosx-aarch64-server-release--jdk-build $HOME/OpenJDK/build/linux-x86_64-server-fastdebug--label textThe following API options are similar to the corresponding
javac option; see the javac documentation for
more details about the arguments for those options.
--class-path path,
-classpath path, or -cp
path--enable-preview--module-path
path or -p path--module-source-path
module-source-path--patch-module
module=path--release
release--source release or
-source release--source-path path
or -sourcepath pathjavac, you cannot use this option to specify where to find
the source code for a single module. Use the
--module-source-path option instead, possibly using the
module-specific form of that option.
--system jdk |
noneBy convention, the APIs should be defined on the command in chronological order: oldest first, newest last. When comparing documentation comments or API descriptions, the APIs will be compared pairwise, with each of the older instances being compared against the newest instance.
The following options are used to specify the elements (declarations)
to be compared within the APIs, specified by the
various --api options and associated API-specific
options.
These options apply equally to all the APIs to be compared: there is no need to repeat these options for each API to be compared.
--access
public|protected|package|privateSpecifies the access of the declarations to be compared. The default
is protected.
public: public declarations onlyprotected: public and protected declarationspackage: public, protected and package-private
declarationsprivate: all declarationsNote: this option does not apply to the parts of the serialized form of a serializable class, even if those parts are provided by private methods and fields.
--exclude
pattern--include options are excluded.
--include
pattern--include option.
--compare-api-descriptions
booleanjavadoc) should be compared for each element being
compared. The option defaults to true if an API directory
is given for each instance of the API to be compared and if
documentation comments are not to be compared. (See
--compare-doc-comments). When the option is enabled, either
explicitly or by default, the API directory must be specified for each
instance of the API to be compared, and set to the location of the files
generated by javadoc that corresponds to the source and
class files being compared. The API directory for an API can be
specified explicitly, with the --api-directory option, or
indirectly, with the --jdk-build and
--jdk-docs options.
--compare-api-descriptions-as-text
booleanjavadoc) should be compared as plain text for each element
being compared. If the argument is true, this option also
implies --compare-api-descriptions true.
--compare-doc-comments
booleanfalse if the API descriptions are to be
compared, and true otherwise. (See
--compare-api-descriptions).
--jdk-docs
name--jdk-build option, specifies the
name of the documentation bundle to use when more than one is available.
It need not be specified if all the APIs specified by
--jdk-build have exactly one directory matching the name
images/*docs*: this is typically the case when building the
OpenJDK docs or docs-jdk targets. For example,
docs, javase-docs,
reference-docs.
--output-directory
directory or -d directory--title text--description
html--info-text
name=htmlSpecifies information to be included in different positions on each page. name can be one of:
top: at the top of each page; this may be used to
indicate the status of the pages.header: in the header bar on each page; if not
specified, a default value is generated, based on the names of the APIs
being compared.footer: in the footer bar on each page; if not
specified, a default value is generated, based on the names of the APIs
being compared.bottom: at the bottom of each page; this may be used to
indicate copyright and license information,--notes file--main-stylesheet
file--extra-stylesheet
fileThis option may be useful when comparing HTML documentation that contains references to custom styles.
--resource-files
file-or-directoryThis option may be useful when comparing HTML documentation that depend on some non-HTML resource files.
--help, -help,
-h, -?--version,
-v--verbose
flag[,flag]*Specifies the kinds of verbose output. flag may be one of
all, none, or one of the following, optionally
preceded by - to negate the flag: module,
package, type, time,
options.
| Flag | Description |
|---|---|
module |
Report on the modules being compared |
package |
Report on the modules and packages being compared |
type |
Report on the modules, packages, and classes and interfaces being compared |
time |
Report the time taken to perform the comparison and generate the reports |
options |
Report how the command-line options are processed |
@filenameapidiff command, you can specify one or more files that
contain arguments for the apidiff command. This lets you
create apidiff commands of any length on any operating
system. The syntax for the contents of the file is similar to that for
other JDK commands, like javac and javadoc.
apidiff exits with one of the following values:
| Exit status | Description |
|---|---|
| 0 | No differences were found |
| 1 | Differences were found |
| 2 | There was an error in the command-line arguments |
| 3 | An error occurred |
The --help and --version options exit with
a status of 0.
The current API is the API specified by the most recent
--api option on the command line, and is the API for which
any subsequent API-specific options will apply.
The “current API” is cancelled when any option is given that is not
specific to any one API. Additional options for an API can be given by
repeating the --api option to set the API as the current
API again.
Patterns provide a way to specify groups of similarly-named modules, packages and types to be included or excluded from the comparison.
A pattern consists of a module-part and/or a type_part.
module-part: : | qualified-identifier
/ | qualified-identifier.* /
type-part: : | ** |
qualified-identifier |
qualified-identifier.* |
qualified-identifier.**
A module-part that is just a qualified identifier matches the named module. A module-part that ends in a wildcard matches all module names that begin with the given qualified identifier.
A type-part that is just a qualified identifier matches the
named type. A type-part that ends in a single *
matches all types in the package with the given qualified identifier. A
type-part that ends in ** matches all types in all
packages that begin with the given qualified identifier. A
type-part of ** can only be used in conjunction
with a non-empty module part.
apidiff cannot compare a combination of types in named
modules and types in the unnamed module, and so either all patterns must
include a module part, or none must.
For example,
java.base/java.nio.** matches all types in the
java.nio packages and corresponding subpackages, in the
java.base modulejava.compiler/** matches all packages and types in the
java.compiler moduleDepending on how you invoke apidiff, you may need to
quote the pattern to prevent the * characters being
interpreted by a command shell.
A “notes” file is used to specify links to be injected into the generated report for some elements.
The file is a plain text file. Blank lines and lines beginning with
# are ignored. The remaining lines are interpreted as a
series of blocks, each of which must start with a line containing a URL
and a short plain-text description, followed by a series of lines, each
containing a signature describing an element or set of elements. For
each block, a link based on the URL and description, will be added to
any element appearing in the generated report that matches any of the
corresponding signatures.
The following signatures are supported:
/*/ ] package/ ] package
.*/ ] package .
type/ ] package .
type .*/ ] package .
type # field/ ] package .
type # <init> (
parameters )/ ] package .
type # method (
parameters )Signatures should not contain any white-space characters. Signatures
ending in /* or .* match the specified item,
and any enclosed elements down to the level of a type element. For
methods and constructors, parameters is a comma-separated list
of parameter types, omitting any type parameters, and using just the
simple name of any declared types.
For example,
java.base/* matches the java.base module,
all packages in java.base, and all types in those
packages.java.base/java.lang.* matches the
java.lang package in the java.base module, and
all types in that package. Note that it does not include subpackages,
such as java.lang.reflect, or any types in those
subpackages.java.base/java.lang.String just matches the type
java.lang.String.java.base/java.lang.String#equals(Object) just matches
the equals(Object).At a minimum, the source or class files must be provided for each
instance of the API to be compared. If the API does not provide or is
not part of a module, use the --source-path and
--class-path options. If the API provides or is part of one
or more modules, use the --source-path,
--module-source-path, --module-path, and
related options.
If you want to compare the content of documentation comments, you must provide source files for all the elements to be compared; any dependencies of those source files can be specified as either source or class files.
If you want to compare the API descriptions, you must provide the
locations of the directories generated by the javadoc tool
for each of the instances of the API being compared. This is often a
directory whose path ends in api, although that is not a
requirement. To eliminate any false positive differences being
introduced by changes to the javadoc tool itself, the same
or equivalent versions of javadoc should be used for each
API to be compared.
If you want to compare all the exported packages in a module, use
--include <module>/**. If you want to compare the
contents of specific packages in a module, use
--include <module>/<package>.* or
--include <module>/<package>.**. The
.** form will also include the contents of any subpackages.
You can use multiple --include options to include different
parts of an API in the comparison.
apidiff can be used to compare different instances of
JDK, but that can be tricky to set up, depending on the kind of
comparison that is required. That being said, there is a “convenience”
option to specify a JDK build, as generated by the standard JDK
makefiles.
If you want to compare the files in two separate JDK builds, for each instance use the following:
--api option to introduce the set of API-specific
options that follow--jdk-build option to specify the location of the
build containing the files to be compared, such as
build/macosx-x64,
build/linux-x86_64-server-release, or the path for any
directory that is used for a custom configuration.The directory specified with --jdk-build should contain
the following files:
spec.gmk,images/jdk,images/*docs*, if
API descriptions should be compared, andsupport/src.zip, if documentation
comments should be comparedIn conjunction with this option, use the jdk-docs option
to specify the name of the docs bundle to be compared, when there is
more than one. Note this option applies to all instances to be compared,
and need only be given once; it is not specific to the current API. Use the
--compare-doc-comments and
--compare-api-descriptions as needed to indicate the
comparisons to be included in the report.
If neither are specified, --compare-api-descriptions is the
default.
While the --jdk-build option provides a convenient way
to have the tool automatically generate the equivalent underlying
options, you can instead specify those options directly.
If you just want to compare some or all of the declarations in different instances of JDK, without comparing the documentation comments or API documentation, for each instance use the following:
--api option to introduce the set of API-specific
options that follow--system option to point to the instance of
JDKIf you want to compare the declarations and the corresponding API
descriptions generated by javadoc, for each instance of JDK
use the following:
--api option to introduce the set of API-specific
options that follow--system option to point to the instance of
JDK--api-directory option to point to the
corresponding documentation generated by the javadoc
toolIf you want to compare the declarations and the corresponding documentation comments, it is recommended to use the following:
--api option to introduce the set of API-specific
options that follow--system option to point to the instance of
JDK--patch-module options to specify the
location of the source for each of the modules to be comparedWhen using --patch-module, you do not need to specify
all the source directories for the module: you just need to specify the
source directories containing the classes whose documentation comments
are to be compared. Any supporting declarations will be found in the JDK
specified by the --system option.
If the list of --patch-module options is large, it may
be convenient to place them in a file and use the
@file option to specify the location of the file.
You might also choose to put all the options for an API in an
API-specific @file.
If you want to compare the API descriptions as well as the
documentation comments, you can combine the recommended options for the
two modes, specifying both --patch-module options for the
source files and --api-directory for the generated
documentation.
If you are using the --jdk-build option, and the
corresponding images directory has multiple matches for
images/*docs*, you will need to use the
--jdk-docs option to disambiguate which documentation
directory to use. The value that you give should be the name of one of
those subdirectories of the images directory. The
--jdk-docs option is not specific to any individual API,
and need only be given once on the command-line. It will be used as
needed to disambiguate the documentation directory to be used for any
API that is defined by using the --jdk-build option.
If you want to see or understand how the options are used internally,
you can use --verbose options, possibly implicitly as part
of --verbose all.
When comparing any generated API documentation, the comparison is
sensitive to any variations caused by the version of
javadoc used to generate the documentation. Therefore, it
is highly recommended to use the same version of javadoc to
generate the documentation for all the versions to be compared. When
building JDK, although the standard docs and
docs-jdk targets will use the version of
javadoc in the same repository, you can specify the version
of JDK to be used for targets like docs-reference-api with
the --with-docs-reference-jdk option to
configure, allowing you to specify the same version of JDK
and hence the same version of javadoc to be used to
generate the API documentation for each build to be compared. Generally,
the JDK version used to generate the documentation should be at least as
recent as the latest version to be compared.
When comparing recent API changes in JDK, such as when creating a
report for a CSR request, when there is no change in
javadoc in the versions being compared, it is reasonable to
use the standard docs or docs-jdk targets to
generate the API documentation to be compared.
If the API does not define any modules, use an appropriate
combination of the --source-path,
--class-path, and --api-directory options. You
can put either the compiled classes or a JAR file on the class path. If
you want to compare documentation comments, put the source files on the
source path. If you want to compare the API documentation, use the
--api-directory to specify the root directory of the
documentation.
For example, to set up an API to be able to compare the API documentation associated with a JAR file:
--api before --class-path build/example.jar --api-directory build/docs/api
To set up an API to be able to compare the documentation comments for a project:
--api before --source-path src/main/java
In both cases, you can specify any additional dependencies on the class path.
If the API defines one or more modules, use an appropriate
combination of the --module-source-path,
--module-path, and --api-directory options.
You can put either the module or a directory of modules on the module
path, where a module is anything that can be recognized as such by
javac. If you want to compare documentation comments, put
the source files on the module source path. If you want to compare the
API documentation, use the --api-directory to specify the
root directory of the documentation.
For example, to set up an API to be able to compare the API documentation associated with the modules for a project:
--api before --module-path build/modules --api-directory build/docs/api
To set up an API to be able to compare the documentation comments for
a project that defines a module called com.example:
--api before --module-source-path com.example=src/main/java
In both cases, you can specify any additional dependencies on the module path.
As well as comparing the declarations found in source files or
compiled class files, apidiff can compare documentation
comments and/or the API documentation generated by javadoc
and the Standard Doclet.
Comparing documentation comments is easy, and does not require
API documentation to have been generated. However, it is just a simple
text comparison of the text of the documentation comments, and so does
not take into account any of the analysis and processing that is done by
the Standard Doclet. Most notably, it does not take
{@inheritDoc} into account, and so might miss some
differences in any inherited documentation.
Comparing API descriptions is better for comparing the
documentation as generated by the Standard Doclet, and as seen by the
end user reading the API specification. However, it does require that
API documentation needs to be generated beforehand, and generally using
the same version of javadoc for all the versions of the API
that are being compared.
The tool operates by creating an instance of the Java compiler
front-end (as found in the jdk.compiler
module) from which it can obtain the selected elements to be compared,
using the Java
Language Model API and Compiler
Tree API.
Note: Because the compiler is reading the source and class files
for each instance of the API being compared, the release of the JDK
platform used to run apidiff must be at least as recent as
each of the releases used to compile the instances to be
compared.
When comparing the API descriptions for each selected element, the
tool attempts to find the relevant content in the API documentation that
is provided using the
--api-directory or
--jdk-build options. The
tool does not attempt to run javadoc locally to
generate the page on the fly.
To compare APIs in the java.base module in JDK builds
/local/baseline-jdk and /local/updated-jdk,
and place the result in the directory out, run the
following command:
bin/apidiff \
--api jdk \
--jdk-build /local/baseline-jdk/build/linux-x86_64-server-fastdebug \
--api sv \
--jdk-build /local/updated-jdk/build/linux-x86_64-server-fastdebug \
--jdk-docs docs \
-d out \
--compare-api-descriptions true \
--include 'java.base/**'
To compare the changes for the fix for an issue such as JDK-8330183, using two separate configurations in the same repo, use a command like this:
apidiff \
--api jdk24 --jdk-build build/baseline \
--api 8330183 --jdk-build build/macosx-aarch64-server-release \
--include 'java.compiler/**' \
--output-directory build/apidiff
While the previous example is minimal, it could be augmented by providing additional details to be included in the output, and additional options to be explicit about some of the desired settings.
apidiff \
--api jdk24 --jdk-build build/baseline --label "The baseline for the changes"\
--api 8330183 --jdk-build build/macosx-aarch64-server-release --label "Add SourceVersion.RELEASE_24" \
--include 'java.compiler/**' \
--output-directory build/apidiff \
--compare-api-descriptions true \
--jdk-docs docs \
--info-text top="This proposal is not yet final" \
--title "Diffs for JDK-8330183 CSR" \
--description "Generated by $USER at $(date -u)"