1. Introduction
Besides Java, other languages can run on the Java Virtual Machine like Scala, Kotlin, Groovy, Clojure.
In the following sections, we’ll take a high-level look at the most popular JVM languages.
Of course, we’ll start with the forerunner of JVM languages – Java.
2. Java
2.1. Overview
Java is a general-purpose programming language embracing the Object-Oriented Paradigm.
A core feature of the language is the cross-platform portability, which means that programs written on one platform are executable on any combination of software and hardware with adequate runtime support. This is achieved by compiling code into bytecode first, instead of directly to platform-specific machine code.
Java bytecode instructions are analogous to the machine code, but they’re interpreted by a Java Virtual Machine (JVM) specific to the host operating system and hardware combination.
Although originally an object-oriented language, Java has started adopting concepts from other programming paradigms like functional programming.
Let’s have a quick look at some of Java’s main features:
- Object-oriented
- Strongly statically typed
- Platform-independent
- Garbage-collected
- Multithreaded
2.2. Examples
Let’s see how a simple “Hello, World!” example looks like:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
In this example, we’ve created a class named HelloWorld and defined the main method which prints a message on the console.
Next, we’ll use the javac command to generate the bytecode which can be executed on a JVM:
javac HelloWorld.java
Finally, the java command executes the generated bytecode on JVM:
java HelloWorld
For more Java examples, check out our list of tutorials.
3. Scala
3.1. Overview
Scala stands for “scalable language”. Scala’s a statically typed language which combines two important programming paradigms, namely object-oriented and functional programming.
The language originated in 2004 but became more popular in recent years.
Scala is a pure Object-Oriented language as it doesn’t support primitives. Scala provides the ability to define classes, objects, methods along with functional programming features like traits, algebraic data types, or type classes.
A few important features of Scala are:
- Functional, Object-oriented
- Strongly statically typed
- Algebraic Data Types
- Pattern Matching
- Enhanced Immutability Support
- Lazy Computation
- Multithreaded
3.2. Examples
First, let’s take a look at the same “Hello, World!” example as before, this time in Scala:
object HelloWorld {
def main(args: Array[String]): Unit = println("Hello, world!")
}
In this example, we’ve created a singleton object named HelloWorld and the main method.
Next, to compile this, we can use scalac:
scalac HelloWorld.scala
The scala command executes the generated bytecode on JVM:
scala HelloWorld
4. Kotlin
4.1. Overview
Kotlin is a statically typed, general-purpose, open-source language developed by JetBrains team, which brings together the Object-oriented and functional paradigms.
The main focus while developing Kotlin was Java interoperability, safety (exception handling), conciseness and better tooling support.
Since the release of Android Studio 3.0, Kotlin is a fully supported programming language by Google on the Android Platform. It’s also included in the Android Studio IDE package as an alternative to the standard Java compiler.
Some important Kotlin features:
- Object-oriented + Functional
- Strongly statically typed
- Concise
- Interoperable with Java
Our introduction to Kotlin also contains more specifics on the features.
4.2. Examples
Let’s see the “Hello, World!” example in Kotlin:
fun main(args: Array<String>) { println("Hello, World!") }
We can write the code above in a new file called helloWorld.kt.
Then, we’ll use the kotlinc command to compile this and generates bytecode which can be executed on a JVM:
kotlinc helloWorld.kt -include-runtime -d helloWorld.jar
The -d option is used to indicate the output file for class files or a .jar file name. The -include-runtime option makes the resulting .jar file self-contained and runnable by including the Kotlin runtime library in it.
Then, the java command executes the generated bytecode on JVM:
java -jar helloWorld.jar
Let’s also see another example of printing a list of items using a for loop:
fun main(args: Array<String>) {
val items = listOf(1, 2, 3, 4)
for (i in items) println(i)
}
5. Groovy
5.1. Overview
Groovy is an object-oriented, optionally typed, dynamic domain specific language (DSL), with support for static-typing and static compilation capabilities. It’s aimed at improving developer productivity, with easy to learn syntax.
Groovy integrates easily with any Java program and immediately adds powerful features, like scripting capabilities, runtime and compile-time meta-programming and functional programming features.
Let’s highlight a few important features:
- Object-oriented with functional features like Higher-order functions, currying, closures
- Typing – Dynamic, Static, Strong, Duck
- Domain Specific Language
- Interoperability with Java
- Productivity by conciseness
- Operator overloading
5.2. Examples
First, let’s see our “Hello, World!” example in Groovy:
println("Hello world")
We wrote the above code in a new file called HelloWorld.groovy. Now we can run this code in two ways: by compiling then executing or by just running uncompiled code.
We can compile a .groovy file using the groovyc command as follows:
groovyc HelloWorld.groovy
Then, we’ll use the java command for executing the groovy code:
java -cp <GROOVY_HOME>\embeddable\groovy-all-<VERSION>.jar;. HelloWorld
For example, the command above could look like:
java -cp C:\utils\groovy-1.8.1\embeddable\groovy-all-1.8.1.jar;. HelloWorld
Let’s also see how we can use the groovy command to execute the .groovy file without compiling:
groovy HelloWorld.groovy
Finally, here’s another example of printing a list of items with the index:
list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list.eachWithIndex { it, i -> println "$i: $it"}
Have a look at more Groovy examples in our introduction article.
6. Clojure
6.1. Overview
Clojure is a general-purpose functional programming language. The language runs on JVM as well as Microsoft’s Common Language Runtime. Clojure is a compiled language still, it remains dynamic, as its features are supported at runtime.
The Clojure designers wanted to design modern Lisp which can run on JVM. That’s why it’s also known as a dialect of the Lisp programming language. Similar to Lisps, Clojure treats code as data and has a macro system as well.
Some important Clojure features:
- Functional
- Typing – Dynamic, Strong, recently started supporting gradual typing
- Designed for concurrency
- Runtime polymorphism
6.2. Examples
Unlike other JVM languages, it’s not that straightforward to create simple “Hello, World!” program in Clojure.
We’ll use the Leiningen tool for running our example.
First, we’ll create a simple project with default template using the following command:
lein new hello-world
The project will be created with following file structure:
./project.clj
./src
./src/hello-world
./src/hello-world/core.clj
Now we need to update the ./project.ctj file with the following content to set the main source file:
(defproject hello-world "0.1.0-SNAPSHOT"
:main hello-world.core
:dependencies [[org.clojure/clojure "1.5.1"]])
Now we’re set to update our code to print “Hello, World!” in the *./src/hello-world/core.*clj file:
(ns hello-world.core)
(defn -main [& args]
(println "Hello, World!"))
Finally, we’ll use the lein command to execute the code above, after moving to the project’s root directory:
cd hello-world
lein run
7. Other JVM Languages
7.1. Jython
Jython is the Java platform implementation of Python which runs on the JVM.
This language was initially designed to enabled writing high-performance application without sacrificing interactivity. Jython is object-oriented, multi-threaded and uses Java’s garbage collector for efficiently cleaning up the memory.
Jython includes most of the modules which are part of the Python language. It can also import and use any classes from the Java libraries.
Let’s see a quick “Hello, World!” example:
print "Hello, world!"
7.2. JRuby
JRuby is an implementation of the Ruby programming language to run on the Java Virtual Machine.
The JRuby language is high performance and multi-threaded, with a vast variety of available libraries from Java and Ruby. Also, it combines features from both languages like object-oriented programming and duck-typing.
Let’s print “Hello, World!” in JRuby:
require "java"
stringHello= "Hello World"
puts "#{stringHello.to_s}"
8. Conclusion
In this article, we’ve studied many popular JVM languages along with basic code examples. These languages implement various programming paradigms like object-oriented, functional, static typing, dynamic typing.
So far it shows that even with the JVM dating back to 1995, it still stands as a highly relevant and compelling platform for modern-day programming languages.