Sunday Jan 25, 2015

Advice on removing javac lint warnings

Over the last twelve months or so, one of my projects has been fixing and reviewing fixes of javac lint warnings in the JDK 9 code base (varargs, fallthrough, serial, finally, overrides, deprecation, raw and unchecked) and once a warning category is cleared, making new instances of that category a fatal build error. Ultimately, all the warnings in the jdk repository were resolved and -Xlint:all -Werror is now used in the build.

Being involved in fixing several thousand warnings, I'd like to share some tips for developers who want to undertake an analogous task of cleaning up the technical debt of javac lint warnings in their own code base. First, I recommend tackling the warnings in a way that aligns well with the build system of the project, with a consideration of getting some code protected by the compiler from some warning categories as soon as possible. While the build of the JDK has been re-engineered over the course of the warnings cleanup, to a first approximation the build has been organized around Hg repositories. (At present, in JDK 9 the build is actually arranged around modules. A few years ago, the build was organized around Java packages rather than repositories.) A warnings cleanup isn't really done until introducing new instances of the warning cause a build failure; new warnings are too easy to ignore otherwise. Therefore, for JDK 9, the effort was organized around clearing the whole jdk repository of a warning category and then enabling that warning category in the build as opposed to, say, completely clearing a particular package of all warnings and then moving to the next package.

There are two basic approaches to resolving a warning: suppressing it using the @SuppressWarnings mechanism or actually fixing the code triggering the warning. The first approach is certainly more expedient. While it doesn't directly improve the code base, it can offer an indirect benefit of creating a situation where new warnings can be kept out of the code base by allowing a warning to be turned on in the build sooner. The different warning categories span a range of severity levels and while some warnings are fairly innocuous, others are suspicious enough that I'd recommend always fixing them if a fix is feasible. When resolving warnings in the JDK, generally the non-deprecation warnings categories were fixed while the deprecation warnings were suppressed with a follow-up bug filed. The non-deprecation warnings mostly require Java language expertise to resolve and little area expertise; deprecation warnings are the reverse, often quite deep area expertise is needed to develop and evaluate a true fix.

Tips on addressing specific categories of lint warnings:

[cast]: Warn about use of unnecessary casts.
Since these warnings are generated entirely from the the contents of method bodies, there is no impact to potential callers of the code. Also, the casts analyzed as redundant by javac are easy and safe to remove; fixing cast warnings is essentially a zero-risk change.
[fallthrough]: Warn about falling through from one case of a switch statement to the next.
When such a falling through is not intentional, it can be a very serious bug. All fallthrough switch cases should be examined for correctness. An idiomatic and intentional fallthrough should have two parts: first, the cases in question should be documented in comments explaining that the fallthrough is expected and second, an @SuppressWarnings({"fallthrough"}) annotation should be added to the method containing the switch statement.

See also the discussion of switch statements in Java Puzzlers, Puzzler 23: No Pain, No Gain.

[static]: Warn about accessing a static member using an instance.
This is an unnecessary and misleading coding idiom that should be unconditionally removed. The fix is to simply refer to the static member using the name of the type rather than an instance of the type.

This coding anti-pattern is discussed in Java Puzzlers, Puzzle 48: All I Get Is Static.

[dep-ann]: Warn about items marked as deprecated in JavaDoc but not using the @Deprecated annotation
Since Java SE 5.0, the way to mark an element as deprecated is to modify it with a @Deprecated annotation. While a @deprecated javadoc tag should be used to describe all @Deprecated elements, the javadoc tag is informative only and does not mean the element is treated as deprecated by the compiler.

A element should have an @deprecated javadoc tag in its javadoc if and only if the element is @Deprecated.

Therefore, the fix should be to either remove the @deprecated javadoc tag if the element should not be deprecated or add the @Deprecated annotation if it should be deprecated.

[serial]: Warn about Serializable classes that do not provide a serialVersionUID.
Serialization is a subtle and complex protocol whose compatibility impact on evolving a type should not be underestimated. To check for compatibility between the reader of serial stream data and the writer of the data, besides matching the names of the reader and writer, identification codes of the reader and the writer are also compared and the serial operation fails if the codes don't match. When present, a serialVersionUID field of a class stores the identification code, called a Stream Unique Identifier (SUID) in serialization parlance. When a serialVersionUID field is not present, a particular hashing algorithm is used to compute the SUID instead. The hash algorithm is perturbed by many innocuous changes to a class and can therefore improperly indicate a serial incompatibility when no such incompatibility really exists. To avoid this hazard, a serialVersionUID field should be present on all Serializable classes following the usual cross-version serialization contracts, including Serializable abstract superclasses.

If a Serializable class without a serialVersionUID has already been shipped in a release, running the serialver tool on the type in the shipped release will return the serialVersionUID declaration needed to maintain serial compatibility.

For further discussion, see Effective Java, 2nd Edition, Item 74: Implement Serializable judiciously.

