A journey through 30 years of API evolution

Vipin Menon
Introduction

Java, since its inception in 1995, has become one of the most influential programming languages. Its promise of “Write Once, Run Anywhere” (WORA) transformed the landscape by offering a platform-independent, object-oriented programming environment. Over 30 years, the evolution of Java APIs showcases constant innovation. From portability to cloud-native apps, machine learning, and distributed systems. This blog takes you how Java has evolved and shaped its API ecosystem as we know it today.

Packages

A Java package is a namespace or container that organizes related classes, interfaces, and sub-packages into a modular structure. Each package serves a specific purpose and improve code management. Java supports both built-in and user-defined packages. This discussion focuses on the evolution of built-in packages and their adaptation to industry requirements.

The java.lang package contains the fundamental classes. java.util provides utility classes. java.io is defined for input and output operations, while java.nio introduces asynchronous capabilities for I/O. java.awt enables graphical user interfaces (GUI), and java.net supports network applications. java.sql facilitates database communication, and javax is introduced as an extension to the JDK focused on extending core functionalities, particularly for enterprise applications.

java and its core api structure
The Foundation (Java 1.0 – 1.4)

When Java first appeared in 1995, it aimed to provide a platform-independent language. This allowed developers to build applications capable of running anywhere once built. Java 1.0 was simple, robust, and lightweight. It offered minimal yet essential APIs that formed the building blocks of the Java ecosystem.

  • java.lang: classes like String, Math, Exceptions and Threads. String helped in manipulating the text. Math helped with mathematical calculations, Exceptions were one of the key feature providing a structured mechanism to handle unexpected errors during program executions. While threads provide a way for a Java program to perform multiple tasks at the same time
  • java.util: Classes like List, Set, and Map as part of the Java Collections Framework. List for indexed data with duplicates, Set for unique elements and Map for <key, value> pairs ensuring each key is unique. This package also contained Logging classes which could be used in Java applications for logging messages such as errors, warnings, and informational messages.
  • java.io: Classes mainly for file operations like InputStream, OutputStream, Reader and Writer developers to read and write data.
  • java.nio: Classes for non-blocking I/O operations, including buffers, channels, and selectors.
  • java.awt: Classes for creating windows, buttons, menus, text fields, labels and other common GUI interfaces. Later, Swing largely replaced it.
  • java.net: Classes for network communication such as Socket and URL, enabling developers to create web-based applications.
  • java.sql: Classes like Connection, statement, ResultSet and for jdbc interface for connecting and executing queries with relational databases, allowing Java applications to interact with databases in a platform-independent way.
  • javax: Classes like swing, xml that extended the functionality of the core java package.

The evolution of the APIs clearly followed industry demands and remained up to date. It started with basic language functionality and I/O support. It then expanded into a comprehensive set of libraries and tools. These offered powerful capabilities for GUI development, distributed systems, networking, and database access. These versions primarily focused on providing developers with the necessary tools to build cross-platform applications. This led to the introduction of JDBC (Java Database Connectivity). It served as a powerful interface to allow Java applications to interact with databases in enterprise applications.

Java in Enterprise World (Java 1.5 – 1.8)

As the internet evolved, the need for scalable and robust enterprise applications became evident. This led Java to position itself as the go-to language for large-scale applications. Java 5 through Java 8 introduced a series of critical API, marking the golden era of Java.

  • java.lang: features like Enum, StringBuilder, ThreadLocal, Lambda , Annotations. Enum allows collection of constants. StringBuilder handles mutable strings efficiently. ThreadLocal helps to store data that is specific to a particular thread. Lastly, Lambda introduced functional programming in Java. Annotations helped to associate metadata to program elements which later became a stepping stone for frameworks like Spring and Hibernate.
  • java.util: Classes like ConcurrentHashMap, Streams, Generics, Optional. ConcurrentHashMap introduced concurrent read and write operations without locking the entire Map. Streams helps with a functional approach to process collections of objects. Generics introduced parameterised types to enhance type safety. Optional is used to represent a value that may or may not be present, helping to prevent NullPointerExceptions.
  • java.io: Classes Console for reading from and writing to the console. BufferedReader and BufferedReader enhancements with lines() method to work with file lines using functional programming there by allowing better integration with streams API.
  • java.nio: Introduced File class. Unlike io, it used platform independent path with support for non-blocking and memory mapped I/O.
  • java.awt: Improved EventHandling due to Lambda expressions. Enhanced java webstart integration and javafx integration.
  • java.net: try-with-resources, SocketChannel, HTTP Client API. try-with-resources manage the lifecycle of network resources automatically. SocketChannel allowed for non-blocking I/O operations. HTTP Client API was introduced as a preview for handling of HTTP requests and responses.
  • java.sql: Introduced JDBC 4.0, java.time types and Stream API support for ResultSet. 4.0 brought in automatic driver loading, connection pooling and better exception handling. time type helped to use LocalDate, LocalDateTime, ZonedDateTime directly within JDBC. Stream helped to enhance resultset with functional processing.
  • javax: Addition of JAXB, JAX-WS, javax.tools, javax.script. JAXB helped easier conversion between Java objects and XML documents. JAX-WS introduced tooling for web services. javax.tools applications to compile Java code at runtime programmatic. javax.script allowed Java to interact with scripting languages like JavaScript, Python.

