• Concurrent programming in Java with virtual threads

    Introduction

    Java virtual threads are lightweight threads designed to increase throughput in concurrent applications. Pre-existing Java threads were based on operating system (OS) threads that proved insufficient to meet the demands of modern concurrency. Servers nowadays must serve millions of concurrent requests, but the OS and thus the JVM cannot efficiently handle more than a few thousand threads.

    Currently, programmers can either use threads as the units of concurrency and write synchronous blocking code in the thread-per-request model. These applications are easier to develop, but they are not scalable because the number of OS threads is limited. Or, programmers can use other asynchronous/reactive models that reuse threads without blocking them. Such applications, while having much better scalability, are much more difficult to implement, debug, and understand.

    Read on →

  • Reactive Streams specification in Java

    Introduction

    Reactive Streams is a cross-platform specification for processing a potentially infinite sequence of events across asynchronous boundaries (threads, processes, or network-connected computers) with non-blocking backpressure. A reactive stream contains a publisher that sends forward data, error, completion events, and subscribers that send backward request and cancel backpressure events. There can also be intermediate processors between the publisher and the subscriber that filter or transform events.

    Backpressure is application-level flow control from the subscriber to the publisher to control the sending rate.

    The Reactive Streams specification is designed to efficiently process (in terms of CPU and memory usage) time-ordered sequences of events. For efficient CPU usage, the specification describes the contracts for asynchronous and non-blocking events processing in different stages (producers, processors, consumers). For efficient memory usage, the specification describes the contracts for switching between push and pull communication models based on the events processing rate, which avoids using unbounded buffers.

    Read on →

  • Java Reflection, part 2: fields, methods, constructors

    Introduction

    Reflection is the ability of an application to examine and modify its structure and behavior at runtime. The ability to introspect structure consists in the presence of the Core Reflection API for reading classes and their fields, methods, constructors, member classes and member interfaces. The ability to modify behavior consists in the presence of this API for getting and setting field values, invoking methods, and creating new instances using constructors.

    The Member interface and its implementations - the Field, Method, and Constructor classes represent reflected fields and methods (which are members of classes and interfaces, according to the Java Language Specification) and constructors (which are not members).

    This article is based on the Java 17 implementation in Oracle OpenJDK.

    Read on →

  • Java Reflection, part 1: primitives, arrays, classes

    Introduction

    Reflection is the ability of a program to introspect and modify its structure and behavior at runtime. The Java language supports some reflection features in its Core Reflection API which consists of classes from the java.lang.reflect package, as well as the Class, Package, and Module classes.

    The first step in using reflection on a type (primitive type, array type, class or interface) is to obtain a Class object and determine the parameters of that type. The next steps may include using the methods of this Class object to determine its fields, methods, constructors, member classes and member interfaces, annotations, generic types, and others.

    This article is based on the Java 17 implementation in Oracle OpenJDK.

    Read on →

  • Building a CI/CD pipeline for an AWS Lambda function using AWS CodePipeline

    Building a CI/CD pipeline for an AWS Lambda function using AWS CodePipeline

    A guide on building a CI/CD pipeline for a serverless Java application using AWS Lambda, AWS Serverless Application Model (AWS SAM), and AWS CodePipeline.

    Introduction

    Continuous Integration, Continuous Delivery, Continuous Deployment (CI/CD) are software development practices for producing software in short cycles between merging source code changes and updating applications. The ultimate goal of these practices is to reduce the costs, time, and risks by delivering software in small pieces.

    The AWS Cloud has a complete set of tools for building CI/CD pipelines for various types of server, serverless and container applications. AWS CodePipeline is the service that automates the stages of CI/CD pipelines. Typically these stages include pulling source code using AWS CodeCommit, building artifacts using AWS CodeBuild, and deploying applications using AWS CodeDeploy.

    Serverless applications in the AWS Cloud have specialized tools for building CI/CD pipelines. The AWS Serverless Application Model (AWS SAM) is a framework based on AWS CloudFormation that simplifies the development of serverless applications based on AWS Lambda.

    Read on →