The javac documentation describes the
-Xprint
option: "Print out textual representation of specified types for debugging purposes; perform neither annotation processing nor compilation. The format of the output may change."The output of
-Xprint
on a .class
file looks very similar to javap's output. For example, javac -Xprint
shows the following output when run against java.lang.Object:javac -Xprint java.lang.Object
package java.lang; public class Object { public Object(); private static native void registerNatives(); public final native java.lang.Class getClass(); public native int hashCode(); public boolean equals(java.lang.Object arg0); protected native java.lang.Object clone() throws java.lang.CloneNotSupportedException; public java.lang.String toString(); public final native void notify(); public final native void notifyAll(); public final native void wait(long arg0) throws java.lang.InterruptedException; public final void wait(long arg0, int arg1) throws java.lang.InterruptedException; public final void wait() throws java.lang.InterruptedException; protected void finalize() throws java.lang.Throwable; }
Compare the above output from
javac -Xprint
on java.lang.Object to the output (shown next) of running javap
against java.lang.Object
:Compiled from "Object.java" public class java.lang.Object{ public java.lang.Object(); public final native java.lang.Class getClass(); public native int hashCode(); public boolean equals(java.lang.Object); protected native java.lang.Object clone() throws java.lang.CloneNotSupportedException; public java.lang.String toString(); public final native void notify(); public final native void notifyAll(); public final native void wait(long) throws java.lang.InterruptedException; public final void wait(long, int) throws java.lang.InterruptedException; public final void wait() throws java.lang.InterruptedException; protected void finalize() throws java.lang.Throwable; static {}; }
Of course, the output above is shown with javap's default settings. The private and protected members can be displayed using
javap
's -private
and -protected
options.One advantage of
javac -Xprint
, however, is that the -Xprint
option can be easily used with javac
if one wants to see the interface for multiple files. The javac
compiler can be used as normal against the normal source code files, but with the -Xprint
option specified, the interfaces will be printed out without actually compiling the code. This is demonstrated here. I add the -Xprint
option to my javac
compiler when compiling the examples from my last blog post on javac -Xlint and get the following output:package dustin.examples; /** * Simple class intended to help demonstrate -Xlint:overrides by providing a * method that won't be overridden quite the same by its child. */ public class BaseClass { protected java.util.List<java.lang.String> names; public BaseClass(); public void addNames(final java.lang.String[] newNames); } package dustin.examples; /** * Simple class intended to help demonstrate -Xlint:overrides by "sort of" * overriding a method defined in its parent. */ public class ChildClass extends dustin.examples.BaseClass { public ChildClass(); @java.lang.Override public void addNames(final java.lang.String... newNames); } package dustin.examples; /** * Simple Color representation. */ public enum Color { BLACK, BLUE, BROWN, CORAL, EGGSHELL, GREEN, MAUVE, ORANGE, PINK, PURPLE, RED, TAN, WHITE, YELLOW; public static dustin.examples.Color[] values(); public static dustin.examples.Color valueOf(java.lang.String name); private Color(); } package dustin.examples; /** * Gender. */ public enum Gender { FEMALE, MALE; public static dustin.examples.Gender[] values(); public static dustin.examples.Gender valueOf(java.lang.String name); private Gender(); } package dustin.examples; /** * Main executable demonstrating HotSpot's non-standard Xlint warning flags. */ public class Main { public Main(); /** *Fred. */ private static final dustin.examples.Person fred; /** *Wilma. */ private static final dustin.examples.Person wilma; /** *Barney. */ private static final dustin.examples.Person barney; /** * Demonstrates -Xlint:cast warning of a redundant cast. */ private static void demonstrateCastWarning(); /** * Cause -Xlint:deprecation to print warning about use of deprecated method. */ private static void demonstrateDeprecationWarning(); /** * Cause -Xlint:fallthrough to print warning about use of switch/case * fallthrough. */ private static void demonstrateFallthroughWarning(); /** * Demonstrate -Xlint:finally generating warning message when a {@code finally} * block cannot end normally. */ private static void demonstrateFinallyWarning(); /** * Divide the provided divisor into the provided dividend and return the * resulting quotient. No checks are made to ensure that divisor is not zero. * @param dividend Integer to be divided. * @param divisor Integer by which dividend will be divided. * @return Quotient of division of dividend by divisor. */ private static double divideIntegersForDoubleQuotient(final int dividend, final int divisor); /** * Demonstrate -Xlint:divzero in action by dividing an int by a literal zero. */ private static void demonstrateDivideByZeroWarning(); /** * Surprisingly, there is no -Xlint warning option for this highly * suspicious situation of passing an object to a Set.contains call that * could not possibly hold that type of object (could never result to true). */ private static void demonstrateNoContainsWarning(); /** * This method demonstrates how javac's -Xlint:empty works. Note that javac's * -Xlint:empty will only flag the empty statement involved in the "if" block, * but does not flag the empty statements associated with the do-while loop, * the while loop, the for loop, or the if-else. NetBeans does flag these if * the appropriate "Hints" are turned on. */ private static void demonstrateEmptyWarning(); /** * Divide the provided divisor into the provided dividend and return the * resulting quotient. No checks are made to ensure that divisor is not zero. * @param dividend Integer to be divided. * @return Quotient of division of dividend by divisor. */ private static long divideIntegerByZeroForLongQuotient(final int dividend); /** * Demonstrate the commonly seen -Xlint:unchecked in action. * @return Set of Person objects. */ private static java.util.Set<dustin.examples.Person> demonstrateUncheckedWarning(); /** * Main executable function to demonstrate -Xlint. Various -Xlint options * are demonstrated as follows: * <ul> * <li>{@code -Xlint:cast}</li>: This class's method demonstrateCastWarning() * demonstrates how a redundant cast can lead to this warning.</li> * <li>{@code -Xlint:deprecation}: This class's method demonstrateDeprecationWarning() * intentionally invokes a deprecated method in the Person class.</li> * <li>{@code -Xlint:divzero}: This class's demonstrateDivideByZeroWarning() * method demonstrates this warning generated when a literal zero is * used as a divisor in integer division.</li> * <li>{@code -Xlint:empty}: This class's demonstateEmptyWarning() method * demonstrates that (likely accidental) "if" expression without any * result of the condition being {@code true} being performed results in * a warning this option's set. * <li>{@code -Xlint:fallthrough}: This class's method demonstrateFallthroughWarning() * demonstrates how {@code switch} statements with {@code case} expressions * without their own {@code break} statements may or may not lead to * this producing a warning message.</li> * <li>{@code -Xlint:finally}: This class's method demonstrateFinallyWarning() * demonstrates the warning related to a return from a {@code finally} * clause.</li> * <li>{@code -Xlint:overrides}: This is demonstrated in classes external to * this one: {@code BaseClass} and its child class @{code ChildClass}.</li> * <li>{@code -Xlint:path}: This is shown by providing a path to the javac * compiler's classpath option for a location that does not exist.</li> * <li>{@code -Xlint:serial}: The Person class implements the Serializable * interface, but does not declare an explicit serialVersionUID.</li> * <li>{@code -Xlint:unchecked}: This class's demonstrateUncheckedWarning() * demonstrates this warning message.</li> * </ul> * @param arguments Command-line arguments: none expected. */ public static void main(final java.lang.String[] arguments); } package dustin.examples; /** * Person class that intentionally has problems that will be flagged as warnings * by javac with -X non-standard options. */ public final class Person implements java.io.Serializable { private final java.lang.String lastName; private final java.lang.String firstName; private final dustin.examples.Gender gender; private final dustin.examples.Color favoriteColor; public Person(final java.lang.String newLastName, final java.lang.String newFirstName, final dustin.examples.Gender newGender, final dustin.examples.Color newFavoriteColor); public java.lang.String getLastName(); public java.lang.String getFirstName(); public java.lang.String getFullName(); /** * Provide the person's full name. * @return Full name of this person. * @deprecated Use getFullName() instead. */ @java.lang.Deprecated public java.lang.String getName(); public dustin.examples.Gender getGender(); public dustin.examples.Color getFavoriteColor(); /** * NetBeans-generated equals(Object) method checks for equality of provided * object to me. * @param obj Object to be compared to me for equality. * @return {@code true} if the provided object and I are considered equal. */ @java.lang.Override public boolean equals(java.lang.Object obj); /** * NetBeans-generated hashCode() method. * @return Hash code for this instance. */ @java.lang.Override public int hashCode(); @java.lang.Override public java.lang.String toString(); }
The output of my own classes shown above is a reminder of another nicety of
javac -Xprint
: it includes the Javadoc comments of the members and methods that it prints out when source code is available. This can be helpful in understanding what the parameters of the API methods are. If javac -Xprint
is run directly against a .class
file, it does not include the Javadoc comments; if it's run against the .java
source file, it does include the Javadoc comments.For example, if I change my directory to the installation directory of the Spring Framework, I can use the command
javac -Xprint src\org\springframework\core\Constants.java
to see the org.springframework.core.Constants
class members and methods with accompanying Javadoc comments. Alternatively, I could run javac -Xprint
against the compiled .class
file as well (but won't see the Javadoc comments in that output) with the command javac -cp dist\spring.jar -Xprint org.springframework.core.Constants
It is nice to be able to run
javac -Xprint
against compiled binaries (.class
) or raw source (.java
).Another interesting facet of the
javac -Xprint
is that it demonstrates what annotation processors can do in Java SE 6.I usually use an IDE and the online Javadoc-based API documentation to learn new APIs or remind myself of the specifics of APIs I don't use frequently. However, every once in a while, I find it useful to be aware of the existence of
javap
and of javac -Xprint
for providing a quick reminder of the available APIs on my own classes and on third-party classes.
No comments:
Post a Comment