These features positioned Java as a modern, multi-paradigm programming language capable of handling complex, high-performance applications.

Java in Cloud Native Era (Java 9-17)

The introduction of Java Platform Module System (JPMS) was the most significant change introduce from Java 9. The module system introduced the ability to modularize code with module-info.java files, enabling better organization of large code bases. It also allowed developers to define dependencies and encapsulate packages within modules. java.base, java.sql, and others were modularized, breaking the monolithic JDK into individual modules. New modules like java.logging, java.management, java.rmi, java.scripting were also introduced maintaining backward compatibility with older versions. Although Java introduced many modules as part of JPMS, we will focus our discussion on the core API. We will also explore how this change impacted them to maintain the flow of the topic.

core api structure from Java 9 and above
  • java.lang: With StackWalker, we can now traverse specific stack frames of interest instead of working with the entire stack trace. The String class was enhanced with the strip() method to better handle whitespace. The var keyword allows for declaring variables without the need to explicitly specify their types. Additionally, NullPointerExceptions now provide more detailed information about which object was null. Introduction of sealed classes and interfaces could restrict which classes can extend or implement them.
  • java.util: Optional allows user-defined exception and can return an alternate value if empty. Stream.takeWhile() and Stream.dropWhile() can take or drop elements based on the predicate conditions. copyOf() can create immutable copies of collections.
  • java.io: InputStream.transferTo() can efficiently transfer data from an InputStream to an OutputStream while properly managing the closure of the stream resources.
  • java.nio: Files.writeString() and Files.readString() simplify reading from and writing to text files, and they automatically handle character encoding.
  • java.awt: The package was moved under java.desktop package. A new rendering pipeline for AWT and Swing applications on macOS, utilizing Apple’s Metal API instead of OpenGL. Improved java.awt.Font with better customisation.
  • java.net: Enhanced HTTP/2 support, including the ability to manage multiple streams over a single connection. cached SecureRandom instances for faster communications over protocols like SSL/TLS.
  • java.sql: Introduced java.sql module separate from core. Launch single-file source code programs (JEP 330) can help run database queries and interact with JDBC in a simple program. It is especially useful for quick tests or scripts.
  • javax: The most significant change in the javax package occurred after Java 11, with the transition of Java EE (Enterprise Edition) to the Jakarta EE project under the Eclipse Foundation. This transition led to the javax namespace being replaced with the jakarta namespace. This marked the deprecation of javax from JDK.
Scalable Solutions (Java 18-23)

Java addressed scalability and concurrency in these versions with the introduction of virtual threads, as part of Project Loom. Project Panama improves Java’s ability to interface with native libraries. It enhances performance and reduces boilerplate code in native interactions. Java’s core libraries were robust, but improvements in other areas of the language and JVM enhanced the overall ecosystem. These changes made it more efficient and better able to leverage the existing API.

  • java.lang, java.util: RecordPatterns (EP 405) introduced a pattern-matching feature that allows a more concise way to match and de structure records. Squential Collections (EP 431) Introduced new interfaces to represent collections with a defined encounter order. Virtual Threads (JEP-444) were introduced which could execute large numbers of concurrent tasks, such as web servers or network applications.
  • java.io, java.nio: The Foreign Function and Memory API (JEP 454) helps Java programs to interoperate with code and data outside of the Java runtime. UTF-8 by default (JEP 400) helped Java programs more predictable and portable.
  • java.net: Structured Concurrency improves the efficiency and manageability of handling concurrent network operations particularly when dealing with multiple network requests or responses happening simultaneously. jwebserver as a command line utility to serve static files.
Future and Beyond (Java 24 – )

When Java 24 releases in March 2025, it will introduce several features. These will enhance cloud environments, improve startup performance, and increase resource management efficiency. Notable among these are Ahead-of-Time (AOT) class loading and linking (JEP 483) to boost startup times. Another feature is Compact Object Headers (JEP 450), which minimize the in-memory size of Java objects. With these improvements, Java is positioning itself as an ideal platform for cloud-native developers. It enables them to take full advantage of these new capabilities.

Conclusion

Over the past 30 years, the Java API ecosystem has evolved. It has catered to the diverse and ever-changing needs of the software development world. Java has shown an unparalleled ability to adapt to its surrounding demands. As we look ahead, this rich ecosystem of API will drive Java’s evolution. This will ensure its place at the forefront of the programming world for years to come.

Total
0
Shares
Previous Post
Java turns 30 in 2025

30 Years of Java, 25 Years of Enterprise Java

Next Post
Illustration of Duke, the Java mascot, pointing at a large cylindrical database icon. Surrounding it are six browser-style windows representing different data models, including relational tables, graph structures, and other database representations. The background is red, emphasizing Java’s association with data and databases.

A Look Back at Java’s 30-year Journey with Databases

Related Posts