Wednesday, May 17, 2017

Kotlin and Android: JetBrains and Google Behind One Language

Google I/O 2017 had several major announcements, but one of the most interesting to me is "first-class support for Kotlin" on Android.

The Kotlin blog post on this announcement discusses the benefits this brings to Kotlin users:

In case you are concerned about other platforms that Kotlin supports (Kotlin/JVM for server and desktop, Kotlin/JS and Kotlin/Native), please be sure that they are as important for us as ever. Our vision here is to make Kotlin a uniform tool for end-to-end development of various applications bridging multiple platforms with the same language. ... First-class support on Android will likely bring more users to Kotlin, and we expect the community to grow significantly. This means more libraries and tools developed in/for Kotlin, more experience shared, more Kotlin job offerings, more learning materials published, and so on. We are excited to see the Kotlin ecosystem flourish!

An interesting point related to and included in this announcement is mentioned in the Kotlin on Android FAQ:

What's the future of Kotlin? JetBrains' thoughtful work on Kotlin's design is one of the reasons we're embracing the language. Google is partnering with JetBrains to ensure a wonderful overall developer story—from language, to framework, to tools. And, we are excited to be working together to move the Kotlin language into a non profit foundation.

The Kotlin blog post describes the future of Kotlin with Android in greater detail:

We will be partnering with Google to create a non-profit foundation for Kotlin. Language development will continue to be sponsored by JetBrains, and the Kotlin team (over 40 people and second largest team at the company) will operate as usual. Andrey Breslav remains the Lead Language Designer, and Kotlin will be developed under the same principles as before.

Android 3.0 Canary 1 (preview) can currently be downloaded at https://developer.android.com/studio/preview/index.html at includes Kotlin support among its new features that include Java 8 support.

In the 2016 edition of my annual post on significant software developments of the year, I listed Kotlin-related developments in the "Honorable Mention" section. With this announcement of Kotlin being officially supported on Android and the language being placed in nonprofit foundation and enjoying support of Google and JetBrains, I think it's very possible that Kotlin will make my top ten list in 2017 for significant software language development developments. Besides these announcements, Kotlin has already seen JavaScript support released in Kotlin 1.1 in 2017 and a preview of Kotlin/Native.

Monday, May 15, 2017

JVM Statistics with jstat

I have written about several command-line tools provided with the Oracle and/or OpenJDK Java Development Kits (JDKs) in the past, but I've never written exclusively about the jstat tool. The Oracle JDK 9 Documentation Early Access states that jstat is used "to monitor Java Virtual Machine (JVM) statistics." There is also a warning, "This command is experimental and unsupported." Although I quoted the JDK 9 documentation, jstat has been a part of the Sun/Oracle JDK in some form (known at one time as jvmstat) in Java SE 8, Java SE 7, Java SE 6, and J2SE 5. Instrumentation for the HotSpot JVM was introduced with Java 1.4.1 (only enabled when -XX:+UsePerfData was set) and has provided "always-on instrumentation" since Java 1.4.2.

Much of the information that jstat provides can be gleaned from visual tools such as VisualVM, JMX and platform MBeans, garbage collection logs or via JVM options. However, jstat provides advantages when compared to each of these alternatives. Its advantages include those common to command-line tools such as the ability to execute from scripts and run without need of developers or others being present. It also is useful to be able to apply jstat to an already running Java process to start monitoring its JVM statistics rather than having the specify the monitoring of those options when starting the JVM.

For my examples in this post, I am using Oracle JDK 9 build 164. The next screen snapshot shows this version and also shows one of the first flags to apply when starting to use jstat: the -options flag.

As demonstrated in the screen snapshot, and as stated in the jstat documentation, jstat -options is used to "display the list of options for a particular platform installation." In my example being shown here, the following options are available:

  • -class
  • -compiler
  • -gc
  • -gccapacity
  • -gccause
  • -gcmetacapacity
  • -gcnew
  • -gcnewcapacity
  • -gcold
  • -gcoldcapacity
  • -gcutil
  • -printcompilation

I'll only be looking at a small subset of these available options in this post, but the jstat documentation provides a single sentence describing each jstat option and the command-line use of each option is very similar to all other options. In fact, once one learns a few minor things regarding use of jstat, the execution of various options becomes the easy part. The difficult part of using jstat is often interpreting the data provided by jstat.

