Tuesday, February 17, 2009

Day-to-Day Java Development Tools and Techniques

There are some common things that are useful to know in many day-to-day Java development activities. It is especially helpful for someone new to Java development to know where to find this information, but I have found bookmarking these sources to be useful even as I have gained experience developing Java applications. Because one of the primary purposes for me writing a blog is to provide myself with an easy way to find things I am looking for, I am using this blog posting to collect some of these sources of information that I frequently use for Java development in one place. Because these items are related to the development of Java applications rather than to source code, it is not surprising that many of the items are specific to the JVM I am using.


Java Processes: jps

There are many times in Java development when it is important to know which Java processes are running. More specifically, I find myself needing the process ID of Java applications for running other tools against those processes or for terminating processes. There are several Sun JDK development tools, but one of my favorites is the jps tool (JVM Process Status Tool). This "experimental" tool lists the Java processes running on the target HotSpot JVM. As I previously blogged, my favorite use of this tool is jps -lm.


JVM Arguments

Java Application Launcher

The environment a Java application runs in can be significantly tweaked via the use of JVM arguments. In addition, JVM arguments allow for different levels of monitoring and analysis of the executing Java application. The command java -help lists the standard options (standard across different JVM implementations) for the Java application launcher. The command java -X can be used to see the Java application launcher's non-standard (X for extension specific to that JVM) arguments. In the HotSpot JVM, some frequently used extension arguments are -Xms and -Xmx for initial Java heap size and maximum Java heap size respectively.

The -Xbootclasspath option can be used to either prepend (/p) or append (/a) resources to the bootstrap classpath.

If you wish to detect which JVM arguments your currently running Java application is using, you can use the ManagementFactory.getRuntimeMXBean().getInputArguments() call as described in Accessing JVM Arguments from Java. This technique takes advantage of Platform MXBeans available since J2SE 5 (custom MXBeans support was added in Java SE 6).

Two useful sources of information on the JVM parameters available when using Sun's JVM are A Collection of JVM Options and Charles Nutter's Favorite Hotspot JVM Flags. Both of these resources list and describe some/all of the not-recommended-for-the-casual-developer double X arguments (-XX) that are available.

Java Compiler

The javac Java compiler also has command-line arguments that can be of great use. Like the java application launcher, the javac compiler that comes with the Sun Java SDK includes both standard options and non-standard/extension options. These options are displayed in a manner consistent with that used for the application launcher. Non-standard options include bootstrap classpath append and prepend options, setting of endorsed standards path, setting of directory of installed extensions, and enabling and disabling of specific warnings (-Xlint options including -Xlint:path).


Warnings

-Xlint

The warnings reported by the Java compiler can be very useful in identifying things that either may be larger current problems than one realizes or could easily turn into more significant problems. Sun's javac compiler allows one to take relatively granular control of which warnings are enabled and disabled using -Xlint (all warnings are reported when this is used by itself). Specific warnings can be reported by providing the type of warning after the -Xlint: notation. If no reports of warnings are desired (other than those the Java Language Specification requires), the notation -Xlint:none is used.

@SuppressWarnings

One can use the @SuppressWarnings annotation introduced with J2SE 5 to mark in code the warnings that should not be reported when the code is compiled. However, a natural question is which specific warnings can be suppressed in-code using this annotation. It turns out that this is compiler-specific. For Sun's compiler, the available warnings that can be suppressed with @SuppressWarnings are listed here and here.


Java Classpath Issues

Classpath Basics

The Java classpath can be one of the most confusing things for a new Java developer. The classpath can become a complicated mess even for experienced developers when different issues arise due to different classloader behaviors, the presence of slightly different versions of libraries on the classpath, and incorrectly typed classpaths. Fortunately, there are several tools to help understand and better work with the classpath.

For those just learning Java and Java classpaths, a good starting point is to read Elliotte Rusty Harold's articles Managing the Java Classpath (Windows) and Managing the Java Classpath (Unix). These articles provide a good overview of the options one has for setting a classpath, why dynamically setting the classpath is preferred over using an environment variable, and provides the basics of how classpaths work with Java packages.

Because the Sun Java compiler will ignore an entry on the classpath that it cannot resolve, it is easy to think that one has correctly typed in a classpath entry even if it is incorrectly typed. The -Xlint:path extension option instructs the Java compiler to report any classpath entries that cannot be resolved.

The JARs, .class files, and other resources specified on a command-line classpath using -classpath or -cp are typically not the only resources on an application's classpath. Other sources of classpath information that must be considered include the standard Java classpath (for standard Java classes), jre/lib/ext, and jre/lib/endorsed (uses bootstrap classpath). In addition classpaths may be different when using an IDE and are different when using web servers and application servers (classpath is typically determined by the contents of the WAR file and EAR file in those cases).

ClassNotFoundException Versus NoClassDefFoundError

One thing that can be a little tricky when first learning Java is distinguishing between the ClassNotFoundException and the NoClassDefFoundError. The Javadoc API documentation for each of these explains their use and why they might occur. In most cases, the easy way to differentiate between the two is that the ClassNotFoundException indicates that a class needed for compilation cannot be found on the classpath and a NoClassDefFoundError indicates that the matching class that was found at compile time cannot be found at runtime. This differentiation between compile time and run time can be useful in figuring out when the classpath entry is missing.

It is also interesting to note that while ClassNotFoundException is a checked exception extending Exception directly, NoClassDefFoundError is actually an Error rather than an Exception. Note that ClassNotFoundException can actually be encountered during runtime in a variety of situations such as the runtime on-the-fly compilation of JavaServer Pages, reflection, and, as the API states, "when an application tries to load in a class through its string name." Generally speaking, the causes of NoClassDefFoundError are more diverse and difficult to resolve than those of ClassNotFoundException.

