![]() |
|
JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared. This is very useful for describing exactly what has changed between two releases of a product. Only the API (Application Programming Interface) of each version is compared. It does not compare what the source code does when executed.
Sample Output: see the Main Index page for sample output.
There is a complete example of how
to use JDiff in the examples
directory. There is also an Ant build file
simple.xml
which shows how to use the
JDiffAntTask
Ant task.
The basic sequence of operations is to run JDiff on one set of source files to create an XML file which represents the API for that version of a product. Then JDiff is run again on another set of source files to create an XML file which represents the API for the next version of a product. Finally, JDiff compares the two APIs as represented in the XML files and generates an HTML report which describes the differences between the two APIs, together with comments describing the reasons for the differences.
Note: if you are not connected to the Internet, or are behind a firewall,
see the documentation for how to use
the -baseURI
option, and also the troubleshooting
firewall entry. This only applies to generating JDiff output,
not to viewing it.
The results are written into a file calledchanges.html
, with more files in a directory calledchanges
. These files contain links to existing Javadoc documentation. A CSS stylesheet is also generated in the filestylesheet-jdiff.css
, and this uses a background image inbackground.gif
. These are the only files which usually need to be shipped with a product to include a report of what has changed since the previous release.. (If the-stats
option was used, then the fileblack.gif
should also be shipped.)
No Windows registry entries are changed by JDiff. To remove JDiff, simply delete the directory where it is installed.
There are two different ways to run JDiff. The first way is to use thejdiff
script in thebin
directory and an XML configuration file. The format of the XML configuration file is the same one which ANT uses, and it can be used as an ANT build file if you already use ANT. If you don't use ANT, the configuration file is simply a convenient place to configure JDiff. If the-buildfile
option is not used,jdiff
will look for a local configuration file namedbuild.xml
.
jdiff [-version] [-buildfile <configuration filename>]
The second way is to invoke JDiff directly as a Javadoc doclet. This is described in more detail in the example which is shipped with JDiff.
javadoc -doclet jdiff.JDiff -docletpath lib\jdiff.jar [-apiname <API name>] [-apidir <optional directory where the API XML file is to be placed>] [-oldapi <name of old API>] [-oldapidir <optional directory where the old API XML file is located>] [-newapi <name of new API>] [-newapidir <optional directory where the new API XML file is located>] [-sourcepath <source path>] [-javadocnew <javadoc files location for the new API>] [-javadocold <javadoc files location for the old API>] [-baseURI <base>] [-excludeclass <exclusion level>] [-excludemember <exclusion level>] [-nosuggest <suggestion level>] [-firstsentence] [-docchanges] [-checkcomments] [-packagesonly] [-showallchanges] [-retainnonprinting] [-excludetag <exclude tag>] [-stats] [-windowtitle <text>] [-doctitle <HTML text>] [-version] [-help]
NOTE: Either-apiname
, or both-oldapi
and-newapi
must be used. All other arguments are optional.
The -d directory
argument works just as with Javadoc, redirecting
the output to the given directory.
The arguments for JDiff are:
-apiname
<API name>-apidir
argument.
-oldapi
<name of old API>-apiname
when
the XML file was generated.
-newapi
<name of old API>-apiname
when
the XML file was generated.
-apidir
<API directory>-apiname
argument.
-oldapidir
<old API directory>-oldapi
argument. Default is the current
directory.
-newapidir
<new API directory>-newapi
argument. Default is the current
directory.
-sourcepath
<source path>examples/SuperProduct1.0
. The
slashes in this argument should match the local architecture.
-javadocnew
<javadoc files location for the new API>-javadocold
<javadoc files location for the old API>-baseURI
<base>-baseURI "file:///C:/jdiff/lib"
would cause
the XML parser to use the copies which are shipped in the
lib
directory, if JDiff is installed in
C:\jdiff
. Note that there are three forward slashes
after "file:".
-excludeclass
<exclusion level>-private
argument must also be passed to Javadoc.
-excludemember
<exclusion level>-private
argument must also be passed to Javadoc.
-firstsentence
-docchanges
for how to
note documentation changes as differences.-docchanges
-firstsentence
option for how to compare just
the first sentence in Javadoc documentation.
-nosuggest
<suggestion level>-checkcomments
-packagesonly
-showallchanges
-retainnonprinting
-excludetag <exclude tag>
foo
, containing
-excludetag @exclude
.
-stats
-windowtitle <text>
-doctitle <HTML text>
-version
-help
The JDiff Ant task is an Ant task to make using JDiff even easier than using the Ant Javadoc task. TheJDIFF_HOME
property must be set to the location of where JDiff is installed, that is, the name of the directory which contains a sudirectorylib
withjdiff.jar
and the other files shipped inlib
with JDiff. The JDiff task provides default locations for the generated XML files, and also generates these XML files each time it is executed. By default, it generates Javadoc reports for both versions too. The Ant JDiff task has been tested with JDK1.4.2 and Ant 1.6.1.
If you are comparing two large projects, it is recommended that you instead use the Ant Javadoc task as shown in. This will permit you to generate the XML file for each version once, and then generate different kinds of reports from the two XML files. The Javadoc task also lets you change all of the parameters shown in the Synopsis. jdiff/examples/build.xml
Parameters
Attribute Description Required destdir The location where the JDiff report will be generated. Defaults to a directory "jdiff_report" in the directory from where Ant was executed. No stats Generate an HTML page of statistical information about the differences between the two APIs. Defaults to "off". No docchanges Enables comparison of Javadoc documentation. Defaults to "off". No verbose Increase the logging vebosity of the task. Defaults to "off". No
Parameters specified as nested elements
Theold
andnew
elements are used to describe the projects to be compared.
Attribute Description Required name The name of the project, e.g. "My Project Version 1". The name, with spaces replaced by underscores, is used as the name of the XML file in destdir
, which is generated by JDiff to represent the structure of the source files of this project.Yes javadoc The location of a Javadoc report for this project. If this attribute is not used, then a Javadoc report for the project will be generated in a subdirectory named name
indestdir
.No
Note: theold
andnew
elements only haveDirSet
nested elements, notFileSet
ones.
Examples
An minimal usage of the JDiff Ant task, taken fromjdiff/examples/simple.xml
, looks like:<target name="easyjdiff" depends="init"> <!-- Must be set to the root of where JDiff is installed. --> <property name="JDIFF_HOME" value=".."/> <!-- Just one simple way to tell Ant about the JDiff task --> <taskdef name="jdiff" classname="jdiff.JDiffAntTask" classpath="${JDIFF_HOME}/lib/antjdiff.jar"/> <!-- Compare Version 1 of a project to Version 2 --> <jdiff> <old name="Version 1"> <dirset dir="SuperProduct1.0" includes="com/**"/> </old> <new name="Version 2"> <dirset dir="SuperProduct2.0" includes="com/**"/> </new> </jdiff> </target>
- Interfaces appear in italics, just as in Javadoc documentation.
- When a package or class appears in bold, it has been added in the new version or API.
- When a package or class appears
struck through, it has been removed in the new version or API.- When a constructor is added, two entries are added to the "All Differences" index: one for the addition of a new constructor, and one for the change of the class. The constructor entry has "constructor" after it.
- There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes.
- It is quite often useful to change the memory parameters for Javadoc, e.g. pass in
-J-Xmx128m
to Javadoc.- On a P3 450MHz machine, to scan all of the J2SE
Java
andjavax
packages and generate XML takes about 2 minutes per version. To generate a report from the XML files takes about 30s- The
api.xsd
template describes the format of the XML for the APIs, and thecomments.xsd
template describes the format of the XML for the comments. The API template is independent of any related work at Sun, but the intention is to adopt whatever becomes the de facto standard in the future, whilst retaining backward compatibility. To enable validation, set the booleanvalidateXML
in the fileXMLToAPI.java
and recompile.- Comments in the comments XML file do get reordered during regeneration. This is harmless.
Comments can be added to a report by using a text editor to add text to the "user_comments_X_to_Y.xml" file, where "X" and "Y" are the names of the two APIs being compared. This file is automatically regenerated each time the report is generated. If the-d directory
argument is used, the user comments XML file also appears, and is expected, in the named directory.Comments which become unused are moved to the end of the file and placed inside XML comments.
The text which is added can be HTML text if necessary, but if the HTML is incorrect, JDiff may fail to read the comments file and exit. Note that the required HTML is in fact XHTML (differences). Since this HTML is stored in an XML document, single tags without their closing ("slash") element are not permitted. For example, most browsers permit HTML which looks like "<p>Here is some text.", with no closing tag. XML requires that either a closing tag exists ("</p>"), or that the single tag is closed, e.g. "<p/>Here is some text.". HTML p, br and hr tags can be single, due to common usage.
To write comments for a particular removal, addition or change in the JDiff-generated report, edit the comments XML file. Your changes will be automatically incorporated into a new version of this file when the report is next generated. Search the file for the identifier for the particular removal, addition or change, using the package name, class name and member name to find the identifier. Alternatively, look at the HTML source of a report and note the identifier (an HTML named anchor) near the intended place for the comment.
Adding links to comments can be accomplished in two ways: with the {@link} Javadoc tag, or by using HTML links directly.Alternatively, you can use an explicit HTML <a> element. e.g.
- To link to a class, use the package and class name, e.g.
{@link packagename.classname}. - To link to a specific method in a class' HTML page, use the package, class name, a pound sign, and then the method and parameters, or () e.g.
{@link packagename.classname#methodname(params)}. - To link to a specific constructor in a class' HTML page, use the package, class name, a pound sign, and then the classname and parameters, or () e.g.
{@link packagename.classname#classname(params)}. - To link to a specific field in a class' HTML page, use the package, class name, a pound sign, and then the name of the field e.g.
{@link packagename.classname#fieldname}. <a href="packagename.classname.html#methodname">link text<a> . The specific HTML named anchor can be found by looking at the HTML source of a report.
Sometimes you may want to have the same comment text appear in multiple places in the report. You can do this by having multiple <identifier> elements in a single <comment> element. This grouping does not persist after the comments file is regenerated.
The first sentence from a comment in the source code for an element is available in the comments XML file by using the @first tag. This tag will be replaced (once) in the comments in the report by the first sentence from the appropriate Javadoc comment.
The JDiff doclet has been tested with J2SE1.2, J2SE1.3 and J2SE1.4 on Windows NT, 2000, XP and RedHat Linux.
You need to have an XML parser such asxerces.jar
(used for XML parsing) from the Apache project on your classpath. The version tested with was Xerces 1.4.2. The filexerces.jar
is included in this release, or alternatively it can be downloaded from www.apache.org.
To use an XML configuration file for JDiff, you needant.jar
from the Apache project on your classpath. The fileant.jar
is included in this release. ANT is a general-purpose build tool and can be found here.
PROBLEM POSSIBLE SOLUTION No changes are seen in the report. By default, Javadoc and JDiff only show public and protected classes and members.. No changes seen for package and private classes. Enable both the correct Javadoc visibility level (-public, -protected, -package, -private) and the correct JDiff visibility level (-excludeclass, -excludemember). No comments were inserted for packages. You need to use the -sourcepath
argument to locate the source code files, so that JDiff can deduce where thepackage.html
file with comments about the package may be. If nopackage.html
file exists or can be found, then no comments can be suggested for packages. Of course, comments can still be added by hand.JDiff takes a long time to load XML, or throws java.net.NoRouteToHostException: Operation timed out
.The validation portion of loading the XML file currently requires the ability to make an HTTP connection. Check your network and try again, or see the -baseURI
option and the next suggestion.From behind a firewall, JDiff fails to load one of the required XML DTD files. Use the following settings to tell the Java2 VM that you are behind a firewall:
java -DproxySet=true -DproxyHost=PROXYSERVER -DproxyPort=PORT
wherePROXYSERVER
is the hostname or IP address of your proxy server, andPORT
is the port number of the proxy server.
The other alternative is to use the local copies of the required files by using the option-baseURI
when generating the API XML files. For example,-baseURI "file:///C:/jdiff/lib"
would cause the XML parser to use the copies which are shipped in thelib
directory, if JDiff is installed inC:\jdiff
. Note that there are three forward slashes after "file:". The-baseURI
approach has the advantage that it requires no connectivity to the Internet to be able to run JDiff.JDiff fails to handle assert
in J2SE1.4Be sure to use the -source 1.4
argument to Javadoc to handle assertions present in J2SE1.4 source code.The ANT Javadoc task for JDiff fails to find any source files when using J2SE1.3.1 and J2SE1.4 The way Javadoc finds source files, classes and packages changed in J2SE1.4 (and possibly in J2SE1.3.1). See the comments in the example and test build.xml files about using the sourcefiles
attribute with the ANT task rather than thepackagenames
attribute.Using an XML parser other than Xerces Set the org.xml.sax.driver
system property to the name of the XML parser class which you wish to use. Setting a system property is usually done by passingto the JVM. To cause Javadoc to pass an argument to the underlying JVM, use -Dname=value
-J-Dname=value
. To pass an argument to Javadoc from within an ANT Javadoc task, use theadditionalparam
attribute, e.g.additionalparam="-J-Dorg.xml.sax.driver=com.example.my.driver"
Comparing Jar files results in duplicate class changes being reported. Be sure to use the -packagesonly
option when using Jar files as the input to JDiff. You should not need to use-packagesonly
otherwise.Documentation difference page becomes all changes part way through. This problem can occur if incorrect HTML is written in the new documentation. JDiff shows this HTML on the documentation difference page, and can cause entries later on in the page to be displayed incorrectly. One solution is to edit the documentation difference page by hand, but the better solution is to fix the offending HTML in the new source code.
The background color of my HTML report is not correct. Check that the file background.gif
from thelib
is in the same directory as thechanges.html
file.The names of exceptions are too long in the HTML report. To use short names for exceptions, set the showExceptionTypes
boolean tofalse
inXMLToAPI.java
file and recompile.
The warnings and error messages which can be generated by JDiff are as follows:
ERROR MESSAGE POSSIBLE CAUSE Error: unknown element type. The XML file contains an element tag which the current version of JDiff cannot recognize. This may occur if an older version of JDiff is used with XML files generated by a newer version. Error: IO Error while attempting to create X. Java was unable to open a file for writing. May occur if the user does not have write permission for the current directory. Error: no identifier found in the comments XML file. The XML file for the comments for the report must contain an identifier to indicate which report of differing APIs these comments are written for. Error: unknown program element type. Internal JDiff error. Error: could not create the subdirectory X. Java was unable to create a directory. May occur if the user does not have write or execute permission for the current directory. Error: file X does not exist for the [old|new] API. The XML files corresponding to the names given to -oldapi
and-newapi
are not in the current directory. This may be because the XML files have not yet been generated, or were generated elsewhere.
It can also occur if the XML file was generated with one API identifier, and is now being read in with another identifier. Either use the same identifier, or change the <api> name element value in the XML file to the new API identifier.Error: no API identifier found in the XML file X. The given XML file does not have an identifier in it, probably due to manual modification. Error: no packages found in the APIs. JDiff was unable to find any packages in the arguments given to Javadoc.
WARNING MESSAGE POSSIBLE CAUSE Warning: illegal string found in text. Ignoring the comment. The suggested comments from Javadoc are stored in XML files in a CDATA element, which permits every string except . Warning: no difference between the APIs. There was no difference between the APIs. You are probably comparing two identical XML files. Warning: no classes found in the package X. A package without classes was encountered. Warning: change from deprecated to undeprecated for class X. A class changed from being deprecated to being undeprecated in the next release. This is usually either poor software design or a misplaced @deprecated Javadoc tag. Warning: change from deprecated to undeprecated for a constructor in class X. A constructor changed from being deprecated to being undeprecated in the next release. This is usually either poor software design or a misplaced @deprecated Javadoc tag. Warning: change from deprecated to undeprecated for method X. A method changed from being deprecated to being undeprecated in the next release. This is usually either poor software design or a misplaced @deprecated Javadoc tag. Warning: text of comment does not end in a period. Generated when the -checkcomments
is used. The suggested comment does not end in a period, question mark or exclamation mark.Warning: N identical ids in the existing comments file. Using the first instance. The comments file contains comment for multiple places in the report, but N of the identifiers for the comment are non-unique. Warning: incorrectly formatted @link in text. JDiff was unable to parse the @link in the suggested comment. Warning: comment com.acme.sp is no longer used. The comment in the comments file intended for the given element is no longer needed, since the element is no longer part of the changes between the APIs. The comment will be moved to the end of the comments file and preserved, but not used. Warning: API identifier in the comments XML file differs from the name of the file. The comments file keeps track of which APIs it is to be used for, and has detected a mismatch with the names of the current APIs. Warning: multiple @deprecated tags found in comments for X. Using the first one only. A comment with more than one @deprecated tag was encountered in the source code. This is considered poor Javadoc style. Warning: @ tag seen in comment. An @ tag other than @link has somehow made its way into a suggested comment. This should not occur, but can be remedied by editing the comments file to use a different comment. Warning: duplicate class : X found. Using the first instance only. Multiple instances of the same fully qualified class name were found in the API XML file. Most likely caused by manual modification of the file after it was generated. Warning: missing @since tag A class, constructor, method or field was added in the later API but no @since tag was found in the Javadoc comment. This information is logged into a file missingSinces.txt
in the same directory aschanges.html
. This file is informational only. The boolean to control this behaviour is in the source fileHTMLIndexes.java
.Warning: API identifier in the XML file X differs from the name of the file Y. The name given to -apiname
when the XML file is generated is embedded in the XML file as a top-level attribute. This warning suggests that the XML file has been modified by hand, but that report generation should proceed using the new API identifier.
During the generation of a report, JDiff also reports a percentage difference between the two APIs being compared, e.g. "Approximately 10% difference between the APIs". This statistic is calculated in the following way:Percentage change = 100 * (added + removed + 2*changed) ----------------------------------- sum of public elements in BOTH APIsSo if there are 15 packages in the old API, and 2 of these are removed, and 17 packages in the new API, 1 of which is newly added, and only 3 of which have changed, then the simple percentage difference would be:100 * (1 + 2 + 2*3)/ (15 + 17) = 28%A change of 100% means that there are no packages in common between the two APIs. A change of 0% indicates that nothing changed between the two APIs. This formula is applied recursively in JDiff for classes and their members. That is, the value for the number of packages changed is not an integer, but instead is the value obtained by applying the same formula to the all the classes in the changed packages, and then to all the members of the changed classes. This results in a lower, but more accurate, percentage difference. The percentage difference value does not appear anywhere in the HTML report files generated by JDiff. The test suite for JDiff v1.0 had a difference value of approximately 63%. A real-world value is the value for the differences between J2SE1.2 and J2SE1.3, which is approximately 8%.
- While Java is highly backward compatible, so that, for example, the XML for a J2SE1.2 application can be generated using JDiff with J2SE1.3, there are a few cases where classes will appear in the XML of the API which are not present in the source code. These classes appear to be inserted by
javac
orjavadoc
. An example of this is the classjava.awt.Robot
, which is inserted into the XML for J2SE1.2 ifjavadoc
in J2SE1.3 is used, but not does not appear in the XML ifjavadoc
in J2SE1.2 is used.
To avoid these (rare) cases, it is recommended that you use the same version of the J2SE that the application was written for.- JDiff does not tell you how two Javadoc web pages differ in layout, though it can tell you how the content has changed. Nor does it compare what the methods in an API do; if JDiff could tell you what had changed about the way two versions of an API execute, the Halting Problem would be solved, and our lives would be very different.
- Java Developer's Journal , April 2002 contained an article about JDiff. The article can also be found here.
- Javadoc Tool homepage for information about using Javadoc to document APIs.
- Doclet documentation from Sun.
- The Doclet API for details on the doclet API.
- Third-party doclets as listed by Sun.
- Third-party doclets as listed by others.
Copyright © 2001-2004 Matthew B. Doar
JDiff Doclet, v1.0.10.