The jstat -help option prints a simple usage as shown in the next screen snapshot.

From the jstat usage message, we learn that the jstat command-line tool is executed by running the name of the command first (jstat) with the hyphenated option name next, followed by the optional -t and/or -h flags, followed by a vimid, and concluding with an optional interval and optional count of the number of times to execute the command on the provided interval. Examples are clearer than descriptive text and some examples are shown in this post and in the jstat documentation.

For monitoring "local" JVM statistics, the vmid is simply the process ID of the JVM process. This is the same PID returned by the hip jcmd (or stodgy jps) for Java processes. The next screen snapshot demonstrates use of jcmd to identify the PID (8728 in this case) of the Java application I'm monitoring in my examples (JEdit in this case).

The "Virtual Machine Identifier" section of the jstat documentation provides significantly more details regarding the vmid because a more complicated vmid (for remote monitoring of JVM statistics) can include a protocol, the local targeted machine's vmid, host, and port. Although all of my examples in this post will use jstat and a simple Java PID (vmid), the jstat documentation does provide examples of use of a more detailed vmid for remote monitoring of JVM statistics.

For the remaining examples in this post, I wanted a Java application that was a bit more interesting from a JVM statistics monitoring perspective than JEdit is. I decided to use the "PigInThePython" sample application from Nikita Salnikov-Tarnovski's post "Garbage Collection: increasing the throughput" on the highly recommended Plumbr Blog. See that post if you're interested in seeing the source code for PigInThePython.

For my first example of using jstat, I use one of its most commonly used options: -gcutil. Besides demonstrating the -gcutil option, I'll use this first example to also demonstrate and explain the jstat output options that generally apply to other jstat options besides gcutil.

The following screen snapshot demonstrates use of jcmd to acquire the PID of the PigInThePython application (5096 in this case) and running of the simplest form of jstat -gcutil.

In its simplest form (with no other options), jstat -gcutil displays a single line of output with no timestamp. The column headings are described in the jstat documentation section "-gcutil option" which also describes the -gcutil option as, "Summary of garbage collection statistics." This documentation explains, for example, that several of the columns indicate percentages of usage of different spaces' allocations while other columns indicate number of garbage collection events and total garbage collection time.

We often want to associate the statistics that jstat provides with the time that other events are occurring in the monitored system to identify correlations between those events and effects on the JVM. The jstat -t option will prepend a timestamp at the beginning of the output. This timestamp is the number of seconds since the JVM that is being monitored was started. Although this is not as convenient for humans to read as other formats, it does make it possible to correlate the JVM statistics with timeframes in which the JVM has been running and with garbage collection logs that had time stamps included. The next screen snapshot demonstrates -t in action:

