Tag Archives: Java

Records Come to Java

A first look at how Java 14’s data records will change the way you code

January 10, 2020

Download a PDF of this article

In this article, I’ll introduce the concept of a record in Java. Records are a new form of Java class designed to

  • Provide a first-class means for modeling data-only aggregates
  • Close a possible gap in Java’s type system
  • Provide language-level syntax for a common programming pattern
  • Reduce class boilerplate

The records feature is under active development and is targeted to appear as a preview feature in Java 14 (which will be released in March). To make the most of this article, you should be fairly knowledgeable about Java programming and curious about how programming languages are designed and implemented.

Let’s start by exploring the basic idea of what a Java record is.

What Is a Java Record?

One of the most common complaints about Java is that you need to write a lot of code for a class to be useful. Quite often you need to write the following:

  • toString()
  • hashCode() and equals()
  • Getter methods
  • A public constructor

For simple domain classes, these methods are usually boring, repetitive, and the kind of thing that could easily be generated mechanically (and IDEs often provide this capability), but as of now, the language itself doesn’t provide any way to do this.

This frustrating gap is actually worse when you are reading someone else’s code. For example, it might look like the author is using IDE-generated hashCode() and equals() that handle all the fields of the class, but how can you be sure without checking each line of the implementation? What happens if a field is added during refactoring and the methods are not regenerated?

The goal of records is to extend the Java language syntax and create a way to say that a class is “the fields, just the fields, and nothing but the fields.” By you making that statement about a class, the compiler can help by creating all the methods automatically and having all the fields participate in methods such as hashCode().

An Example Without Records

In this article, I am going to use foreign exchange (FX) trading as an example domain to explain records. I will show how you can use them to improve your modeling of the domain and get cleaner, less verbose, simpler code as a result.

Note that in a short article, it’s impossible to describe a fully realized production-grade trading system, so instead I will focus on a few basic aspects.

Let’s consider how to place an order when trading FX. The basic order type might consist of

  • The number of units you’re buying or selling (in millions of currency units)
  • The “side,” that is, whether you’re buying or selling (often called “bid” and “ask,” respectively)
  • The currencies you’re exchanging (the “currency pair”)
  • The time at which you placed my order
  • How long your order is good for before it times out (the time to live or “TTL”)

So, if you have £1 million and want to sell it for US dollars, and you want $1.25 for each £1, in the jargon of FX trading you are “buying 1 million of the GBP/USD rate at $1.25.” Traders also speak of when the order was created—usually at the present time, and how long the order is good for, which is often 1 second or less.

In Java, you might declare a domain class such as the following (I’m calling it “Classic” to underscore that you need to do this with a class at present):

public final class FXOrderClassic {
    private final int units;
    private final CurrencyPair pair;
    private final Side side;
    private final double price;
    private final LocalDateTime sentAt;
    private final int ttl;

    public FXOrderClassic(int units, 
               CurrencyPair pair, 
               Side side, 
               double price, 
               LocalDateTime sentAt, 
               int ttl) {
        this.units = units;
        this.pair = pair; // CurrencyPair is a simple enum
        this.side = side; // Side is a simple enum
        this.price = price;
        this.sentAt = sentAt;
        this.ttl = ttl;
    }

    public int units() {
        return units;
    }

    public CurrencyPair pair() {
        return pair;
    }

    public Side side() {
        return side;
    }

    public double price() { return price; }

    public LocalDateTime sentAt() {
        return sentAt;
    }

    public int ttl() {
        return ttl;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) 
            return false;

        FXOrderClassic that = (FXOrderClassic) o;

        if (units != that.units) return false;
        if (Double.compare(that.price, price) != 0) 
            return false;
        if (ttl != that.ttl) return false;
        if (pair != that.pair) return false;
        if (side != that.side) return false;
        return sentAt != null ? 
            sentAt.equals(that.sentAt) : that.sentAt == null;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = units;
        result = 31 * result + 
                   (pair != null ? pair.hashCode() : 0);
        result = 31 * result + 
                   (side != null ? side.hashCode() : 0);
        temp = Double.doubleToLongBits(price);
        result = 31 * result + 
                   (int) (temp ^ (temp >>> 32));
        result = 31 * result + 
                   (sentAt != null ? sentAt.hashCode() : 0);
        result = 31 * result + ttl;
        return result;
    }

    @Override
    public String toString() {
        return "FXOrderClassic{" +
                "units=" + units +
                ", pair=" + pair +
                ", side=" + side +
                ", price=" + price +
                ", sentAt=" + sentAt +
                ", ttl=" + ttl +
                '}';
    }
}

Then the order can be created like this:

var order = new FXOrderClassic(1, 
                    CurrencyPair.GBPUSD, 
                    Side.Bid, 1.25, 
                    LocalDateTime.now(), 1000);

But how much of the code to declare the class is really necessary? In current versions of Java, most developers would probably just declare the fields and then use their IDE to autogenerate all the methods. Let’s see how records improve the situation.

As a side note, Java doesn’t provide any way to talk about a data aggregate other than by defining a class, so it is clear that any type containing “just the fields” will be a class.

The Example with Records

The new concept is a record class (usually just called a record). This is an immutable (in the usual “shallow” Java sense) transparent carrier for a fixed set of values known as the record components. Each component gives rise to a final field that holds the provided value and an accessor method to retrieve the value. The field name and the accessor name match the name of the component.

The list of fields provides a state description for the record. In a class, there might be no relation between a field x, the constructor argument x, and the accessor x(), but in a record, they are by definition talking about the same thing: A record is its state.

To enable the creation of new instances of record classes, a constructor called the canonical constructor is also generated, which has a parameter list that exactly matches the declared state description.

The Java language (as of a preview feature in Java 14) provides concise syntax for declaring records, in which all the programmer needs to do is to declare the component names and types that make up the record, like this:

public record FXOrder(int units,
                      CurrencyPair pair,
                      Side side,
                      double price,
                      LocalDateTime sentAt,
                      int ttl) {}

By writing this record declaration, you are not just saving some typing. You are making a much stronger, semantic statement: that the FXOrder type is just the state provided and any instance is just a transparent aggregate of the field values.

One consequence of this is the field names become your API, so it becomes even more important to pick good names. (For example, Pair is not a good name for a type because it could refer to a pair of shoes.)

To access the new language features, you need to compile with the preview flag any code that declares records:

javac --enable-preview -source 14 FXOrder.java

If you now examine the class file with javap, you can see that the compiler has autogenerated a bunch of boilerplate code. (I am showing only the methods and their signatures in the decompilation below.)

$ javap FXOrder.class
Compiled from "FXOrder.java"
public final class FXOrder extends java.lang.Record {
  public FXOrder(int, CurrencyPair, Side, double, 
      java.time.LocalDateTime, int);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public int units();
  public CurrencyPair pair();
  public Side side();
  public double price();
  public java.time.LocalDateTime sentAt();
  public int ttl();
}

This looks remarkably like the set of methods in the code for the class-based implementation. In fact, the constructor and accessor methods all behave exactly as before.

Peculiarities of Records

However, methods such as toString() and equals() use an implementation that might be surprising to some developers:

public java.lang.String toString();
    Code:
       0: aload_0
       1: invokedynamic #51,  0    // InvokeDynamic #0:toString:(LFXOrder;)Ljava/lang/String;
       6: areturn

That is, the toString() method (as well as equals() and hashCode()) is implemented using an invokedynamic-based mechanism. This is similar to how string concatenation has also been migrated to use invokedynamic in recent Java versions.

You can also see that there is a new class, java.lang.Record, that will act as the supertype for all record classes. It is abstract and declares equals()hashCode(), and toString() to be abstract methods.

The java.lang.Record class cannot be directly extended, as you can see by trying to compile some code like the following:

public final class FXOrderClassic extends Record {
    private final int units;
    private final CurrencyPair pair;
    private final Side side;
    private final double price;
    private final LocalDateTime sentAt;
    private final int ttl;
    
    // ... rest of class elided
}

The compiler will reject the attempt, as follows:

$ javac --enable-preview -source 14 FXOrderClassic.java

FXOrderClassic.java:3: error: records cannot directly extend Record
public final class FXOrderClassic extends Record {
             ^
Note: FXOrderClassic.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
1 error

This means that the only way to get a record is to explicitly declare one and have javac create the class file. This approach also ensures that all record classes are created as final.

A couple of other core Java features also have special characteristics when applied to records.

First, records must obey a special contract regarding the equals() method:

If a record R has components c1c2, … cn, then if a record instance is copied as follows:

R copy = new R(r.c1(), r.c2(), ..., r.cn());

Then it must be the case that r.equals(copy) is true. Note that this invariant is in addition to the usual familiar contract regarding equals() and hashCode(); it does not replace it.

Secondly, Java serialization of records is different than it is for regular classes. This is a good thing because, as is now widely recognized, the Java serialization mechanism is deeply flawed in the general case. As Brian Goetz, Java language architect, puts it: “Serialization constitutes an invisible but public constructor, and an invisible but public set of accessors for your internal state.”

Fortunately, records are designed to be very simple: They are just transparent carriers for their fields, so there is no need to invoke the weirdness in the detail of the serialization mechanism. Instead, you can always use the public API and canonical constructor to serialize and deserialize records.

In addition, the serialVersionUID of a record class is 0L unless it is explicitly declared. The requirement for matching serialVersionUID values is also waived for record classes.

Before going on to the next section, I want to emphasize that there is a new programming pattern and there also is new syntax for a low-boilerplate class declaration, and they are not related to the inline classes feature being developed in Project Valhalla.

Design-Level Considerations

Let’s move on to explore some of the design-level aspects of the records feature. To do so, it’s helpful to recall how enums work in Java. An enum in Java is a special form of class that implements a pattern but with minimal syntax overhead; the compiler generates a bunch of code for us.

Similarly, a record in Java is a special form of class that implements a data carrier pattern with minimal syntax. All the boilerplate code that you expect will be autogenerated by the compiler.

However, while the simple concept of a data carrier class that just holds fields makes intuitive sense, what does that really mean in detail?

When records were first being discussed, many different designs were considered, for example:

  • Boilerplate reduction of plain old Java objects (POJOs)
  • JavaBeans 2.0
  • Named tuples
  • Product types (a form of algebraic data type)

These possibilities were discussed in some detail by Brian Goetz in his original design sketch. Each design option comes with additional secondary questions that follow from the choice of the design center for records, such as:

  • Can Hibernate proxy them?
  • Are they fully compatible with classic JavaBeans?
  • Are two records that declare the same fields in the same order considered the same type?
  • Will they come with pattern matching techniques such as pattern matching and destructuring?

It would be plausible to base the records feature on any one of these approaches, because each has advantages and disadvantages. However, the final design decision is that records are named tuples.

This choice was partially driven by a key design idea in Java’s type system known as nominal typing, which is the idea that every piece of Java storage (variables, fields) has a definite type and that each type has a name that should be meaningful to humans.

Even in the case of anonymous classes, the types still have names; it’s just that the compiler assigns the names and they are not valid names for types in the Java language (but are still OK within the VM), for example:

jshell> var o = new Object() {
   ...>   public void bar() { System.out.println("bar!"); }
   ...> }
o ==> $0@37f8bb67

jshell> var o2 = new Object() {
   ...>   public void bar() { System.out.println("bar!"); }
   ...> }
o2 ==> $1@31cefde0

jshell> o = o2;
|  Error:
|  incompatible types: $1 cannot be converted to $0
|  o = o2;
|      ^^

Notice that even though the anonymous classes were declared in exactly the same way, the compiler still produced two different anonymous classes, $0 and $1, and would not allow the assignment because in the Java type system, the variables have different types.

There are other (non-Java) languages where the overall shape of a class (for example, what fields and methods it has) can be used as the type (rather than an explicit type name); this is called structural typing.

It would have been a major change if records had broken with Java’s heritage and brought in structural typing for records. As a result, the “records are nominal tuples” design choice means you should expect that records will work best where you might use tuples in other languages. This includes use cases such as compound map keys or to simulate multi-return from a method. An example compound map key might look like this:

record OrderPartition(CurrencyPair pair, Side side) {}

Incidentally, records will not necessarily work well as a replacement for existing code that currently uses JavaBeans. There are several reasons for this: JavaBeans are mutable, whereas records are not, and they have different conventions for their accessors.

Records do allow some additional flexibility beyond the simple, single-line declaration form because they are genuine classes. Specifically, the developer can define additional methods, constructors, and static fields apart from the autogenerated defaults. However, these capabilities should be used carefully. Remember that the design intent of records is to enable developers to group related fields together as a single immutable data item.

A good rule of thumb is this: The more tempting it is to add additional methods to the basic data carrier (or to make it implement an interface), the more likely it is that a full class should be used rather than a record.

Compact Constructors

One important possible exception to this rule is the use of compact constructors, which are described like this in the Java specification:

The intention of a compact constructor declaration is that only validation and/or normalization code need be given in the body of the canonical constructor; the remaining initialization code is supplied by the compiler.

For example, you might want to validate orders to make sure that they don’t attempt to buy or sell negative quantities or set an invalid TTL value:

public record FXOrder(int units, 
                      CurrencyPair pair, 
                      Side side, 
                      double price, 
                      LocalDateTime sentAt, 
                      int ttl) {
    public FXOrder {
        if (units < 1) {
            throw new IllegalArgumentException(
                "FXOrder units must be positive");
        }
        if (ttl < 0) {
            throw new IllegalArgumentException(
                "FXOrder TTL must be positive, or 0 for market orders");
        }
        if (price <= 0.0) {
            throw new IllegalArgumentException(
                "FXOrder price must be positive");
        }
    }
}

A compact constructor does not cause a separate constructor to be generated by the compiler. Instead, the code that you specify in the compact constructor appears as extra code at the start of the canonical constructor. You do not need to specify the assignment of constructor parameters to fields—that is still generated automatically and appears in the constructor in the usual way.

One advantage that Java records have over the anonymous tuples found in other languages is that the constructor body of a record allows for code to be run when records are created. This allows for validation to occur (and exceptions to be thrown if an invalid state is passed). This would not be possible in purely structural tuples.

Alternative Constructors

It is also possible to use some static factory methods within the body of the record, for example, to work around the lack of default parameter values in Java. In the trading example, you might include a static factory like this to declare a quick way to create orders with default parameters:

public static FXOrder of(CurrencyPair pair, 
                             Side side, 
                             double price) {
        return new FXOrder(1, pair, side, price, 
                           LocalDateTime.now(), 1000);
    }

This could also be declared as an alternative constructor, of course. You should choose which approach makes sense in each circumstance.

One other use for alternative constructors is to create records for use as compound map keys, as in this example:

record OrderPartition(CurrencyPair pair, Side side) {
    public OrderPartition(FXOrder order) {
        this(order.pair(), order.side());
    }
}

The type OrderPartition can then be easily used as a map key. For instance, you might want to construct an order book for use in the trade-matching engine:

public final class MatchingEngine {
    private final Map<OrderPartition, RankedOrderBook> 
      orderBooks = new TreeMap<>();

