41,99 €
Explore the Java Virtual Machine with modern programming languages
This book is meant for programmers who are interested in the Java Virtual Machine (JVM) and want to learn more about the most popular programming languages that can be used for JVM development. Basic practical knowledge of a modern programming language that supports object-oriented programming (JavaScript, Python, C#, VB.NET, and C++) is assumed.
Anyone who knows software development knows about the Java Virtual Machine. The Java Virtual Machine is responsible for interpreting Java byte code and translating it into actions. In the beginning, Java was the only programming language used for the JVM. But increasing complexity of the language and the remarkable performance of the JVM created an opening for a new generation of programming languages. If you want to build a strong foundation with the Java Virtual Machine and get started with popular modern programming languages, then this book is for you.
The book will begin with a general introduction of the JVM and its features, which are common to the JVM languages, helping you get abreast with its concepts. It will then dive into explaining languages such as Java, Scala, Clojure, Kotlin, and Groovy and will show how to work with each language, their features, use cases, and pros and cons. By writing example projects in those languages and focusing on each language's strong points, it will help you find the programming language that is most appropriate for your particular needs.
By the end of the book, you will have written multiple programs that run on the Java Virtual Machine and know about the differences between the various languages.
This practical, example-filled guide will help you get started with the JVM and some of its most popular languages.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 500
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: June 2017
Production reference: 1230617
www.packtpub.com
Author
Vincent van der Leun
Copy Editor
Gladson Monteiro
Reviewer
Ramasubramanian Sankar
Project Coordinator
Ulhas Kambali
Commissioning Editor
Aaron Lazar
Proofreader
Safis Editing
Acquisition Editor
Nitin Dasan
Indexer
Rekha Nair
Content Development Editor
Vikas Tiwari
Graphics
Abhinash Sahu
Technical Editor
Subhalaxmi Nadar
Production Coordinator
Shantanu Zagade
Vincent van der Leun is a software engineer living in the city of Utrecht in the Netherlands. Programming since the age of 8, he has worked with many different languages and platforms over the years. Rediscovering Java a few years ago, he loved it so much that he became an Oracle Certified Professional, Java 7 Programmer, and started the JVM Fanboy blog. Currently he works for CloudSuite, a company specializing in modern e-commerce solutions. At CloudSuite he works on various backend systems and web services, writes JavaScript code for frontend applications, supports consultants by providing complex SQL queries, and consumes coffee while having design-related discussions with fellow developers. When not trying out new web frameworks or technologies in his spare time, he is collecting cult movies and obscure action flicks on DVD/Bluray, reading classic science fiction novels, or attending concerts of non-mainstream singers and songwriters.
Ramasubramanian Sankar is a passionate, polyglot, fullstack developer, and a seasoned technical architect working in the Information Technology industry for over 13 years now. Specializing on JVM-based backend services and distributed systems, he has experience with a diverse set of platforms and languages. After having worked with service companies, banks, antivirus product companies, and product-based start-ups, he is currently working as a consultant for Ajira technologies in Chennai with a group of like-minded technologists. He is passionate about architecting and designing simple, high-performant, and clean solutions for complex business problems. He writes/rants about his learnings on Twitter (@ramsankar83) and on his technology blog (http://technicalitee.blogspot.in/). His current interest is in learning functional programming and putting it to practical use. He loves LISP and is actively looking forward to use it in production some day.
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/178712794X.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
Java Virtual Machine
JVM implementations
Why develop on JVM?
JVM adapts to market changes
Java Class Library
Ecosystem
Scenario 1 – Using a JVM application server
Scenario 2 – Using a general high-level web application framework
Scenario 3 – Using a microservice framework
Popular use cases
Web applications
Big data
IoT
JVM concepts
Virtual machine
The JIT compiler
Primitive datatypes
Classes
Reference types
References and null references
Garbage collector
Example
Backward compatibility
Build tools
Java editions
Java SE
Java EE
Example – Java Persistence API as implemented by two application servers
Java ME
Other languages on JVM
Why choose a language other than Java?
Java is a very verbose language
Java is not ideal for everything or everyone
Missing classes in Java Class Library
Mixing JVM languages in a project
Increasing build process complexity
Language runtime libraries
Writing unit tests in a different language
Summary
Developing on the Java Virtual Machine
JDK
Installing JDK
Downloading JDK
Installing JDK on Windows
Installing JDK on macOS
Installing JDK on Linux
Downloading API documentation
Exploring JDK
The directory structure
JDK commands
GUI monitoring tools
Java VisualVM
Oracle Mission Control
JConsole
JRE
Class organization with packages
What are packages?
Choosing a package name
Package name examples
Fully qualified class name
Java Class Library
Java Class Library organization
Package overview
Fundamental classes of the java.lang package
The Object class (java.lang.Object)
Important object methods
The String class (java.lang.String)
Primitive wrapper classes (Integer, Long, Short, Char, Float, Double in java.lang)
Autoboxing examples
Exceptions and errors (java.lang.Exception and java.lang.Error)
The Collections API - java.util.ArrayList and java.util.HashMap
ArrayList (java.util.ArrayList)
Commonly used methods of the ArrayList class
ArrayList usage example
HashMap (java.util.HashMap)
Commonly used methods of the HashMap class
HashMap usage example
Preparing your classes for the Collections API
About hashCode()
About equals ()
The hashing mechanism
Running JVM applications on the command line
At least one class must have a static main() method
Required directory structure for class files
Setting ClassPath for a JVM instance
Placing class files inside a JAR archive
Runnable JAR file
Running a program with the java command
Run a project consisting of separate class files
Running a project that is placed inside a runnable JAR file
Other useful parameters of the java command
-D to pass properties and values
-ea to enable assertions
A hands-on example project to run on JVM
A ClassPath example
Eclipse IDE
Downloading Eclipse IDE
Installing Eclipse IDE
Summary
Java
OOP in Java
Defining classes
Class access modifiers
Final class modifier - locking a class
Defining packages
Importing classes
Adding class members - variables and methods
Instance variables
Methods
Modifiers
Protecting class members with access modifiers
Access modifier example
Static modifier - instance variables and class variables
Final modifier - locking a class member
Overloading methods
Constructors and finalizers
Constructors
Finalizers
Extending a class
Overriding methods
Calling constructors of a parent class
Abstract classes
Interfaces
Upcasting and downcasting
Writing Java code
Operators
Conditional checks
The if...else statement
The switch...case statement
POJO
Arrays
Generics and Collections
Loops
The for loop
The normal for loop
The enhanced for loop
The while loop
The do...while loop
Exceptions
Runtime exceptions
Threads
Lambdas
Style guide
Quiz
Summary
Java Programming
Configuring Eclipse IDE
Creating a web service in Java
Creating a new Gradle project in Eclipse IDE
Exploring the generated project
Modifying the Gradle build file
Building the project
Coding the backend class
Backend class business rules
Creating a dummy implementation of the method
Creating the test case class and writing its first unit test
Implementing an input validation check
Writing the second unit test
Implementing the business logic
Creating an executable application task
Creating a web service
Running the web service
Creating Javadoc documentation
Summary
Scala
Installing Scala
Scala's Read-Eval-Print-Loop shell
Functional versus imperative programming
Scala language syntax and rules
Statically typed language
Mutable and immutable variables
Common Scala types
Any class
AnyRef class - reference classes
AnyVal class - value classes
Strings
OOP in Scala
Defining packages and subpackages
Importing members
Defining classes
Instance variables and methods
Instance variables
Instance methods
Access modifiers for class instance members
Constructors
Extending a class
Overriding methods
Overloading methods
Abstract classes
Traits
Singleton objects
Operator overloading
Case classes
Scala's standard library
Generics
Collections
Immutable list
Mutable list
Immutable map
Mutable map
XML processing
Functional programming in Scala
Iterating through collections using functions
The map, filter, and reduce design pattern
Map - transform data
Filter - filter items from a collection or array
Reduce - for performing calculations
Currying
Quiz
Summary
Scala Programming
Scala IDE for the Eclipse plugin
Installing Scala IDE for Eclipse
Switching to the Scala IDE perspective
SBT
Installing SBT
Creating an SBT-based Eclipse IDE project
Creating a new SBT project
Loading the SBTEclipse plugin
Generating a new Eclipse IDE project with SBTEclipse
Importing the generated project in Eclipse IDE
The Scala compiler (scalac)
Creating a singleton object with the main() method
Creating a singleton object that extends the App trait
Creating an Akka project
Adding an Akka dependency to the SBT build file
Updating the Scala IDE project
Akka concepts
Actors
Actor references (ActorRef)
Messages
Dispatchers
Creating our first Akka actor - QuotesHandlerActor
Creating messages
Writing a ScalaTest-based unit test
Implementing a message handler
Creating QuotePrinterActor
The main application
Summary
Clojure
Installing Clojure
Creating a start script
Creating a start script on Windows
Creating a start script on macOS and Linux
Clojure's interactive shell (REPL)
Clojure language
Syntax
Expressions
Defining variables
Defining functions
Data structures
Numeric types
Strings and characters
Collections
Lists
Vectors
Sets
Hash-maps
Iteration over arrays and loops
Conditions
Working with Java classes
Creating simple Java classes with deftype and defrecord
Managing states with agents
Agent example
Style guide
Quiz
Summary
Clojure Programming
The Counterclockwise plugin for Eclipse IDE
Installing the Counterclockwise plugin
Switching to the Java perspective
Leiningen's build tool
Installing Leiningen
Creating executable programs in Clojure
Compiling to class files without Leiningen
Compiling projects with Leiningen
Creating a new Counterclockwise project
Clojure REPL in Eclipse IDE
Updating the project's Clojure version
Adding a dependency
Exploring monads by applying test-driven development
The Luminus web framework
Creating a Luminus project
Importing the project in Counterclockwise
Exploring the Luminus project
Adding a page to the web application
Summary
Kotlin
Installing Kotlin
Launch scripts
Kotlin's REPL interactive shell
Kotlin language fundamentals
Defining local variables
Defining a function
Kotlin's types
Kotlin basic types
Strings
Null safety handling
Option 1 - Adding a conditional check
Option 2 - Using the safe call operator ?.
Option 3 - Using the Elvis operator ?:
Option 4 - Using the !! operator
Conversions
Collections and generics
Loops
OOP in Kotlin
Defining packages
Importing members
Defining classes and constructors
Adding members to classes
Adding functions
The main entry function
Adding properties
Inheritance
Interfaces
Visibility modifiers
Singleton and companion objects
Data classes
Lambdas and inline functions
Procedural programming in Kotlin
Style guide
Quiz
Summary
Kotlin Programming
Kotlin for the Eclipse IDE plugin
Installing the Kotlin plugin for the Eclipse IDE
Switching to Kotlin perspective
Apache Maven
Installing Apache Maven
Downloading a preconfigured Kotlin starter kit
Importing the project in the Eclipse IDE
Exploring the pom.xml build file
Updating the build file in Eclipse
Creating a JavaFX desktop GUI application
Preparing the project
Creating a runnable application
Writing an extension function
Layout panes
Implementing a BorderPane-based layout
Implementing animation
Debugging the program
Summary
Groovy
Installing Groovy
GroovyConsole and GroovyShell
GroovyConsole
GroovyShell
Groovy Language
Object-oriented programming in Groovy
Groovy is fully object oriented
Access modifiers
Adding properties to a class
Optional types
Automatically creating a fully featured POJO
Creating immutable classes
Groovy Development Kit (GDK)
Groovy Strings (GStrings)
Collections
Lists
Maps
Dynamic and static programming
Meta programming
Static programming in Groovy
Quiz
Summary
Groovy Programming
Installing the Groovy Eclipse plugin
Switching to Java perspective
Apache Ivy and IvyDE
Installing Apache IvyDE plugin for Eclipse IDE
Creating and configuring the project
Creating a new Groovy Eclipse project
Creating an ivy.xml file for Ivy
Java Database Connectivity (JDBC)
H2 database
Creating an in-memory database
Generating XML using MarkupBuilder
Generating XML based on SQL
The Vert.x microservice platform
Adding Vert.x dependency to Ivy
Creating the web service
Summary
Other JVM languages
Oracle Nashorn
Embedding Nashorn in JVM-based projects
Running Nashorn
Jython (Python)
Differences between CPython and Jython
Running Jython
JRuby (Ruby)
Ruby on Rails and JRuby
Running JRuby
Frege (Haskell)
Calling Java code from Frege
Running Frege
Ceylon
Ceylon's module system
Running Ceylon
Summary
Quiz Answers
Chapter 3: Java
Chapter 5: Scala
Chapter 7: Clojure
Chapter 9: Kotlin
Chapter 11: Groovy
The Java Virtual Machine is a mature and very versatile platform for running software that takes full advantage of modern hardware features. While it is true that Java-based applications once could be considered slow, bloated, and extremely memory-hungry, things have improved greatly over the years. It's no coincidence that many mainstream cloud-based services and websites, which often have to serve tens of thousands users simultaneously, are powered by a JVM-based backend.
While Java is, without a doubt, the most popular language used to create applications that run on the JVM, other languages are getting more and more popular every year. This book covers five different JVM-based languages: Java, Scala, Clojure, Kotlin, and Groovy. Some of those languages are statically typed while others are dynamically typed. Likewise, this book covers both object-oriented programming languages and functional programming languages. The JVM is versatile enough to make this all possible.
By covering all these languages in a single book, you can easily compare each language with the others and, hopefully, pick your favorite language by building the sample projects.
Chapter 1, Java Virtual Machine, provides a high-level overview of the Java platform and the Java Virtual Machine (JVM). It describes popular use cases for applications running on the JVM, namely web applications, big data analysis, and Internet of Things (IoT). Also covered are important JVM concepts, including its just-in-time compiler, type system, and garbage collector.
Chapter 2, Developing on the Java Virtual Machine, explains the JVM in more technical detail. Covered are both the installation procedure and organization of the Java Development Kit (JDK) on major operating systems (Windows, macOS, and Linux). Also explained is the organization of the Java Class Library and instructions on how to run JVM-based applications by setting up the ClassPath.
Chapter 3, Java, covers the fundamentals of the Java language. It covers creating classes and instantiating objects based on these classes, adding methods and properties to classes, and Java's access modifiers and other modifiers. Some of the other concepts that are discussed include abstract classes, interfaces, arrays, and collections and exceptions. More advanced features such as threading and lambdas are covered as well.
Chapter 4, Java Programming, contains a step-by-step guide to creating a simple web service in the Java language. Tools that are used along the way include the Eclipse IDE, the Gradle build tool, and programming libraries such as SparkJava (a micro web service framework) and the JUnit unit testing framework.
Chapter 5, Scala, talks about the hybrid functional programming and object-oriented programming language Scala. It describes the installation procedure and the usage of the interactive shell bundled with the language. By using the interactive shell, Scala code can be entered and executed dynamically, without explicitly compiling code. Both object-oriented and functional programming in Scala are discussed.
Chapter 6, Scala Programming, contains a step-by-step guide to create a simple console-based application powered by the popular Akka toolkit. Akka is a toolkit specializing in writing scalable applications that take full advantage of modern multicore processors. Many Akka concepts, such as its actor-based system, are discussed thoroughly. To build the project, the Scala Build Tool (SBT) is used, while the ScalaTest library is used for writing unit tests.
Chapter 7, Clojure, explains the fundamentals of Clojure, a dynamic functional programming language inspired by Lisp, which is not object-oriented. Like Scala, Clojure comes with an interactive shell that can be used to enter the various examples that are provided. Agents, a technique to handle state in multithreading applications, are discussed as well.
Chapter 8, Clojure Programming, provides step-by-step guides for two smaller projects. One project is based on monads, a technique that is commonly used in functional programming languages, especially in Lisp. The second project is a web application that is powered by Luminus, a popular micro web framework for Clojure. The Leiningen build tool is used to build both the projects.
Chapter 9, Kotlin, discusses JetBrain's statically typed programming language, Kotlin. Kotlin's type system, which promises null safety, is explained. Other features that are discussed include data classes, lambdas, and inline functions. Procedural programming in Kotlin is covered as well.
Chapter 10, Kotlin Programming, contains a step-by-step guide to create a GUI-based desktop application using the JavaFX toolkit. Apache Maven is used to build the project. The Eclipse IDE's debugger is used to find and fix bugs.
Chapter 11, Groovy, covers the dynamic programming language Groovy, one of the first alternative languages that appeared on the JVM. While Groovy is primarily a dynamic language, it allows compiling statically typed code as well. Both use cases are explained and described in this chapter. Also explored is the Groovy Development Kit, an extensive library of built-in classes, which is distributed as part of the Groovy language distribution.
Chapter 12, Groovy Programming, provides a step-by-step guide to create a web service in Groovy that pulls data from an embedded database management system using the Java Database Connectivity (JDBC) standard and generates XML using classes from the Groovy Development Kit. The Vert.x framework is used to power the web service.
Appendix A, Other JVM Languages, covers five other JVM-based languages, often dialects of mainstream languages: Oracle Nashorn (JavaScript), Jython (Python), JRuby (Ruby), Frege (Haskell), and Ceylon, a statically typed language by Red Hat.
Appendix B, Quiz Answers, gives the solutions to quizes provided at the end of all the chapters.
To get the most out of this book, a modern laptop or desktop computer is required, running an up-to-date version of either Windows, macOS, or Linux (preferably Ubuntu). About 4 GB of RAM memory is recommended at the minimum; more RAM is always welcome. It is assumed that the reader has a reasonable knowledge of the operating system of their choice and is comfortable with installing programs and adding directories to a path.
This book is meant for programmers who are interested in the Java Virtual Machine (JVM) and who want to learn more about the most popular programming languages that can be used for JVM development. A basic practical knowledge of a modern programming language that supports object-oriented programming (JavaScript, Python, C#, VB.NET, and C++) is assumed.
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of.
To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message.
If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Introduction-to-JVM-Languages. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from http://www.packtpub.com/sites/default/files/downloads/IntroductionToJVMLanguages_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.
To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.
Please contact us at [email protected] with a link to the suspected pirated material.
We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
Java Virtual Machine (JVM) is a modern platform on which you can develop and deploy software. As the name implies, it was originally created to power applications written in the Java language. However, it didn't take language designers long to realize that they could not only run their languages on JVM, but also take advantage of its features and extensive class library.
Sun Microsystems released Java and the first JVM implementation in 1995. With its focus on Internet applications, Java quickly became popular. It was also designed from the ground up to run anywhere. Its initial goal was to run on set-top boxes, but when Sun Microsystems found out the market was not ready at that time yet, they decided to bring the platform to desktop computers as well. To make all those use cases possible, Sun invented their own binary executable format and called it Java bytecode. To run programs compiled to Java bytecode, a JVM implementation must be installed on the system.
This book will help you get started with five most popular languages that target JVM. By learning the language fundamentals and writing code yourself, you will be able to find the language that best suits you, your team, and your projects.
Before we dive into the Java Development Kit (JDK) and Java Class Library in the next chapter, we will look at some practical points first. With so many competing programming languages and platforms available today, it makes sense to first take a detailed look at what JVM has to offer to developers. Therefore, we will cover the following topics:
Reasons for developing on JVM
Popular use cases of JVM
I
ntroducing JVM concepts
Java editions
Other languages on JVM
It's important to note that this book focuses on JVM implementations compatible with Oracle's Java SE (Standard Edition) 8 (and higher) platform only. This version can be installed on desktop computers, servers, and many single-board computers (including all the models of the popular credit-card-sized Raspberry Pi). We will use Oracle's implementation in this book, but both the open source OpenJDK and IBM's own J9 Java SE implementations of the same version should work equally well.
The Java platform as published by Google on Android phones and tablets is not covered in this book at all. One of the reasons is that the Java version used on Android is based on an older version of Java. While progress has been made to make Android's version of the platform more up to date, it still doesn't have all the features of Oracle's Java SE 8, and it requires different compilers and tools. Another reason is that Google omitted a lot of the Java SE APIs and replaced them with their own unique, incompatible APIs. Some of the languages covered in this book can be used with Android, however. Kotlin, in particular, is a very popular choice for modern Android development. This use case will not be explored in this book, though.
With so many programming languages and platform options available today, why would you consider developing and deploying your next project on JVM? After all, Java, the language that JVM was originally built for, has been declared obsolete (and, ridiculously, even dead) by fans of different languages more times over the years than anyone cares to remember.
Yet, while many other programming languages have come in and gone out of the spotlight, Java has always managed to return to impressive spots, either near or lately even on top of the list of the most used languages in the world.
Let's look at some of the most important reasons why the JVM platform is so strong:
It keeps up with the modern times by adapting to market changes
The Java Class Library, the built-in library of classes, is very strong
It has an unmatched ecosystem
When Java first appeared in the mid-1990s, computers had CPUs with only a single core and didn't have gigabytes of memory, as memory chips used to be prohibitively expensive. Java is one of those languages that kept up with modern developments: when multicore CPUs appeared, Java was soon able to support those additional cores when running code in multiple threads. But it did not stop there. In each newer version, it added new classes that made working with concurrency easier. This trend still continues.
When the functional programming paradigm became popular, Java received built-in support for lambdas and streams in the core language. While Java was quite late to get this support, compared to other popular languages, Java's implementation was better than many others. This was because it offered built-in support for multithreading almost for free.
Adapting to market changes also means that sometimes things have to go. Back when Java was introduced, running Java code directly in the browser was a big thing. These mini applications were called applets and required a custom browser plugin for each browser and system. Of course, we now know that the market has chosen the JavaScript language as the standard language to create interactive websites, and Oracle recently deprecated the applet standard.
For each edition of Java (more on available editions later in this chapter), it has been decided which classes are guaranteed to be available in a JVM implementation of a specific version. The Java Class Library for Java SE 8 is a very large collection of classes, and every JVM runtime installation that adheres to the Java SE 8 platform standard must implement those classes, regardless of the vendor of the JVM implementation.
Classes in this library provide functionalities such as writing or reading from the console window, performing file I/O, and communicating with TCP servers. Also, there are many classes available to start and manage operating system threads. More fundamentally, it contains classes that define data structures, such as lists and maps (called dictionaries in some other languages), among many others. In the next chapter, we will thoroughly look at the classes in the Java Class Library.
The Java Class Library is an important reason why language designers love targeting JVM. Using the data structures defined in the Java Class Library, they are able to focus more on the language design and less on building a full runtime library from scratch. Building a fully tested, multiplatform runtime system library comparable to the Java Class Library is a huge undertaking.
A built-in class library can obviously not cover all the use cases of a programmer. If something is missing, you can turn to libraries and tools built by other companies, groups, and individuals to save time. Because Java has been so successful for many years, its ecosystem is unmatched. It will be hard to find a platform with proven high-quality tools, libraries, toolkits, and framework choices that are better than the ones available in JVM.
With so many add-on libraries available, Java hardly ever pushes the developer in a certain direction. As an example of how rich the ecosystem is, let's look at the main options JVM developers typically have when creating a web application:
Build a web application that runs inside a JVM application server
To quickly have results, a general high-level web framework can be used
For more control, the application can be built with a microservice framework
Developers could take the enterprise route and install a JVM-based application server, either a free open source one or a paid proprietary one, that will run the application along with web applications simultaneously, if desired. The server will handle configuration issues and manage database connections.
There are simple application servers available that just contain enough built-in APIs to run basic web applications. But there are also full blown Oracle-certified application servers that have a magnitude of built-in and standardized APIs, including APIs to access databases, generate or consume XML or JSON documents, communicate with other web services via the SOAP or REST standards, provide web security, send or receive messages from legacy computer systems, and many others.
The two most important frameworks for enterprise development are the following:
Oracle's Java Enterprise Edition (Java EE) platform, covered later in this book
The Spring Framework ecosystem (including Spring Boot)
Many applications use both these technologies together.
Some of the popular application servers are the following:
Apache Tomcat (for basic web applications)
Apache TomEE
Red Hat WildFly
Oracle GlassFish
Red Hat JBoss Enterprise Application Platform
Oracle WebLogic
The first four are open source and the last two proprietary.
The second possibility would be to use a complete web application framework. These frameworks usually offer higher-level APIs than enterprise frameworks and offer built-in model-view-controller (MVC) solutions that have the capability to enhance a developer's productivity significantly.
Frameworks such as these usually dictate or steer the developer in a certain direction as they have built-in support for only a few hardcoded libraries/toolkits. Often, plugins are supported to add support to other choices, however. By giving up some freedom, quick development cycles can be achieved. Some frameworks require that the application is run inside a JVM application server, while other frameworks provide their own HTTP server.
Apache Struts used to be very popular in this category, but nowadays, the Play framework is probably the most popular choice.
A different choice could be to create the application using the modern microservice framework. Frameworks such as these have a built-in HTTP server to run your application, but they do not provide any other tools or libraries out of the box. In this scenario, it's easier to mix and match other libraries and toolkits that you want to use yourself.
Commonly, the application will be separated into multiple standalone web services to follow the modern microservice architecture, but this is not a strict requirement of these frameworks.
Vert.x and Spark Java (not to be used with the Apache Spark big data platform) are the most commonly used microservice frameworks.
Now that we've seen some valid points that confirm why JVM is a viable platform for modern software development, let's look at some places where JVM usage is particularly popular:
Web applications
Big data analysis
Internet of Things (IoT)
With its focus on performance, JVM is a very popular choice for web applications. When built correctly, applications can scale really well, if needed across many different servers.
JVM is a well-understood platform, meaning that it is predictable. Plus, it provides many tools to debug and profile problematic applications. Because of its open nature, monitoring of JVM internals is also possible. For web applications that have to serve thousands of users concurrently, this is an important advantage.
JVM already plays a huge role in the cloud. Popular examples of companies that use JVM for core parts of their cloud-based services include Twitter (famously using Scala), Amazon, Spotify, and Netflix. The actual list is much larger.
Big data is a hot topic. When data is regarded too big for traditional databases to be analyzed, one can set up multiple clusters of servers for processing such data. Analyzing data in this context can, for example, refer to searching for something specific, looking for patterns, and calculating statistics.
This data could be obtained from the data collected from web servers (for example, logged visitors' clicks), the output obtained from external sensors at a manufacturer's plant, legacy servers that have been producing log files for many years, and so forth. Data sizes can vary wildly as well, but often, they take up multiple terabytes in total.
Two popular technologies in the big data arena are the following:
Apache Hadoop (provides storage of data and takes care of data distribution to other servers)
Apache Spark (uses Hadoop to stream data and makes it possible to analyze incoming data)
Both Hadoop and Spark are for the most part written in Java. While both offer interfaces to a lot of programming languages and platforms, it will not be a surprise that JVM is one among them.
The functional programming paradigm focuses on creating code that would run safely on multiple CPU cores, so languages that are fully specialized in this style, such as Scala or Clojure, are appropriate candidates to be used with either Spark or Hadoop.
Portable devices that feature Internet connectivity are very common these days. Since Java was created with the idea of running on embedded devices from the beginning, JVM is, yet again, at an advantage here.
For memory-constrained systems, Oracle offers the Java ME Embedded platform. It is meant for commercial IoT devices that do not require a standard graphical or console-based user interface.
For devices that can spare more memory, the Java SE Embedded edition is available. The Java SE Embedded version is very close to the Java SE discussed in this book. When running a full Linux environment, it can be used to provide desktop GUIs for full user interaction.
Both Java ME Embedded and Java SE Embedded platforms can access the general-purpose input/output (GPIO) pins on the Raspberry Pi, which means that sensors and other peripherals connected to these ports can be accessed by Java code.
Every aspiring JVM developer should be familiar with its most important concepts:
JVM is a virtual machine
Most implementations feature a just-in-time (
JIT
) compiler
It offers a few built-in primitive datatypes
Everything else is an object
Objects are accessed via reference types
The
garbage collector
(
GC
) process removes obsolete objects from memory
Build tools are used a lot in the JVM world
That the Java Virtual Machine is a virtual machine is a rather obvious observation, but it should be kept in mind. One of the consequences is that you are, in theory, writing applications for a type of machine that differs from the machine you are developing or running your applications on.
It generally does not matter whether the code runs on a 32-bit or 64-bit version of the Java Runtime Environment (JRE). The latter will probably make more memory available to the application than the 32-bit version, but the running program will not care about this difference as long as it doesn't make native operating system calls or require gigabytes of memory.
Finally, it should be noted that each application that runs on JVM loads its own instance of JVM on system memory. This means when you run multiple Java applications at the same time, they will all have their own copy of JVM at their disposal; this also means different applications can use different versions of JVM if required for whatever reason. For security reasons, it is not suggested that you have different versions of the JDK or JRE on one system; it's usually better to have only the latest supported versions installed.
Although not dictated anywhere, all popular JVM implementations are not just simple interpreters; they feature complex JIT compilers along with their interpreters.
When you launch a Java application, JVM is launched and initialized first. Once this is done, it immediately starts interpreting and running the Java bytecode. If the interpreter believes it makes sense, it will compile sections of the programs and load libraries to native executable code in memory and start executing that version of the code instead of the interpreted Java bytecode version. This often results in code that could be executed much faster.
Whether the code is compiled or interpreted depends on many things. If a routine is called often, it becomes a probable candidate for the JIT compiler to compile it to the native code.
JVM has a few so-called built-in primitive datatypes. This is the main reason why Java is not considered a pure OOP language. Variables of these types are not objects and always have a value:
Java name
Description and size
Values (inclusive)
byte
Signed byte (8 bits)
-128 to 127
short
Signed short integer (16 bits)
-32768 to 32767
int
Signed integer (32 bits)
-2
31
to 2
31
-1
long
Signed long integer (64 bits)
-2
63
to 2
63
-1
float
Single-precision floating point (32-bit)
Non-precise floating point values
double
Double-precision floating point (64-bit)
Non-precise floating point values
char
A single Unicode UTF-16 character (16-bit)
Unicode character 0 to 655535
boolean
Boolean
True/False
Note that not all JVM languages support the creation of variables of primitive types and follow this modern assumption: everything takes the object approach. We will see that this is usually not a problem as the Java Class Library has wrapper objects that wrap primitive types, and most languages, including Java, automatically use these wrappers when required. This process is called auto-boxing.
Functions and variables are always declared inside a class. Even the application entry function that is called upon a program launch, called the main() function, is a function that is located inside a class.
JVM only supports the single-inheritance model. Classes always inherit from one class at the maximum. This is not a big loss. As we will see in the next chapter, a structure called an interface comes to the rescue. An interface is basically a list of function prototypes (only the definition of functions, without code) and constants. Classes that implement an interface are required by the compiler to have implementations for those functions. Classes can implement as many interfaces as they want, but they must provide implementations for each method of all the implemented interfaces.
JVM classes are usually grouped in packages. In the next chapter, we will see how classes are organized.
Like most modern programming languages, JVM does not work with direct memory pointers to objects; it uses reference types. A reference type variable either points to a specific instance of a class or it points to nothing.
If a reference type points to an object, it can be used to call the object's methods or access public attributes.
If a reference type points to nothing, it is called a null reference. When calling methods or reading attributes using a null reference, an error will be generated at runtime. We will see that some languages covered in this book came up with solutions to this common problem.
JVM does not require the programmer to manually allocate and release blocks of memory when creating or disposing of objects. The programmer can generally concentrate on just creating objects when he or she needs them.
A process known as the GC halts the application at certain intervals and scans the memory for objects that are no longer in scope (not reachable by any other object loaded at that point). It will remove those objects that can safely be deleted from the memory and reclaim the freed space.
This process used to cause very serious performance issues in the past, but the algorithm has improved much over the years. Also, if an application needs it, system administrators can configure many parameters of the GC to better control it.
The developer should always keep the high-level concept of the GC algorithm in mind. If you keep creating tons of objects and always keep them in the scope (meaning making it in such a way that all those objects can be reached, for example, by storing them in a list that the application can access), then out of the memory, errors are very likely to occur sooner or later.
Let's assume you have developed an e-commerce application for an online store. Also, let's assume that each logged-in user has their own ShoppingBasket instance that holds the products that they add to their basket.
Say, a user has logged in today and is planning to buy a soap bar and a delicious pack of cookies. For this user, the application will create two Product instances, one for each chosen product, and add them to the products list of ShoppingBasket:
Just before visiting the checkout page, the user sees that Amazon offers the same cookies at a much better price and decides to remove the cookies from the basket. Technically, the application would remove the Product instance from the list of products. But from there on, the product instance representing Chocolate cookies is an orphan object. As there is no reference to it, it cannot be reached by the application:
After a while, JVM's GC kicks in and sees the Chocolate cookies object instance. It determines that the object cannot be reached in any way by the application anymore and therefore decides to remove it. The memory the object was using up will now be released:
There are several tricks to tame GC. One well-known trick when an application needs to work with lots of similar objects is to put these objects in a pool (list of objects). When an application needs an object, it simply gets one from the pool and modifies the object according to its needs. When it has finished and doesn't need the object anymore, it will put it back in the pool. Since these objects are always in the scope (when not used, in the pool, which the application can access), GC will not try to dispose of these objects.
The maintainers of JVM and Java Class Library understand the needs of business developers. The code that is written today should ideally run tomorrow. JVM offers reasonable backward compatibility. Developers familiar with Python 2 and 3 will know that this is not a given in the industry.
Newer JVM versions can run applications that were compiled for older JVM versions, as long as the application's code does not use APIs or technologies that were removed from the JVM version that is running the application. Here's an example: libraries compiled for Java 6 can still be loaded and used in projects that run on a Java 8 JVM instance. But this is not the case the other way around; applications running on a Java 6 JVM instance cannot load classes compiled for later versions.
Of course, like every other platform or language, the JDK and Java Class Library maintainers have to deprecate classes and whole technologies from time to time. While there are issues, backward compatibility on JVM is generally better than many other platforms and languages. Also, APIs are generally only removed if proper and well-documented alternatives exist.
Back when projects were simpler, simple batch or operating system shell script files used to automate the compiling and packaging process. As projects became more complex, it became harder to define these scripts. For different operating systems, completely different scripts had to be written.
Soon, the first set of dedicated Java build tools appeared. These worked with XML build files. More or less, cross-platform compatible scripts could be written this way. At first, long and cumbersome scripts had to be written; later, tools worked with the convention over configuration paradigm. When using the conventions suggested by the tool, much less code has to be written; however, if your situation is different from the default behavior, it can take a lot of effort to let the tools do what you want or need. Newer tools ditch XML files and provide script languages to automate the building.
Some of the features that many of those tools offer are as follows:
Built-in dependency managers that can download add-on libraries from well-known repositories from the Internet
Automatically run unit tests and conditionally stop packaging if a test fails
The JDK does not offer a build tool itself, but it will be hard to find projects that do not at least use one of the following open source build automation tools:
Apache Ant (has no built-in dependency manager and works with XML-based build scripts)
Apache Maven (introduced convention over configuration with XML files and works with plugins)
Gradle (build scripts written in Groovy or Kotlin)
JVM programmers that use a popular IDE do not have to worry too much about build automation tools. This is because all IDEs can generate build scripts themselves. If you want more control, you can start writing your own scripts manually and let the IDE use that script to compile, test, and run your project.
Several editions of Java are available. Each one aims at different use cases. Some of the editions have had numerous name changes over the years; the current names of the editions are as follows:
Java Standard Edition
(
Java SE
)
Java Enterprise Edition
(
Java EE
)
Java Micro Edition
(
Java ME
)
This is the most important edition. When people mention the term "Java," they usually refer to this edition. This book concentrates solely on the Java SE platform.
This edition is meant to run on desktop machines and servers, and as we will see later, an embedded version is also available and bundled with Raspberry Pi's Linux distribution. Java SE comes with the complete Java Class Library. It includes the classic Swing GUI Toolkit; most versions also contain the modern JavaFX GUI toolkit.
Java SE is mostly meant to create standalone consoles, desktop GUIs, or headless applications; alternatively, it is used to create external libraries.
Java EE builds upon Java SE; therefore, it requires that Java SE is installed. It adds lots of APIs in a lot of categories. Java EE applications usually run inside JVM application servers. This book does not cover Java EE in depth but will mention it from time to time. This is because it is a very important addition to the Java platform, especially for business developers.
It is not possible to download a Java EE standalone edition from the Oracle website; instead, you will have to download a full application server that is compatible with the Java EE platform version you want to use. Some IDEs bundle the Java EE application server as well; we will cover this in the next chapter.
The Java EE standard only describes the APIs that must be available, but it does not dictate the implementation. It's up to the Java EE-compatible application servers to come up with actual implementations that adhere to these standards.
Java EE describes the Java Persistence API (JPA). It is an object relation mapper (ORM) API, a layer between Java objects and relational databases (often SQL databases, such as Oracle database, Oracle MySQL, PostgreSQL, and so on). With a few lines of code, the content of JVM objects can be written to the database or vice versa: read from the database and put in the object.
Oracle's own reference implementation of Java EE is an open source application server called GlassFish. GlassFish bundles the existing EclipseLink open source project as the implementer of the JPA standard. Meanwhile, Red Hat's WildFly, a different open source Java EE application server, bundles Red Hat's own, more popular, Hibernate ORM open source project, which also implements the JPA standard.
If developers only use the features documented in the JPA standard, then it should not matter to them which implementation is used, but problems arise once features are used that are unique to a specific implementation.
Before the days of iOS and Android, Java ME happened to be an important platform for feature phones and early smartphones for games and some basic applications. iOS and Android both never supported Java ME applications, so nowadays it does not play a major role anymore.
It featured a subset of the Java Class Library and offered some additional APIs to work with mobile devices. Java ME got a second life as Java ME Embedded, which can be used for commercial IoT devices.