It is typically useful to monitor JVM statistics such as those presented by jstat -gcutil more than once. The next screen snapshot demonstrates use of a specified interval (100 milliseconds intervals as specified with 100ms to have these results captured and shown every 100 milliseconds.

The output in the last screen snapshot never repeats the header with the column acronyms after showing it the first time. If one wants to have that header repeated after a certain number of lines to make it easier to know which numbers belong with which columns much farther down in the output, the -h option can be used to specify the number of results after which the column headers are displayed again. In the next screen snapshot, -h20 is used to see the header after every 20 rows.

There may be times when it's desirable to have jstat provide its data every so often and only for a certain number of times. The interval allows one to specify the duration of time between the results and any integer following that interval specification acts as the limit on the total number of times the results will be displayed. In the next screen snapshot, the 15 at the end of the command limits the output to 15 total rows.

The jstat -gccause option returns the same information as -gcutil, but also adds information about what caused the monitored garbage collections. The following screen snapshot demonstrates this.

In the above screen snapshot, we see that the "cause of last garbage collection" (LGCC) was "G1 Humongous Allocation" and that "cause of current garbage collection" (GCC) is "No GC" (there is no garbage collection currently underway).

The next screen snapshot demonstrates use of jstat -class to see "Class loader statistics" number of classes loaded ("Loaded"), number of kilobytes loaded (first "Bytes"), number of classes unloaded ("Unloaded"), and number of kilobytes unloaded (second "Bytes"), and "time spent performing class loading and unloading operations" ("Time").

The command jstat -printcompilation indicates "Java HotSpot VM compiler method statistics" and is demonstrated in the next screen snapshot.

The -printcompilation option displays columns "Compiled" ("Number of compilation tasks performed by the most recently compiled method"), "Size" ("Number of bytes of byte code of the most recently compiled method"), "Type" ("Compilation type of the most recently compiled method"), and "Method" (name of class/method of most recently compiled method expressed in format consistent with HotSpot VM option -XX:+PrintCompilation).

The jstat -compiler command allows us to see "Java HotSpot VM Just-in-Time compiler statistics" such as number of compilation tasks performed ("Compiled"), number of failed compilation tasks ("Failed"), number of invalidated compilation tasks ("Invalid"), time spent on compilation ("Time"), type and class/method name of last failed compilation ("FailedType" and "FailedMethod"). This is demonstrated in the next screen snapshot.

There are several more options available with jstat and most of them are specific to different perspectives on garbage collection in the monitored JVM.

The jstat documentation warns that the tool is experimental and subject to change or removal in future versions of the JDK. The documentation also warns against writing scripts and tools that parse the output of jstat as the output content or format might change in the future. However, I can see how some might take the risk and write parsing code because this command-line tool is easily accessible from scripts and the parsing code needed would not be very complex.

This post has been an introduction to jstat, but there is much more to learn about the tool. Interpretation of the tool's results is more complex than using the tool and the analysis of the data provided by jstat is likely to be more challenging than the effort to collect the numbers. Several additional resources are listed below to provide more information on the collecting of and analyzing of Java Virtual Machine statistics with the jstat tool.

Additional jstat Resources

Wednesday, May 10, 2017

Java Platform Module System Public Review Fails to Pass

There has been an unusual level of drama, intrigue, and politics in the world of Java over the past few weeks that culminated in this week's JSR 376 Java Platform Module System Public Review Ballot. Java modularity [including the Java Platform Module System (JPMS)] has been arguably the most significant piece of JDK 9 and so it's not surprising that it has received so much attention. In addition to the typical publicly available mailing list traffic, there have been blog posts and open letters to further advertise the contention and debate surrounding JPMS (JSR 376), described as "a central component of Project Jigsaw."

The final vote was, according to the JSR #376 Java Platform Module System Public Review Ballot page, 10 votes for and 13 votes against, so "the EC has not approved this ballot." The comments that go along with the votes in the text area at the bottom of the ballot page are telling. In particular, I thought it interesting how many reviewers vote no mainly because they were uncomfortable with the other, more vocal reviewers not approving. It's also interesting that the Public Review Ballot for JSR #379 Java SE 9 Release Contents (an "umbrella" JSR) passed overwhelmingly on the same day this one failed.

It will be interesting to see how this continues to unfold over the coming days and weeks and what impact is has on the release date for JDK 9. Rather than rehash the arguments on both sides, I reference posts from key contributors to the discussion below.

References: Executive Committee Participants/Representatives

References: Opinions/Forums

References: Other Overviews

References: Since the Vote

Monday, May 8, 2017

Java's Observer and Observable are Deprecated in JDK 9

In the blog post Applying JDK 9 @Deprecated Enhancements, I discussed additions of the optional elements (methods) forRemoval() and since() to the @Deprecated annotation in JDK 9. I stated in that post, "The application of new JDK 9 @Deprecated methods on the Java SE API can also be instructive in how they are intended to be used." In this post, I look at the application of the enhanced @Deprecated annotation to the JDK class java.util.Observable.

The class java.util.Observable has been with us almost since the beginning (since Java 1.0). As of JDK 9, however, it will be marked as deprecated. The following screen snapshot shows a portion of this class's Javadoc representation in a web browser.

This is an example of a class that in the category "Deprecated With No Plans for Removal" described in my previous post. The presence of since() provides information on when it was deprecated (JDK 9) and the absence of forRemoval() indicates lack of concrete plans to actually remove the class. The java.util.Observer interface has also been deprecated in a similar manner and its documentation references the documentation for the Observable class.

Not only does the Observable documentation relay when it was deprecated, but it also documents the problems with Observable that make deprecation desirable and provides important information on alternatives that might be used instead of Observable:

This class and the Observer interface have been deprecated. The event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent package. For reactive streams style programming, see the Flow API.

This is a good example of how Java developers can use the Javadoc tag @deprecated to provide much deeper detail related to deprecation than can be provided even with the enhanced @Deprecated annotation. JEP 277 ("Enhanced Deprecation") explicitly listed unifying of Javadoc tag @deprecated and annotation @Deprecated as a "non-goal": "It is not a goal of this project to unify the @deprecated Javadoc tag with the @Deprecated annotation."

Additional details justifying the deprecation of Observable and Observer can be found in JDK-8154801 ("deprecate Observer and Observable"). There is a quote in there from Josh Bloch as part of JDK-4180466 ("Why is java.util.Observable class not serializable.") dated February 1999:

This class is no longer under active development. It is largely unused in the JDK, and has, for the most part, been superseded by the 1.1 Beans/AWT event model. ... Observable has fallen into disuse and is no longer under active development.

For the most part, it seems that Observer and Observable are not used much, so deprecation shouldn't be much of an issue, especially given no definitive plans to remove these altogether.

Monday, April 24, 2017

Java and Docker: Now and the Future

Sharat Chander's blog post Official Docker Image for Oracle Java and the OpenJDK Roadmap for Containers provides a high-level overview of the "Official Docker Image for Oracle Java," an introduction to Docker and why containers like Docker are desirable, and a peek at things to come for Java on Docker. The post also provides a link to the "Docker image for Oracle Server JRE" that "is now available on Docker Store."

Chander briefly discusses attempts to set "up a consistent, reproducible environment that scales to thousands/millions of instances" for the cloud and how operating system tools and hardware virtualization have been used in this way. He then introduces Docker as another approach and provides a brief description of the benefits of Docker.

Chander's post introduces Alpine Linux and quotes their web page, "Small. Simple. Secure. Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox." Chander associates Alpine Linux's use of musl libc (described as "a new general-purpose implementation of the C library" that "is lightweight, fast, simple, free and aims to be correct in the sense of standards-conformance and safety") and busybox (combination of "tiny versions of many common UNIX utilities into a single small executable") to Java and paraphrases the message list post announcing Project Portola: "The goal of OpenJDK 'Project Portola' is to provide a port of the JDK to Alpine Linux, and in-particular the 'musl' C library."

The FAQ section of Chander's post has some interesting questions and answers. For example, there is information on Oracle's "recommendations for running Oracle Java SE on Docker" available on GitHub. There is information on Java 8 Update 131 enhancements that enable "better memory and processor integration between Java and Docker" and it's interesting to note that in "JDK 9 the JVM will be container-aware" instead of "the thread and memory settings [coming] from the host OS."

The OpenJDK Docker Repository is available at https://hub.docker.com/_/openjdk/.

It's interesting to see what is being done and what's planned for using Java with Docker.

Tuesday, April 18, 2017

Oracle JDK 9 Early Access Documentation Updated

Raymond Gallardo's 4 April 2017 post Early Access documentation for Oracle JDK 9 has been updated today announces updates to the Oracle JDK9 Documentation Early Access page. Gallardo highlights a few of the updated sections including What's New in Oracle JDK 9, Oracle JDK 9 Migration Guide, HotSpot Virtual Machine Garbage Collection Tuning Guide (including Garbage-First Garbage Collector Tuning), javapackager tool for "packaging Java and JavaFX applications," and XML Catalog API.

The Main Tools to Create and Build Applications section features information on jlink (JEP 282), jmod (create and show contents of Project Jigsaw JMOD files), and jdeprscan (static analysis tool that scans ... for uses of deprecated API elements). There is also information on jhsdb for obtaining "specific information from a hanging or crashed JVM."

I summarized some of the tools and features being removed from the JDK with Java 9 in the post JDK 9 is the End of the Road for Some Features. Some of these are spelled out with additional details in the section Removed Tools. The Changes to Garbage Collection section similarly shows changes and removals in Java 9 of options and commands related to garbage collection. The section Changes to the Installed JDK/JRE Image outlines removal of things such as rt.jar and tools.jar, the extension mechanism, and the endorsed standards override mechanism.

The section Enable Logging with the JVM Unified Logging Framework demonstrates how to "use -Xlog option to configure or enable logging with the Java Virtual Machine (JVM) unified logging framework." The Changes to GC Log Output section explains how to use this -Xlog with gc (-Xlog:gc) for logging related to garbage collection and points out that "the -XX:+PrintGCDetails and -XX:+PrintGC options have been deprecated."

I previously blogged on the future of the Concurrent-Mark-Sweep garbage collector. The Java SE 9 HotSpot Virtual Machine Garbage Collection Tuning Guide states, "The CMS collector is deprecated. Strongly consider using the Garbage-First collector instead."

The main Oracle JDK 9 Documentation Early Access page is at http://docs.oracle.com/javase/9/index.html and its Developer Guides link provides direct references to guides such as Troubleshooting Guide, HotSpot Virtual Machine Garbage Collection Tuning Guide, Java Scripting Programming Guide, Java Language Updates, and Migration Guide.

Monday, April 17, 2017

Implications of the Presence of StringBuffer

When I am working on legacy code and run across instances of StringBuffer, I typically replace them with instances of StringBuilder. Although a performance advantage can be gained from this change, I often change it in places I know will have little noticeable effect in terms of performance. I feel it's worth making the change for a variety of reasons in addition to the potential for performance benefit. There's rarely a reason to not choose StringBuilder over StringBuffer (API expectations are the most common exception) and the existence of StringBuffer in code misleads and provides a bad example to those new to Java.

In the book The Pragmatic Programmer: From Journeyman to Master, Andy Hunt and David Thomas discuss "the importance of fixing the small problems in your code, the 'broken windows'." Jeff Atwood touched on this subject in the post The Broken Window Theory and it has been more recently addressed in the posts Software Rot, Entropy and the Broken Window Theory and Don't leave broken windows. The presence of StringBuffer implies a staleness in the code. In effect, use of StringBuffer may not be a "broken window," but it's a really old, leaky single-pane window that should be replaced with a modern, energy-efficient double-pane window.

I found Peter Lawrey's recent blog post StringBuffer, and how hard it is to get rid of legacy code to be an interesting take on other implications of StringBuffer that still exist in code. Lawrey quotes the last paragraph of the StringBuffer class Javadoc documentation, "As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization." Lawrey then uses simple Java methods and jmap to demonstrate that instances of StringBuffer are still used in classes and libraries delivered with the JDK even as late as Java 8.

Lawrey points out that the presence of StringBuffer in frequently used Java code more than a decade after the introduction of "drop-in replacement" StringBuilder is evidence of how difficult it is to "clean up legacy code." Lawrey's full conclusion states, "Using StringBuffer on startup doesn’t make much difference, but given it has a well known, drop in replacement, and it is still used, even in new functionality more than ten years later shows how hard it can be to clean up legacy code or to change thinking to get people to use best practice libraries."

I decided to try out one of Lawrey's simplest examples when compiled with Java 8 Update 121 and when compiled with a recent release of OpenJDK 9. I (slightly) adapted Lawrey's example to the simple "Main" class listing shown next.

Main.java

import java.io.IOException;

/**
 * (Slightly) adapted class from blog post
 * "StringBuffer, and how hard it is to get rid of legacy code" at
 * https://vanilla-java.github.io/2017/04/13/String-Buffer-and-how-hard-it-is-to-get-rid-of-legacy-code.html
 */
public class Main
{
   /**
    * Main function that instantiates this Java "application" and does nothing
    * else until "ENTER" is pressed.
    */
   public static void main(final String[] args) throws IOException
   {
      System.out.println("Waiting [press ENTER to exit] ..");
      System.in.read();
   }
}

The following screen snapshot shows the output of using jcmd with its -all option (includes unreachable objects in the inspection) to show the number of instances of StringBuffer and StringBuilder in the simple Java application when compiled and run against three different versions of Java (Java 8 Update 102, Java 8 Update 121, and OpenJDK 9.0 ea+164). The execution of jcmd is performed in PowerShell and so Select-String is used similarly to how grep is used in Linux.

Although the versions of the class compiled and executed with versions of Java 8 had instances of StringBuffer, the version compiled with and executed against Java 9 only had instances of StringBuilder. It looks like the resolution of JDK-8041679 ("Replace uses of StringBuffer with StringBuilder within core library classes") and JDK-8043342 ("Replace uses of StringBuffer with StringBuilder within crypto code") have had their intended effect.