    public void addOrder(final FXOrder o) {
        orderBooks.get(new OrderPartition(o)).addAndRank(o);
        checkForCrosses(o.pair());
    }

    public void checkForCrosses(final CurrencyPair pair) {
        // Do any buy orders match with sells now?
    }

    // ...
}

Then, when a new order is received, the addOrder() method extracts the appropriate order partition (consisting of a tuple of the currency pair and buy/sell side) and uses it to add the new order to the appropriate price-ranked order book. The new order might match against existing orders already on the books (which is called “crossing” of orders), so I need to check whether it does in the checkForCrosses() method.

Sometimes, you might not want to use the compact constructor and instead have a full, explicit canonical constructor. This signals that you need to do actual work in the constructor—and the number of use cases for this with simple data carrier classes is small. However, for some situations such as the need to make defensive copies of incoming parameters, this option is necessary. As a result, the possibility of an explicit canonical constructor is permitted by the compiler, but think very carefully before making use of it.

Conclusion

Records are intended to be simple data carriers, a version of tuples that fits into Java’s established type system in a logical and consistent manner. This will help many applications make domain classes clearer and smaller. It will also help teams eliminate many hand-coded implementations of the underlying pattern and reduce or remove the need for libraries like Lombok.

However, just as for sealed types, some of the most important use cases for records will emerge in the future. Pattern matching and, in particular, deconstruction patterns that allow a record to be broken up into its components show great promise and may well change the way that many developers program in Java. The combination of sealed types and records also provides Java with a version of a language feature known as algebraic data types.

If you’re familiar with these features from other programming languages, great. If not, don’t worry; they are being designed to fit with the Java language you already know and be easy to start using in your code.

However, you must always remember that until a finalized version of Java is delivered that contains a specific language feature, you should not rely on it. When talking about possible future features, as I have in this article, it should always be understood that the feature is being discussed for exploration purposes only.

Ben Evans

Ben Evans (@kittylyst) is a Java Champion and Principal Engineer at New Relic. He has written five books on programming, including Optimizing Java (O’Reilly). Previously he was a founder of jClarity (acquired by Microsoft) and a member of the Java SE/EE Executive Committee.

The 25 greatest Java apps ever written

From space exploration to genomics, from reverse compilers to robotic controllers, Java is at the heart of today’s world. Here are a few of the countless Java apps that stand out from the crowd.

June 5, 2020

Download a PDF of this article

top 25 greatest java apps ever written

The story of Java began in 1991, at a time when Sun Microsystems sought to extend their lead in the computer workstation market into the burgeoning personal electronics market. Little did anyone know that the programming language Sun was about to create would democratize computing, inspire a worldwide community, and become the platform for an enduring software development ecosystem of languages, runtime platforms, SDKs, open source projects, and lots and lots of tools. After a few years of secret development led by James Gosling, Sun released the landmark “write once, run anywhere” Java platform in 1995, refocusing it beyond its original design for interactive television to applications for the burgeoning World Wide Web. By the turn of the century, Java was animating everything from smartcards to space vehicles.

Today, millions of developers program in Java. Although Java continues to evolve at an ever-faster pace, on the occasion of the platform’s 25th anniversary, Java Magazine decided to take a look back at how Java molded our planet.

What follows is a list of the 25 most ingenious and influential Java apps ever written, from Wikipedia Search to the US National Security Agency’s Ghidra. The scope of these applications runs the gamut: space exploration, video games, machine learning, genomics, automotive, cybersecurity, and more.

This list, in no particular order, is far from exhaustive. If you think I’ve left off anything obvious, set the record straight! On Twitter, tweet to @OracleJavaMag with the hashtags #MovedbyJava and #Top25JavaApps. Or send an email to javamag_us@oracle.com.

On a personal note, I started my tenure as editor in chief of Software Development magazine in 2000, when the San Francisco Bay Area’s savvy new Java developers were making headlines. I remember devouring the first edition of Head First Java, by Kathy Sierra and Bert Bates. Their very visual explanations made clear not only the language syntax but also the object-oriented programming concepts that led to Java’s success. Little did I know then that, fully 20 years later, Java would remain a powerful force in my own career, now at Oracle.

To those on the Oracle Java development team (many of whom worked at Sun before Oracle acquired the company in 2010) who helped develop this list: Thank you. My thanks also to Andrew Binstock, the former editor in chief of Java Magazine; my colleague Margaret Harrist, who in 2006 was the content marketing strategist for Sun’s software division; and Java community members such as you, many of whom I talked with while doing this research, including Jeanne Boyarsky, Sharat Chander, Aurelio García-Ribeyro, Manish Gupta, Manish Kapur, Stuart Marks, Mani Sarkar, Venkat Subramaniam, and Dalibor Topic.

And now for the top 25 greatest Java apps ever written…

Final frontier

Worlds of space

1. Maestro Mars Rover controller. In 2004, Java became the first programming language to expand humanity’s planetary reach. For three months that year, NASA scientists at the Jet Propulsion Laboratory (JPL) in Pasadena, California, used the Java-based Maestro Science Activity Planner built by JPL’s robot interface lab to control the Spirit Mars Exploration Rover as it explored the red planet. Experimentation with Java had begun many years earlier at JPL via the creation of a command and control system for the 1995 Mars Sojourner. Java founder James Gosling spent so much time at JPL that he became an advisory board member.

2. JavaFX Deep Space Trajectory Explorer. Planning a space flight? You may need tools from a.i.solutions, a US aerospace contractor whose products and engineering services have been used by defense companies and civilian space agencies for more than 20 years.

The company’s JavaFX Deep Space Trajectory Explorer lets trajectory designers calculate deep space three-body system paths and orbits. The application can generate multidimensional views and models for any planet-moon system or asteroid and filter millions of points in a dense visual search.

3. NASA WorldWind. The work of rocket scientists became free for all to use with NASA’s release of the open source WorldWind, an SDK for a virtual globe that lets programmers add the US space agency’s geographic rendering engine to their own Java, web, or Android apps. Going far beyond Google Earth, WorldWind’s geospatial data is generated by NASA engineers who visualize terrain from elevation models and other data sources. According to the website: “Organizations around the world use WorldWind to monitor weather patterns, visualize cities and terrain, track vehicle movement, analyze geospatial data, and educate humanity about the Earth.”

4. JMARS and JMoon. Publicly available since 2003 and still commonly used by NASA scientists, Java Mission-planning and Analysis for Remote Sensing (JMARS) is a geospatial information system written by the people at Arizona State University’s Mars Space Flight Facility. JMARS for the Moon (called JMoon by lunar scientists) analyzes wide-angle camera images from the Lunar Reconnaissance Orbiter, a robotic spacecraft that, since its launch in 2009, has been orbiting the moon at an altitude of 50 to 200 kilometers and sending its observations to NASA’s Planetary Data System.

5. Small Body Mapping Tool (SBMT). Popular among space scientists and developed at the Johns Hopkins University Applied Physics Laboratory, SBMT uses data from spacecraft missions to visualize irregular bodies such as asteroids, comets, and small moons in 3D. SBMT is written in Java and uses the open source Visualization Toolkit (VTK) for 3D graphics in Java. Flight mission teams for Dawn, Rosetta, OSIRIS-REx, and Hayabusa2 have all used SBMT as they explored comets, asteroids, and a dwarf planet.

Data intensity

Worlds of space

6. Wikipedia Search. It’s fitting that an encyclopedia for the people, by the people should run on open source software—and feature a search engine powered by Java. Lucene, written by Doug Cutting in 1999 and named after his wife’s middle name, was actually the fifth search engine Cutting developed. He created the others as an engineer for Xerox PARC, Apple, and Excite. In 2014, Wikipedia replaced the Lucene engine with Elasticsearch, a distributed, REST-enabled search engine also written in Java.

7. Hadoop. Lucene isn’t the only Cutting creation to make our list. Inspired by a Google research paper describing the MapReduce algorithm for processing data on large clusters of commodity computers, in 2003 Cutting wrote an open source framework for MapReduce operations in Java and named it Hadoop, after his son’s toy elephant. Hadoop 1.0 was released in 2006, spawning the big data trend and inspiring many companies to collect “data lakes,” strategize on mining their “data exhaust,” and describe data as “the new oil.” By 2008, Yahoo (where Cutting worked at the time) claimed their Search Webmap, running on a Linux cluster of 10,000 cores, was the largest production Hadoop application in existence. By 2012, Facebook claimed to have more than 100 petabytes of data on the world’s largest Hadoop cluster.

8. Parallel Graph AnalytiX (PGX). Graph analysis is about understanding relationships and connections in data. PGX is one of the world’s fastest graph analytics engines, according to benchmarks. Written in Java and first publicized in 2014 by a team led by Oracle Labs researcher Sungpack Hong, PGX lets users load up graph data and run analytics algorithms such as community detection, clustering, path finding, page ranking, influencer analysis, anomaly detection, path analysis, and pattern matching on them. Use cases abound in health, security, retail, and finance.

9. H2O.ai. Machine learning (ML) has a steep curve—and that can keep domain experts from implementing great ML ideas. Automated ML (AutoML) helps by inferring some of the steps in the ML process, such as feature engineering, model training and tuning, and interpretation. The open source, Java-based H2O.ai platform created by Java Champion Cliff Click aims to democratize AI and act as a virtual data scientist for those just getting started, as well as to help ML experts become more efficient.

Worlds of fun

Worlds of fun

10. Minecraft. The peaceful environment of this game—comprising biomes, people, and abodes that you build yourself out of blocks—holds an enduring fascination for children and adults everywhere, making it the most popular video game in history. Developed in Java by Markus “Notch” Persson and released in alpha in 2009, Minecraft and its 3D universe are a never-ending source of creativity, because no two spawned worlds are alike. The video game’s use of Java also lets programmers at home and school create their own mods.

11. Jitter robot and leJOS. Before the autonomous Roomba vacuum cleaner, there was the Jitter. A prototype robot built to suck up particles floating in the International Space Station (ISS), Jitter was able to navigate in zero gravity, bouncing off walls and using a gyroscope to orient itself. According to one report, Russian cosmonauts found the robot’s xyz rotation handling impressively reminiscent of how the ISS itself controlled its orientation. Jitter is the most out-of-this-world prototype of leJOS, the Java Virtual Machine for Lego Mindstorms, Lego’s hardware-software environment for developing programmable robots from toy building blocks. The toy OS dates back to the TinyVM project of 1999 started by José Solorzano, which morphed into leJOS and was led by Brian Bagnall, Jürgen Stuber, and Paul Andrews. This full-featured environment has many robotics programming-specific classes simplified by the object-oriented nature of Java, letting anyone take advantage of advanced controllers and behavioral algorithms.

12. Java applets. The word applet first appeared in 1990 in PC Magazine, according to the Oxford English Dictionary. But applets didn’t truly take off until Java came along in 1995. Java applets were small programs that could launch in a web page (in a frame, a new window, Sun’s AppletViewer, or a testing tool) and run on a JVM separate from the browser. Some credit Minecraft’s early success to the fact that players could play in a web browser via Java applets rather than having to download and install the game. Although Java applets have been deprecated since Java 9 and they were removed in 2018 from Java SE 11, for a time they were the fastest game in town. Fun fact: Java applets could also access 3D hardware acceleration, making them popular for scientific visualizations.

Code of honor

Worlds of coding

13. NetBeans and the Eclipse IDE. The integrated development environment that first entranced the Java world was NetBeans, started at Charles University in Prague in 1996 (under the name Xelfi) and commercialized in 1997 by a company of the same name founded by entrepreneur Roman Staněk. Sun bought the modular IDE, which supports all Java application types, in 1999 and open sourced it the following year. In 2016, Oracle donated the entire NetBeans project to the Apache Software Foundation.

Another popular Java-based integrated development environment is the open source Eclipse IDE, which can be used not only for Java coding but also for other programmling languages ranging from Ada to Scala. Launched in 2001 by IBM and based on IBM VisualAge, the Eclipse SDK is meant for Java developers but can be extended via plugins. The Eclipse IDE was spun out of IBM into the Eclipse Foundation in 2004, and it remains one of the top IDEs available.

14. IntelliJ IDEA. There are many IDEs, but IntelliJ IDEA became a favorite after its 2001 introduction. Today, IntelliJ IDEA is the framework for many IDEs for languages as diverse as Python, Ruby, and Go. Written in Java, IntelliJ IDEA and the suite of related JetBrains IDEs add productivity and navigation features that many developers have come to rely upon. These include code indexing, refactoring, code completion (which predates the text autocomplete on smartphones), and dynamic analysis that spots errors (similar to a spellchecker). “IntelliJ IDEA has helped overcome the challenges of managing and debugging Java and JVM-based complex applications under one framework,” says Java Champion Mani Sarkar, a freelance software and data engineer based in the UK. “They make developers feel effective, productive, and above all happy when using their tools.”

15. Byte Buddy. Oslo-based software engineer Rafael Winterhalter, creator of the open source Java library Byte Buddy, admits to dedicating his life—sometimes with maddening focus—to what amounts to a small niche. Nonetheless, the fruit of his dedication is wildly popular: The Byte Buddy runtime code generation and manipulation library, used in Java tools such as Hibernate and Mockito, is downloaded 20 million times a month, says Winterhalter.

16. Jenkins. Created in 2004 by Sun Microsystems engineer Kohsuke Kawaguchi, Jenkins is a powerful open source continuous integration server. Written in Java, Jenkins helps build, test, and deploy applications quickly and automatically. It’s often recognized as one of the early DevOps tools that made “infrastructure as code” possible. Jenkins and its more than 1500 community-contributed plugins tackle myriad deployment and testing tasks, from working with GitHub, to supporting color-blind developers, to providing a MySQL Connector JAR file.

17. GraalVM. A team of researchers in Zurich, led by Oracle Labs’ Thomas Wuerthinger, has spent years honing three ideas: What if you wrote a compiler in Java (the original JVM is written in C)? What if it could run any program written in any language? And what if it were blazingly efficient? Sixty published research papers later, GraalVM beat the odds and became a commercial product. Among the enthusiastic fans of this technology is Twitter, which uses GraalVM to improve their service’s speed and compute efficiency.

18. Micronaut. Developers who code for the cloud need to think carefully about how much memory their application uses—and how the app uses that memory. “You have to make the app very responsive to restarts, and failover, and shutting down and coming back up again, and making it optimized in terms of startup time and memory consumption,” says Graeme Rocher, creator of Micronaut, a Java framework for microservices that uses annotation metadata so the JVM can compile the app’s bytecode efficiently.

19. WebLogic Tengah. In 1997, WebLogic Tengah became the first substantial implementation of an enterprise Java server. “It predated Java 2 Enterprise Edition and became BEA’s principal offering, which eventually led to Oracle’s acquisition of BEA Systems,” says Andrew Binstock, former editor in chief of Java Magazine and of Dr. Dobb’s Journal. Around the same time, IBM’s success with the San Francisco Project, a business object framework, “was what really moved Java from a new, interesting thing that the cool kids were playing with and made it a serious business tool,” Binstock says. Today, Oracle WebLogic Server remains the leading Java application server. An alternative still thrives, however: The open source application server GlassFish, started at Sun in 2005, was donated in 2018 to the Eclipse Foundation.

20. Eclipse Collections. There’s a reason many high-paying developer jobs at investment banks, stock exchanges, and other financial services companies require strong Java skills: The programming language is adept at handling concurrency, the management of multiple execution threads common in high-frequency trading and other large-scale financial transactions. Originally known as Goldman Sachs Collections and later donated to the Eclipse Foundation, Eclipse Collections expands on native Java’s performance-intensive features “with optimized data structures and a rich, functional, and fluent API,” says Java Champion Mani Sarkar. Sarkar notes that Eclipse Collections contains caching, primitives support, concurrency libraries, common annotations, string processing, input/output, and more.

21. NSA Ghidra. At the 2019 RSA Conference in San Francisco, the U.S. National Security Agency introduced a Java-based open source tool called Ghidra, which security researchers and practitioners now use to understand how malware works and check their own code for weaknesses. This reverse-engineering platform can decompile software from machine language back into source code (languages such as Java). The tool has a storied, if not infamous, history: Its existence was revealed to the public in March 2017 via WikiLeaks.

Mapping the genome

Worlds of genomics

22. Integrated Genome Browser. The race to map the human genome started in 1990 and ended 13 years later, when medical researchers succeeded in sequencing the 3 billion DNA base pairs of biotechnologist Craig Venter, after a decade of work involving 3,000 people at a cost of US$3 billion. Once the sequence was completed, scientists were raring to dive into our species’ source code—but how? Enter the Java-based genome browser, a visualization tool developed by a team including bioinformatics professor Ann Loraine, to explore both the foundational datasets and the reference gene annotations. The open source Integrated Genome Browser lets researchers zoom into, pan, and graph genomic data in order to identify and annotate genetic features. In keeping with this worldwide effort, a similar tool comes from the University of California Santa Cruz in the form of the Genome Browser, managed by Jim Kent.

23. BioJava. Launched in 2000 and still going strong, BioJava is an open source library for processing biological data, a field known as bioinformatics. Scientists using this library can work with protein and nucleotide sequences and study data on gene-to-protein translation, genomics, phylogenetic development, and macromolecular structures. The project is supported by the Open Bioinformatics Foundation, and its contributors worldwide are funded by a variety of pharmaceutical, medical, and genomics interests. “BioJava is a popular option for method and software development thanks to the tooling available for Java and its cross-platform portability,” writes Aleix Lafita and colleagues in a 2019 paper titled “BioJava 5: A community-driven open source bioinformatics library.” The paper goes on to note that BioJava had accepted contributions from 65 different developers since 2009, and over the previous year had accumulated 224 forks and 270 stars on GitHub and had been downloaded more than 19,000 times.

Favorite ‘things’

Worlds of iot

24. VisibleTesla. This Java-based app was created by Tesla automobile enthusiast Joe Pasqua in 2013 as a free program to monitor and control his Tesla Model S. VisibleTesla, inspired by the Tesla Motors Club community, offers features similar to those found on the electric car maker’s official mobile app. Users can set up geofencing and notifications for things such as an unlocked door or the state of charge, as well as collect and manipulate trip data. The project’s open source code is on GitHub.

25. SmartThings. The Internet of Things (IoT) application developed by SmartThings, cofounded in 2012 by Alex Hawkinson and later funded with US$1.2 million raised on Kickstarter, lets you control and automate everything from household lights, locks, coffee makers, thermostats, and radios to home security systems—all through a smartphone or tablet. The application uses the Java-based Micronaut framework (see #18) so its cloud-based services can operate at subsecond speeds. The company was acquired by Samsung Electronics in 2014 for a cool US$200 million.

But wait, there’s more. After this article was published, we received hundreds of comments on Reddit, Slashdot, Hacker News, and Twitter, and it inspired many letters to the editor. The piece even received happy social media posts from those who made the list. See the feedback in “The code underpinning the Brazilian healthcare system—and other world-changing Java applications.”

Alexa Morales

Alexa Weber Morales is director of developer content at Oracle. Morales is the former editor in chief of Software Development magazine and has more than 15 years of experience as a technology content strategist and journalist.

The 10 most popular Java Magazine articles

The best of 2020: The 10 most popular Java Magazine articles

Read them, reread them, share them.

Download a PDF of this article

Alan Zeichick

February 19, 2021

Did you read the one about records? The article about code review antipatterns? Elasticsearch? How about the listing of the 25 greatest Java applications ever written—from Minecraft to the U.S. National Security Agency’s Ghidra? Lambda expressions, anyone?

These were the 10 stories that were most widely read. We hope you will enjoy spending a few minutes revisiting the best of 2020.

#1

The 25 greatest Java apps ever written

From space exploration to genomics, from reverse compilers to robotic controllers, Java is at the heart of today’s world. Here are a few of the countless Java apps that stand out from the crowd.
by Alexa Weber Morales

#2

Records come to Java

A first look at how Java 14’s data records will change the way you code
by Ben Evans

#3

Inside Java 15: Fourteen JEPs in five buckets

Hidden classes, sealed classes, text blocks, records, and EdDSA: There’s lots of goodness in JDK 15.
by Alan Zeichick

#4

Modern Java toys that boost productivity, from type inference to text blocks

Developers using older versions of the Java platform are missing out.
by Angie Jones

#5

Programming the GPU in Java

Accessing the GPU from Java unleashes remarkable firepower. Here’s how the GPU works and how to access it from Java.
by Dmitry Aleksandrov

#6

Five code review antipatterns

Everyone cares about best practices, but worst practices can sometimes be more illuminating.
by Trisha Gee

#7

Easy searching with Elasticsearch

Using Elasticsearch’s high- and low-level APIs to search synchronously and asynchronously
by Henry Naftulin

#8

12 recipes for using the Optional class as it’s meant to be used

Follow these dozen best practices to protect your applications against ugly null pointer exceptions—and make your code more readable and concise.
by Mohamed Taman

#9

Understanding the JDK’s new superfast garbage collectors

ZGC, Shenandoah, and improvements to G1 get developers closer than ever to pauseless Java.
by Raoul-Gabriel Urma and Richard Warburton

#10

Behind the scenes: How do lambda expressions really work in Java?

Look into the bytecode to see how Java handles lambdas.
by Ben Evans