[overrides]: Warn about issues regarding method overrides.
As explained in Effective Java, 2nd Edition, Item 9: Always Override hashCode when you override equals, for objects to behave properly when used in collections, they must have correct equals and hashCode implementations. The invariant checked by javac is more nuanced than the one discussed in Effective Java; javac checks that if a class overrides equals, hashCode has been overriden somewhere in the superclass class chain of the class. It is common for a set of related classes to be able to share a hashCode implementation, say a function of a private field in the root superclass in a set of related types. However, each class will still need to have its own equals method for the usual instanceof check on the argument to equals.
[deprecation]: Warn about use of deprecated items.
Well documented @Deprecated elements suggest a non-deprecated replacement. When using a replacement is not feasible, or no such replacement exists, @SuppressWarnings("deprecation") can be used to acknowledge the situation and remove the warning. A small language change made in JDK 9 makes suppressing deprecation warnings tractable.
[rawtypes]: Warn about use of raw types.
[unchecked]: Warn about unchecked operations.
Both rawtypes and unchecked warnings are linked to the same underlying cause: incomplete generification of APIs and their implementations. Generics shipped in 2004 as part of Java SE 5.0; Java code written and used today should be generics aware! Being generics-aware has two parts, using generics properly in the signature / declaration of a method, constructor, or class and using generics properly in method and constructor bodies. Many uses of generics are straightforward; if you have a list that only contains strings, it should probably be declared as a List<String>. However, some uses of generics can be subtle and are out of scope for this blog entry. However, extensive guides are available with detailed advice. IDEs also provide refactorings for generics; check their documentation for details.

I hope these tips help you make your own Java project warnings-free.

Wednesday Jan 14, 2015

More concise try-with-resources statements in JDK 9

As part of milling Project Coin in JDK 9, the try-with-resources statement has been improved. If you already have a resource as a final or effectively final variable, you can use that variable in the try-with-resources statement without declaring a new variable in the try-with-resources statement.

For example, given resource declarations like

        // A final resource
        final Resource resource1 = new Resource("resource1");
        // An effectively final resource
        Resource resource2 = new Resource("resource2");