Some interesting and in-depth articles on class loading are available in the Demystifying Class Loading Problems series. Other references regarding the difference between these two exceptions are available at Difference Between ClassNotFoundException and NoClassDefFoundError, What is the Difference Between ClassNotFoundException and NoClassDefFoundError?, Java Fanatics: NoClassDefFoundError versus ClassNotFoundException, and ClassNotFoundException and NoClassDefFoundError.

UPDATE (2 March 2009): Identifying an Instance's Original Classpath Definition

UPDATE (2 March 2009): This subheading and entire paragraph have been added since the original post. Some of the NoClassDefFoundErrors one might run into can be traced to multiple definitions of the same class on the classpath with slight differences. One way to see which class definition a loaded class is using is described in another blog post of mine.



System Properties

Java provides some standard properties that can be used for several different benefits. An often used property from this set include line.separator for a platform-independent reference to a new line. It is not easy to remember all of the available system properties, especially those that are not used often. Fortunately, several resources either list these or provide code examples of how to see a list of them. For example, Java Standard System Properties lists them, How to Print All the Java System Properties demonstrates how to programmatically list them, and Java: System Properties both demonstrates how to get the properties via code and lists them. The Javadoc-based API documentation for System.getProperties() lists the system properties that are always available. I've even been known to blog on properties before.

The Platform MXBean RuntimeMXBean provides a RuntimeMXBean.getSystemProperties() method that can be used to see the system properties as well.


View Swing GUI's Hierarchy with CTRL-SHIFT-F1

A nifty trick with Swing-based applications is the ability to use CTRL-SHIFT-F1 to see the Swing GUI's hierarchy. This is further demonstrated and explained in the Tech Tip Ctrl-Shift-F1 in Swing Applications.


serialver

The command-line serialver tool is useful for generating servialVersionUID attributes on classes that implement the Serializable interface. I have blogged previously on the serialver tool.


jar Tool and JAR Files

jar Tool

With the prevalence of IDEs and Ant and Maven for building Java code, it is easy to forget about the jar command. However, knowledge of the jar command can be useful for writing and running simple tests and examples. One of jar's characteristics that makes it most useful is the fact that it uses the ZIP compression format and uses similar syntax to the tar command. The versatile jar command can even be used to display the contents of an Adobe AIR .air file.

Executable JAR Files

JAR files can be made executable so that they can be run with a command line java -jar someJar.jar without the need to specify classpath information or the main executable class in the JAR. The classpath and the main class to execute do not need to be explicitly stated because they are embedded in the executable JAR's manifest file with the Class-Path and Main-Class name/value pairs respectively. There are a few details to be aware of when using executable JARs (such as specifying the class path entries via directories relative to the location of the executable JAR file) and these details are covered in the blog posting Executable Jar File in Java.

JAR Manifest File Information

You can place essentially any name/value pair in a manifest file on its own line. While virtually any names and values can be used, there are some standard and accepted manifest name/value pairs one might wish to use. These include Class-Path, Main-Class, package version information (Specification-Title, Specification-Version, Specification-Vendor, and implementation equivalents). The Manifest file is also used to seal packages in JAR files. See also the Wikipedia entry on Manifest File for more details.


JVM JMX Instrumentation

The JVM itself has been instrumented with Java Management Extensions (JMX) support since J2SE 5. This provides valuable information regarding the JVM and applications running in the JVM. Sun provides JConsole (since J2SE 5) and VisualVM (since Java SE 6 Update 7) with their SDK for easy developer monitoring of the JVM and its deployed applications.

Platform MXBeans have been provided with the Sun JVM since J2SE 5 and provide a wide variety of details regarding the JVM. Platform MXBeans provide information on JVM topics such as thread contention, operating system details, memory analysis, and logging management. As described earlier, the RuntimeMXBean provides interesting information such as the classpath in effect, the boot classpath, system properties, and JVM vendor and specification details. The available Platform MXBeans are described in greater detail in Using the Platform MBean Server and Platform MXBeans.

Java EE application servers also provide information via JMX.


UPDATE (18 February 2009) Generating a Stack Trace

UPDATE (18 February 2009) Eyal Lupu reminded me (see feedback) of a very handy tool during debugging (especially when processes are hanging). Forced generation of a stack trace with a SIGQUIT, CTRL+\, or CTRL-BREAK (Windows) is described in greater detail in An Introduction to Java Stack Traces.


Documentation

Some of the Java documentation resources that I use most often include the overall JDK 6 Documentation (includes links to many of the other documents referenced in this blog posting), the Java SE 6 API documentation, the Java EE 5 API documentation, and specialized documentation such as the Spring Reference Manual and the Oracle Technology Network JPA Annotations Reference. Perhaps my favorite tool for finding useful documentation is the Google search engine.

2 comments:

Eyal Lupu said...

Hi,
Nice post I have just one comment:
I would mention another important tool: kill -3 (SIGQUIT) , or in windows ctrl+break. When sending this signal to a JVM (or hitting ctrl+break in a window which executes a JVM) it will dump all of its tread stack traces and memory statistics.

Eyal Lupu (my blog)

@DustinMarx said...

Eyal Lupu,

Thanks for the feedback and that very useful tip. That is an excellent tip that fits nicely with the intent of this blog post. In fact, I wish I had included it in the beginning (I knew I was missing some that I could not think of).

Dustin