the old way to write the code to manager these resources would be something like:

        // Original try-with-resources statement from JDK 7 or 8
        try (Resource r1 = resource1;
             Resource r2 = resource2) {
            // Use of resource1 and resource 2 through r1 and r2.

while the new way can be just

        // New and improved try-with-resources statement in JDK 9
        try (resource1;
             resource2) {
            // Use of resource1 and resource 2.

An initial pass has been made over the java.base module in JDK 9 to update the JDK libraries to use this new language feature.

You can try out these changes in your own code using a JDK 9 snapshot build. Enjoy!

Sunday Apr 14, 2013

Changing Sources and Moving Targets: Evolving the javac command line

As written up in JEP 182: Policy for Retiring javac -source and -target Options, we're implementing a policy to over time clean up the -source and -target portions of javac's command line:

  • Class files going all the way back to version 45.3 generated by JDK 1.0.2 will continue to be recognized by javac when put on the classpath, etc.
  • The never-documented -target options 1.4.1, 1.4.2, and jsr14 have been removed in JDK 8 (8010179).
  • In JDK 8, source and target options for 1.5 and below will be deprecated and a warning will be printed on their use (8011043).
  • In JDK 9, source and target options for 1.5 and below will be removed (8011044).
  • Starting in JDK 9, a "one plus three back" policy will apply to source and target options. JDK 9 will support (9/1.9, 8/1.8, 7/1.7, 6/1.6) and JDK 10 will support (10/1.10, 9/1.9, 8/1.8, 7/1.7) and so on.

Removing support for the old options will ease compiler maintenance in several ways. First, there will be direct benefits from allowing some code to be deleted. Nixing jsr14 allowed about 250 lines of code to be excised. Second, fewer interactions between new language features and old source levels need to be handled in the compiler. The Java Language Specification only deals with a single version of the language and there is no formal specification of many aspects of how a Java compiler is supposed to behave. To use a recent example, there is no specification for how a new-in-8 default method being introduced to the language and core libraries by Project Lambda should appear to code being compiled under, say, -source 6. Limiting the span of source and target version supported reduces the need to define such cross-version interactions. (The practical impact of source cross-version interfaces would be greatly reduced if developers more often follwed the recommended practice of setting the bootclasspath when cross-compiling to an older platform version.)

This policy will help balance stability versus progress and should cover releases having public updates when a new JDK is released.

Thursday Feb 21, 2013

Functional Interfaces

As part of Project Lambda, after discussion with the JSR 335 expert group, we decided to add a FunctionalInterface annotation type to the platform. To a first approximation, functional interfaces are those interface types which define only a single method and are therefore usable in lambda expressions. (There are some tricky details in the definition of a functional interface relating to generics and also some details about excluding from consideration methods defined on java.lang.Object.) The new annotation type allows a library designer to clearly indicate the property of intending an interface type to be used with lambda expressions along with an implied commitment to keep that property true in the future. However, the compiler will allow any interface type meeting the structural properties of a functional interface to be used for a lambda expression regardless of whether or not the interface has a @FunctionalInterface annotation.

They types being added in the java.util.function package are by design functional interfaces and can be annotated with @FunctionalInterface from early days. However, many existing Java SE types are also functional interfaces and we want to identify and annotate those appropriately too. To find those candidate interfaces to be annotated, I ran an annotation processor over the code, using the same methodology as used to find Closeable candidates during JDK 7.

A significant number of candidates were found throughout the JDK. After suitable discussion and review, the first batch of core libraries changes have been pushed. Analogous discussions have been started in the 2D, awt, and swing areas.

For guidance in retrofitting @FunctionalInterface to an existing candidate type, if the type is routinely instantiated using an anonymous class, it is a good candidate for being annotated with @FunctionalInterface.

Monday Oct 29, 2012

JDK bug migration: components and subcomponents

One subtask of the JDK migration from the legacy bug tracking system to JIRA was reclassifying bugs from a three-level taxonomy in the legacy system, (product, category, subcategory), to a fundamentally two-level scheme in our customized JIRA instance, (component, subcomponent). In the JDK JIRA system, there is technically a third project-level classification, but by design a large majority of JDK-related bugs were migrated into a single "JDK" project. In the end, over 450 legacy subcategories were simplified into about 120 subcomponents in JIRA. The 120 subcomponents are distributed among 17 components. A rule of thumb used was that a subcategory had to have at least 50 bugs in it for it to be retained.

Below is a listing the component / subcomponent classification of the JDK JIRA project along with some notes and guidance on which OpenJDK email addresses cover different areas. Eventually, a separate incidents project to host new issues filed at will use a slightly simplified version of this scheme.

The preponderance of bugs and subcomponents for the JDK are in library-related areas, with components named foo-libs and subcomponents primarily named after packages. While there was an overall condensation of subcomponents in the migration, in some cases long-standing informal divisions in core libraries based on naming conventions in the description were promoted to formal subcomponents. For example, hundreds of bugs in the java.util subcomponent whose descriptions started with "(coll)" were moved into java.util:collections. Likewise, java.lang bugs starting with "(reflect)" and "(proxy)" were moved into java.lang:reflect.

  • client-libs (Predominantly discussed on 2d-dev and awt-dev and swing-dev.)
    • 2d
    • demo
    • java.awt
    • java.awt:i18n
    • java.beans (See beans-dev.)
    • javax.accessibility
    • javax.imageio
    • javax.sound (See sound-dev.)
    • javax.swing
  • core-libs (See core-libs-dev.)
    • java.lang
    • java.lang.invoke
    • java.lang:class_loading
    • java.lang:reflect
    • java.math
    • java.nio (Discussed on nio-dev.)
    • java.nio.charsets
    • java.rmi
    • java.sql
    • java.sql:bridge
    • java.text
    • java.util
    • java.util.concurrent
    • java.util.jar
    • java.util.logging
    • java.util.regex
    • java.util:collections
    • java.util:i18n
    • javax.annotation.processing
    • javax.lang.model
    • javax.naming (JNDI)
    • javax.script
    • javax.script:javascript
    • javax.sql
    • org.openjdk.jigsaw (See jigsaw-dev.)
  • security-libs (See security-dev.)
    • javax.crypto (JCE: includes SunJCE/MSCAPI/UCRYPTO/ECC)
    • javax.crypto:pkcs11 (JCE: PKCS11 only)
    • (JSSE, includes
    • javax.smartcardio
    • javax.xml.crypto
    • org.ietf.jgss
    • org.ietf.jgss:krb5
  • other-libs
    • corba
    • corba:idl
    • corba:orb
    • corba:rmi-iiop
    • javadb
    • other (When no other subcomponent is more appropriate; use judiciously.)

Most of the subcomponents in the xml component are related to jaxp.

  • xml
    • jax-ws
    • jaxb
    • javax.xml.parsers (JAXP)
    • (JAXP)
    • javax.xml.transform (JAXP)
    • javax.xml.validation (JAXP)
    • javax.xml.xpath (JAXP)
    • jaxp (JAXP)
    • org.w3c.dom (JAXP)
    • org.xml.sax (JAXP)

For OpenJDK, most JVM-related bugs are connected to the HotSpot Java virtual machine.

The full JDK bug database contains entries related to legacy virtual machines that predate HotSpot as well as retired APIs.

  • vm-legacy
    • jit (Sun Exact VM)
    • jit_symantec (Symantec VM, before Exact VM)
    • jvmdi (JVM Debug Interface )
    • jvmpi (JVM Profiler Interface )
    • runtime (Exact VM Runtime)

Notable command line tools in the $JDK/bin directory have corresponding subcomponents.

Some aspects of JDK infrastructure directly affect JDK Hg repositories, but other do not.

  • infrastructure
    • build (See build-dev and build-infra-dev.)
    • licensing (Covers updates to the third party readme, licenses, and similar files.)
    • release_eng (Release engineering)
    • staging (Staging of web pages related to JDK releases.)

The specification subcomponent encompasses the formal language and virtual machine specifications.

  • specification
    • language (The Java Language Specification)
    • vm (The Java Virtual Machine Specification)

The code for the deploy and install areas is not currently included in OpenJDK.

  • deploy
    • deployment_toolkit
    • plugin
    • webstart
  • install
    • auto_update
    • install
    • servicetags

In the JDK, there are a number of cross-cutting concerns whose organization is essentially orthogonal to other areas. Since these areas generally have dedicated teams working on them, it is easier to find bugs of interest if these bugs are grouped first by their cross-cutting component rather than by the affected technology.

  • docs
    • doclet
    • guides
    • hotspot
    • release_notes
    • tools
    • tutorial
  • embedded
    • build
    • hotspot
    • libraries
  • globalization
    • locale-data
    • translation
  • performance
    • hotspot
    • libraries

The list of subcomponents will no doubt grow over time, but my inclination is to resist that growth since the addition of each subcomponent makes the system as a whole more complicated and harder to use.

When the system gets closer to being externalized, I plan to post more blog entries describing recommended use of various custom fields in the JDK project.

Wednesday Sep 26, 2012

JDK bug migration milestone: JIRA now the system of record

I'm pleased to announce the OpenJDK bug database migration project has reached a significant milestone: the JDK has switched from the legacy Sun "bugtraq" system to a new internal JIRA instance as the system of record for our bug tracking. This completes the initial phase of the previously described plan of getting OpenJDK onto an externally visible and writable bug tracker. The identities contained in the current system include recognized OpenJDK contributors.

The bug migration effort to date has been sizable in multiple dimensions. There are around 140,000 distinct issues imported into the JDK project of the JIRA instance, nearly 165,000 if backport issues to track multiple-release information are included. Separately, the Code Tools OpenJDK project has its own JIRA project populated with several thousands existing bugs. Once the OpenJDK JIRA instance is externalized, approved OpenJDK projects will be able to request the creation of a JIRA project for issue tracking.

There are many differences in the schema used to model bugs between the legacy bug system and the schema for the new JIRA projects. We've favored simplifications to the existing system where possible and, after much discussion, we've settled on five main states for the OpenJDK JIRA projects:

  • New
  • Open
  • In progress
  • Resolved
  • Closed

The Open and In-progress states can have a substate Understanding field set to track whether the issues has its "Cause Known" or "Fix understood". In the closed state, a Verification field can indicate whether a fix has been verified, unverified, or if the fix has failed.

At the moment, there will be very little externally visible difference between JIRA for OpenJDK and the legacy system it replaces. One difference is that bug numbers for newly filed issues in the JIRA JDK project will be 8000000 and above. If you are working with JDK Hg repositories, update any local copies of jcheck to the latest version which recognizes this expanded bug range. (The bug numbers of existing issues have been preserved on the import into JIRA). Relatively soon, we plan for the pages published on to be generated from information in JIRA rather than in the legacy system. When this occurs, there will be some differences in the page display and the terminology used will be revised to reflect JIRA usage, such as referring to the "component/subcomponent" of an issue rather than its "category". The exact timing of this transition will be announced when it is known.

We don't currently have a firm timeline for externalization of the JIRA system. Updates will be provided as they become available. However, that is unlikely to happen before JavaOne next week!

Friday Jun 15, 2012

My integer overfloweth

While certain classes like java.lang.Integer and java.lang.Math have been in the platform since the beginning, that doesn't mean there aren't more enhancements to be made in such places! For example, earlier in JDK 8, library support was added for unsigned integer arithmetic. More recently, my colleague Roger Riggs pushed a changeset to support integer overflow, that is, to provide methods which throw an ArithmeticException on overflow instead of returning a wrapped result. Besides being helpful for various programming tasks in Java, methods like the those for integer overflow can be used to implement runtimes supporting other languages, as has been requested at a past JVM language summit.

This year's language summit is coming up in July and I hope to get some additional suggestions there for helpful library additions as part of the general discussions of the JVM and Java libraries as a platform.

Tuesday Jun 05, 2012

Moving monarchs and dragons: migrating the JDK bugs to JIRA

Among insects, monarch butterflies and dragonflies have the longest migrations; migrating JDK bugs involves a long journey as well! As previously announced by Mark back in March, we've been working according to a revised plan to transition the JDK bug management from Sun's legacy system to initially an Oracle-internal JIRA instance which is afterward made visible and usable externally. I've been busily working on this project for the last few months and the team has made good progress on many aspects of the effort:

  • JDK bugs will be imported into JIRA regardless of age; bugs will also be imported regardless of state, including closed bugs. Consequently, the JDK bug project will start pre-populated with over 100,000 existing bugs, some dating all the way back to 1994. This will allow a continuity of information and allow new issues to be linked to old ones.

  • Using a custom import process, the Sun bug numbers will be preserved in JIRA. For example, the Sun bug with bug number 4040458 will become "JDK-4040458" in JIRA. In JIRA the project name, "JDK" in our case, is part of the bug's identifier. Bugs created after the JIRA migration will be numbered starting at 8000000; bugs imported from the legacy system have numbers ranging between 1000000 and 79999999.

  • We're working with the team to try to maintain continuity of the ability to both read JDK bug information as well as to file new incidents. At least for now, the overall architecture of will be the same as it is today: it will be a gateway bridging to an Oracle-internal system, but the internal system will change to JIRA from the legacy database. Generally we are aiming to preserve the visibility of bugs currently viewable on; however, bugs in areas not related to the JDK will not be visible after the transition to JIRA. New incoming incidents will be sent to a separate JIRA project for initial triage before possibly being moved into the JDK project.

  • JDK bug management leans heavily on being able to track the state of bugs in multiple releases, especially to coordinate delivering synchronized security releases (known as CPUs, critital patch updates, in Oracle parlance). For a security release, it is common for half a dozen or more release trains to be affected (for example, JDK 5, JDK 6 update, OpenJDK 6, JDK 7 update, JDK 8, virtual releases for HotSpot express, etc.). We've determined we need to track at least the tuple of (release, responsible engineer/assignee for the release, status in the release) for the release trains a fix is going into. To do this in JIRA, we are creating a separate port/backport issue type along with a custom link type to allow the multiple release information to be easily grouped and presented together.

  • The Sun legacy system had a three-level classification scheme, product, category, and subcategory. Out of the box, JIRA only has a one-level classification, component. We've implemented a custom second-level classification, subcomponent. As part of the bug migration we've taken the opportunity to think about how bugs should be grouped under a two-level system and we'll the new system will be simpler and more regular. The main top-level components of the JDK product will include:

    • core-libs
    • client-libs
    • deploy
    • install
    • security-libs
    • other-libs
    • tools
    • hotspot
    For the libs areas, the primary name of the subcomponent will be the package of the API in question. In the core-libs component, there will be subcomponents like:
    • java.lang
    • java.lang.class_loading
    • java.math
    • java.util
    • java.util:i18n
    In the tools component, subcomponents will primarily correspond to command names in $JDK/bin like, jar, javac, and javap.

    The first several bulk imports of the JDK bugs into JIRA have gone well and we're continuing to refine the import to have greater fidelity to the current data, including by reconstructing information not brought over in a structured fashion during the previous large JDK bug system migration back in 2004.

    We don't currently have a firm timeline of when the new system will be usable externally, but as it becomes available, I'll share further information in follow-up blog posts.

Sunday Apr 01, 2012

Goto for the Java Programming Language

Work on JDK 8 is well-underway, but we thought this late-breaking JEP for another language change for the platform couldn't wait another day before being published.

Title: Goto for the Java Programming Language
Author: Joseph D. Darcy
Organization: Oracle.
Created: 2012/04/01
Type: Feature
State: Funded
Exposure: Open
Component: core/lang
Scope: SE
JSR: 901 MR
Discussion: compiler dash dev at openjdk dot java dot net
Start: 2012/Q2
Effort: XS
Duration: S
Template: 1.0
Reviewed-by: Duke
Endorsed-by: Edsger Dijkstra
Funded-by: Blue Sun Corporation


Provide the benefits of the time-testing goto control structure to Java programs. The Java language has a history of adding new control structures over time, the assert statement in 1.4, the enhanced for-loop in 1.5,and try-with-resources in 7. Having support for goto is long-overdue and simple to implement since the JVM already has goto instructions.

Success Metrics

The goto statement will allow inefficient and verbose recursive algorithms and explicit loops to be replaced with more compact code.

The effort will be a success if at least twenty five percent of the JDK's explicit loops are replaced with goto's. Coordination with IDE vendors is expected to help facilitate this goal.


The goto construct offers numerous benefits to the Java platform, from increased expressiveness, to more compact code, to providing new programming paradigms to appeal to a broader demographic.

In JDK 8, there is a renewed focus on using the Java platform on embedded devices with more modest resources than desktop or server environments. In such contexts, static and dynamic memory footprint is a concern. One significant component of footprint is the code attribute of class files and certain classes of important algorithms can be expressed more compactly using goto than using other constructs, saving footprint. For example, to implement state machines recursively, some parties have asked for the JVM to support tail calls, that is, to perform a complex transformation with security implications to turn a method call into a goto. Such complicated machinery should not be assumed for an embedded context. A better solution is just to expose to the programmer the desired functionality, goto.

The web has familiarized users with a model of traversing links among different HTML pages in a free-form fashion with some state being maintained on the side, such as login credentials, to effect behavior. This is exactly the programming model of goto and code. While in the past this has been derided as leading to "spaghetti code," spaghetti is a tasty and nutritious meal for programmers, unlike quiche.

The invokedynamic instruction added by JSR 292 exposes the JVM's linkage operation to programmers. This is a low-level operation that can be leveraged by sophisticated programmers. Likewise, goto is a also a low-level operation that should not be hidden from programmers who can use more efficient idioms.

Some may object that goto was consciously excluded from the original design of Java as one of the removed feature from C and C++. However, the designers of the Java programming languages have revisited these removals before. The enum construct was also left out only to be added in JDK 5 and multiple inheritance was left out, only to be added back by the virtual extension method methods of Project Lambda.

As a living language, the needs of the growing Java community today should be used to judge what features are needed in the platform tomorrow; the language should not be forever bound by the decisions of the past.


From its initial version, the JVM has had two instructions for unconditional transfer of control within a method, goto (0xa7) and goto_w (0xc8). The goto_w instruction is used for larger jumps. All versions of the Java language have supported labeled statements; however, only the break and continue statements were able to specify a particular label as a target with the onerous restriction that the label must be lexically enclosing.

The grammar addition for the goto statement is:

    goto Identifier ;

The new goto statement similar to break except that the target label can be anywhere inside the method and the identifier is mandatory. The compiler simply translates the goto statement into one of the JVM goto instructions targeting the right offset in the method. Therefore, adding the goto statement to the platform is only a small effort since existing compiler and JVM functionality is reused.

Other language changes to support goto include obvious updates to definite assignment analysis, reachability analysis, and exception analysis.

Possible future extensions include a computed goto as found in gcc, which would replace the identifier in the goto statement with an expression having the type of a label.


Since goto will be implemented using largely existing facilities, only light levels of testing are needed.


  • Compatibility: Since goto is already a keyword, there are no source compatibility implications.
  • Performance/scalability: Performance will improve with more compact code. JVMs already need to handle irreducible flow graphs since goto is a VM instruction.

Sunday Mar 11, 2012

Repeating annotations in the works

Work has commenced on the repeating annotations feature discussed in JEP 120: Repeating Annotations.

First, the meta-annotation type used to declare the containing annotation has been added to java.lang.annotation. Updates to the AnnotatedElement interface will be made later. Next, with feedback from other members of the compiler team, I've written a draft specification of the needed language changes:

Updates to JLS 9.6 Annotation Types:

If annotation type T is annotated with an annotation a of type ContainerAnnotation then:

  • The value of the @ContainerAnnotation annotation is called the containing annotation type TC.
  • TC must declare a value() method whose return type is T[], or a compile-time error occurs. (This implies that TC can be the containing annotation type for only a single annotation type.) [Note: Since an annotation type T cannot declare a method that returns T or T[] as a value, that implies that it is a compile time error for an annotation type to specify itself as a container annotation type.]
  • TC may declare methods other than value(). Any such methods must have a default clause, or a compile-time errors occurs. [Note: this is a bit weird "action at a distance" in terms of compiler errors. The error message here is given at the site of the T since the containing annotation might only be present as a class file.]
  • It is a compile time error if the retention of T is not a subset of the retention of TC. This comparison is made taking default retention into consideration.

    In more detail, if the retention of the TC is SOURCE, the retention of T must be SOURCE. If the retention of TC is CLASS, the retention of T may be either CLASS or SOURCE. if the retention of the TC is RUNTIME, the retention of T may be SOURCE, CLASS, or RUNTIME.

  • It is a compile time error if T is @Documented and TC is not @Documented.

    [Note that it is permissible TC to be @Documented and for T to not be @Documented.]

  • It is a compile time error if T is @Inherited and TC is not @Inherited.

    [Note that it is permissible TC to be @Inherited and for T to not be @Inherited.]

  • It is a compile time error if T has target values that are not included in the target set of TC, taking default target values into account.

Note that an annotation type TC may be a container type for annotation type T while also having its own container type TCC.

[However, two annotation types cannot be containers for each other because that would create an illegal cyclic annotation type situation. For example, the following program is rejected by javac:

public @interface Mutual {
    Omaha[] value() default {};

@interface Omaha {
    Mutual[] value() default {};

@Mutual({@Omaha, @Omaha})
@Omaha({@Mutual, @Mutual})
class Foo {}

with the message error: cyclic annotation element type
    Omaha[] value() default {};
1 error]

Updates to JLS 9.7 Annotations:

"It is a compile-time error if a declaration is annotated with more than one annotation for a given annotation type."

Change to "unless the annotation type is annotated with an @ContainerAnnotation."

Annotation types with an @ContainerAnnotation are known as repeatable annotation types. The presence of an @ContainerAnnotation indicates multiple annotations of that annotation type will be logically replaced with a single annotation synthesized by the compiler. The type of the synthesized annotation, TC, is the type given by the value of the ContainerAnnotation annotation on T. The order of the elements of the value() method of the synthesized TC annotation matches the left to right order of the base repeatable annotations.

If an element only has a single repeatable annotation, the annotation is not replaced.

It is conventional to place the repeatable annotations of a given type contiguously on an element, but this is not required.

It is a compile time error if an element is annotated with both multiple base annotations of a repeatable annotation type T and with one or more annotations of the containing type TC.
[In other words, the collapsing of repeatable annotations to their containers is not recursive.]

Friday Jan 20, 2012

Unsigned Integer Arithmetic API now in JDK 8

At long last, after due discussion and review, I've just pushed initial API support for unsigned integer arithmetic into JDK 8! The support is implemented via static methods, primarily on java.lang.Integer and java.lang.Long, that:

  • Provide bidirectional conversion between strings and unsigned integers
  • Compare values as unsigned
  • Compute unsigned divide and remainder

Colloquially, "unsigned integer" means a 32-bit int or 64-bit long value where all the bits are interpreted as contributing to the magnitude. In the unsigned realm, the values of an integer type of a given bit-width range from 0 to 2width-1 rather than from -(2width-1) to 2width-1-1. A feature of the two's complement encoding of Java integers is that the bitwise results for add, subtract, and multiply are the same if both inputs are interpreted as signed values or both inputs are interpretted as unsigned values. (Other encodings like one's complement and signed magnitude don't have this properly.) Therefore, of the basic arithmetic operations, only a separate divide method needs to be provided to operate on values interpreted as unsigned.

To avoid dealing with the overhead of boxed values and to allow reuse of the built-in arithmetic operators, the unsigned API support does not introduce new types like UnsignedInt with instance methods to perform addition, subtraction, etc. However, that lack of separate Java-level unsigned types does mean a programmer can accidentally improperly mix signed and unsigned values. However, new unsigned types aren't the only way to mitigate this hazard. For example, a naming convention of adding a trailing "U" or "_U" to variables holding unsigned values could be adopted. A more structured approach would be to add an @Unsigned annotation type to the platform and apply that annotation to variables and fields holding unsigned values. One of the extra-linguistic checkers to be enabled by JSR 308 could then analyze code for signed/unsigned correctness.

I'm glad these methods are finally in the JDK. Later in JDK 8, there may be a few more fun bit-twiddling additions, such as methods to get the high order bits of a full multiply and methods which throw exceptions on integer overflow instead of wrapping around.

Tuesday Jan 10, 2012

Project Coin Fixes in 7u2

Last month, JDK 7u2 was released. The release has a few correctness fixes for the Project Coin features, two diamond fixes courtesy Maurizio and one fix to strings in switch:

  • Diamond inference with nested classes had an improper interaction. For example, in code like

    class X {
      class Y {
        Y(T a, Z b) {...}
      public static void main(String... args) {
        X<String>.Y<String> x1 = new X<String>().new Y<String>("",""); //ok
        X<String>.Y<String> x2 = new X<String>().new Y<>("",""); // Failed!
    diamond was not allowed at the second constructor call, but such code is accepted as of 7u2. (7046778)

  • The compiler erroneously allowed constructs like

    Foo<String>[] fooArr = new Foo<>[]{...};
    Such code is now properly rejected. (7057297)

  • If extra parenthesis were used around the case label of a string switch statement, as in

    switch (s) {
      case ("a"):
    javac would throw a NullPointerException when compiling the code. (7071246) Previously, the workaround was to remove the unneeded "(" and ")", but javac has been corrected to accept this valid syntax. (We received multiple reports of this bug, so parenthesis around case labels is much more common style than I would have expected!)

If you're using the Project Coin language features, I recommend upgrading to 7u2 to get these fixes and to minimize source compatibility concerns going forward.

Wednesday Nov 16, 2011

Project Coin at Devoxx 2011

Returning to Antwerp, earlier today Maurizio and I presented a talk on Project Coin at Devoxx and the slides are now available.

The talk was streamed live on Parleys and will be available for download and viewing on the Devoxx 2011 channel in due course.

Now that my major Devoxx speaking obligations are over, more attention can be paid to Belgium waffles and beer!

Wednesday Aug 31, 2011

JDK 7 Changesets Over Time

Calling out some statistics I put together for OSCON, I think it is interesting to examine the cumulative number of monthly changesets in the JDK 7 forest from the time of the transition to Mercurial to JDK 7 GA:

This graph covers roughly three and a half years of the project's history, with the purple lines being time under Sun and the red lines being time under Oracle. The blue line is a scaling of the number of changesets per month, roughly the first derivative of the total. The solid purple and red lines show the trend in the rate of change in the last year of Sun's stewardship of the JDK and the first year of Oracle's stewardship. Under Sun, the rate of change was decreasing. After a lull for some "Welcome to Oracle" events, activity on JDK picked up and was on average 15% higher in the first year under Oracle than the last year under Sun (≈244 changesets/month under Oracle vs ≈211 changesets/month under Sun). The first year under Oracle included JDK 7 being feature complete in early 2011; however, JDK 7 wasn't done at that point! Several JSRs were still in flight and subsequently there was a large push in March and April this year to wrap up activity in JDK 7 ahead of the rampdown stabilization period immediately before GA.

Thursday Aug 18, 2011

JDK 7: Small Library Treats

With JDK 7 out the door, many writeups of the release have naturally focused on its larger features like Project Coin, NIO.2, the fork/join framework, and invokedynamic. However, there are a number of small but useful library conveniences in JDK 7 that shouldn't be overlooked. Library changes I think are handy include:

  • To allow more informative assertion errors to be constructed, AssertionError now includes a constructor taking a string message and a Throwable cause, which is one of the four conventional constructors for exception types.

  • The methods which convert strings to numeric values differed in whether or not a leading plus, "+", was regarded as valid input. Float, Double, and BigDecimal accepted a leading plus while Byte, Short, Integer, Long, and BigInteger did not. As of JDK 7, all those types consistently accept a leading plus in their parseFoo, valueOf, and decode methods.

  • To help write more efficient comparators, Boolean, Byte, Character, Short, Integer, and Long each have a two-argument static compare method that performs the desired comparison operation without boxing overhead.

  • This six checked exception types that can be thrown by core reflection now have a common supertype, ReflectiveOperationException. This additional type complements the improved exception handling available with multi-catch and more precise re-throw from Project Coin.

  • The java.util.Objects class contains a number of small, but commonly used methods, many of them for coping with null inputs. For example, Objects contains a two-argument static equals method which does the right thing on null inputs. I've replaced a half-dozen copies of that method's logic in the JDK; I'm sure many more instances can be removed in other code bases as JDK 7 is adopted.

  • Part of NIO.2, I expect over time the utility methods in java.nio.file.Files to copy, read, and write the contents of file will see heavy usage.

Tuesday Aug 16, 2011

A Pictorial View of a JSR Progressing through the JCP

While JSR 348 is working on making changes to the JCP process JSRs pass through, for those working on or following JSRs understanding the state transitions of the current process, JCP 2.7, is helpful. As shown below, after an approval ballot to initiate the JSR, the expert group convenes and produces a series of draft specifications, currently an early draft, followed by a public review draft, a proposed final draft, and the final specification. If needed, an expert group can actually produce multiple early drafts or proposed final drafts.

States in italics involve votes from the executive committee (EC). Given a successful vote, the JSR advances; otherwise, there can be a reconsideration ballot to address issues raised by the EC, after which a JSR can get back on track of close down.

As reported on this blog, JSR 334 duly went through all the mainline phases from initiation to completion (approval ballot, early draft review, public review, proposed final draft, final approval ballot, final release).

Not shown is the separate, and simpler, set of state transitions for maintenance reviews, as done for JSR 269, Pluggable Annotation Processing API, this spring.

Monday Jul 25, 2011

OSCON: The State of JDK OpenJDK

After a short keynote on JDK 7, later in the day on Monday I presented a talk about The State of JDK and OpenJDK; the slides for the talk are now available.

OSCON: JDK 7 in a Nutshell

Update: The slides.

If all goes according to plan, at 10 am PST on Monday, July 25 I'll be giving a keynote talk about JDK 7 in a Nutshell at OSCON Java in Portland and the talk is slated to be streamed live. After the keynote, I'll post the slides.

Monday Jul 18, 2011

Project Coin: JSR 334 Finale!

Slightly more than eight months after its JSR review ballot was first filed, JSR 334 has just successfully passed its final approval ballot. Along with the other portions of the Java SE 7 umbrella JSR, the language changes done under JSR 334 are now officially part of the Java SE platform, the first Java programming language changes since JDK 5 shipped way back in 2004.

Thanks go to the members of the JSR 334 expert group for their service, to the langtools team at Sun and Oracle for their integral participation in Project Coin and JSR 334, and to the interesting proposals and thoughtful comments on the coin-dev alias.

I'm happy with how the suite of six features turned out and I'm especially pleased with the degree of IDE support available even before JDK 7 has officially shipped.

I'm looking forward to Java programmers being able to use the new language features and to the additional changes that may come with "coin, the flip side" in JDK 8.

Thursday Jul 07, 2011

Project Coin at the Java 7 Launch

Update: Video now available from the Project Coin link on this page.

Somewhat before the scheduled GA at the end of the month, today at Oracle headquarters and elsewhere we celebrated the launch of JDK 7. The webcasts of my half-hour breakout session on Project Coin and three other technical breakouts will be available for replay later. In the meantime, I've posted the slides.

One comment I made during the session made an impression on twitter: after a glitch going back from the NetBeans demo to PowerPoint slides I noted "its always impressive how computers know when you are running a demo." This chronic technological reaction to demos may even last longer than Moore's law!




« July 2016

No bookmarks in folder