How to Choose Your JVM-Based Language

February 10, 2022

When looking for modern languages for software development, you might have noticed that Java isn’t exactly the freshest solution out there. But it’s used in virtually all of IT, from client to server, web to mobile, and even machine learning and analytics. Plus, it comes with a good amount of experience spread throughout its communities.

For over a decade now, the ecosystem around a JVM has no longer been just about the Java programming language. Authors have implemented languages on top of Java’s engine that solve Java’s problems, as well as other well-known languages from other ecosystems. Their JVM implementations allow developers to use their existing skills within the Java ecosystem.

Choosing the best language for a project can be a daunting task, and most companies simply stick with Java. But if you can leverage the advantages that these alternative JVM languages bring and the downsides don’t affect you, it could be worth a shot to stray from Java and try something new.

So, if you want to benefit from the fantastic new language design features that computer scientists have come up with in the last decade and enjoy the full power of the JVM, read on! This article covers today’s most popular JVM languages and helps you choose the best one for your next project.

Java

Let’s start with the classic. While Java is obviously not an alternative to itself, the Java you met 5 to 10 years ago has gotten a facelift. 

Java was created in 1995 by James Gosling for Sun Microsystems. It’s an object-oriented programming language that’s easier to use than C++ and more versatile than Smalltalk. It’s statically typed but doesn’t require manual memory management. Currently, Oracle is the owner of Java and takes care of all updates and support.

Java has had several upgrades in the past few years. Below, we’ll be taking a look at some of the changes Oracle has released since version 8, which came out in 2014. Java received many functional programming features in v8, and the subsequent versions expanded on these.

Java Hello World

Let’s look at a Hello World program in Java:



class Main {

 public static void main(String[] args) {

    System.out.println("Hello, World!");

  }

}

Java has very strict rules about program structure. You have to type everything, and everything must be encapsulated by a class. In this brief example, we can already see that even a small task like printing a string takes quite a bit of boilerplate code to get it done.

Updates to the Java Language

While object-oriented programming was all the rage when C++ and Java came out, functional programming became popular after 2000. Java already received anonymous functions that cut down on the boilerplate consisting of anonymous classes, and the latest changes to Java doubled down on this.

Pattern matching, switch expressions, and record classes are a few of the additions that were a boon for functional programming in Java. Reactive programming, a sub-paradigm of functional programming that focuses on data streams, became a core part of the language as well with the addition of the Flow API.

Java also received a bunch of general usability improvements. The cumbersome collection classes got some factory methods, text blocks now ease the pain of including domain-specific languages like SQL or HTML, and new string methods are now available, to name just three quality-of-life upgrades.

Is Mature Tooling Available?

Java is the best-supported language in the whole ecosystem. If you make your choice based solely on the availability of tools, Java is the clear winner.

It doesn’t just offer you tools for every problem in the development lifecycle, like IDEs, debuggers, or CI/CD servers; it also provides you with multiple alternatives for each tool.

Don’t like NetBeans? Use Eclipse!

TeamCity isn’t your thing? Try Jenkins!

If you want to cover all the steps from building to deploying software, the Java ecosystem has got you covered.

Online Communities

Popular Java Projects

  • Elasticsearch – An online search engine for self-hosting
  • Minecraft – One of the most popular multiplayer 3D games in the world
  • Spring Boot – A backend framework for web development
  • Lottie – A 2D animation framework for mobile platforms
  • Jenkins – A CI/CD pipeline tool for self-hosting

IDE Support

Debugger 

Minimal Supported JVM Version

All versions of the JVM are supported.

Cloud Support

All big cloud providers offer Java SDKs.

Kotlin

Kotlin is probably THE alternative to Java. While it takes functional programming seriously, it offers more practical approaches to everyday development problems. JetBrains, a significant player in the development tooling space, built Kotlin and released it in 2011. Since then, it has grown its user base tremendously. Kotlin owes part of this success to Google, making it an officially supported programming language for Android app development.

Kotlin uses a more advanced type system that includes non-nullable types, saving you from those dreaded NullPointerExceptions. Compared to Scala, which was released earlier, it takes a less functional approach.

Kotlin Hello World

Now, the Kotlin Hello World example:

fun main() {                        

    println("Hello, World!")        

}

Kotlin is more flexible than Java; functions don’t need a class and more of the commonly used functions, like println, are globally available without any namespace clutter.

Kotlin’s Strengths

Google officially supports Kotlin as a first-class language to develop apps for Android. This way, you get modern programming language ergonomics and commercial support from a big player in the mobile game.

Kotlin is higher-level than Java and more practical than Scala. Since it came after Scala and Groovy, it could learn from many of their mistakes. Kotlin’s modern type system can infer many type annotations automatically, which eliminates much boilerplate code without sacrificing safety as dynamic typing does.

It also has coroutines, a programming construct that abstracts threads. These make concurrent programming easier for the masses, which is vital when multi-core CPUs are the standard. In addition, Kotlin makes it easy to integrate with Objective-C and Swift code, a superpower when you’re doing mobile development on multiple platforms!

Overall, Kotlin is a very high-level and pragmatic language that comes with a bunch of quality-of-life improvements that were missing from Java or only suboptimally implemented in alternatives.

Kotlin’s Weaknesses

Kotlin doesn’t have primitive types. Everything in Kotlin is an object, which makes low-level memory layout harder. But since it transparently integrates with Java, you can always write low-level code in a Java file and include it when needed.

Kotlin also has less recruiting potential than Java, but with the official support of Google on Android, this shouldn’t be an issue for long.

Mature Kotlin Tools Available

Kotlin was created by JetBrains, an influential player in the Java development tool ecosystem. Since tooling was their main business before Kotlin, this reflects significantly in the availability and maturity of the developer tools.

Kotlin has official support from Google for Android application development, one of the JVM’s biggest platforms. Android Studio, the IDE recommended by Google, comes with out-of-the-box support for Kotlin.

Communities

Popular Projects

  • Ktor – An asynchronous web framework
  • KotlinDL – A deep learning framework
  • Exposed – An SQL framework

IDE Support

Debugger 

Minimal JVM Version

The current version of Kotlin requires Java version 8.

Cloud Support

Kotlin can use the Java SDKs of all major cloud providers transparently.

Scala

Scala is another attempt at bringing a more sophisticated programming approach to the JVM. This time, the primary idea is to merge functional and object-oriented programming. The language is statically typed, but as with Kotlin, the type system requires fewer annotations than Java. So again, if you’re into the whole functional programming thing, Scala might be worth a look. Immutable data, pattern matching, and, with the newest compiler, even a sound type system? What’s not to like!

Martin Odersky, a computer science professor from Switzerland, created Scala in 2004. He previously had added parametric polymorphism to Java with Generics, so he had some serious programming language design cred even before he invented Scala. 

Scala Hello World

Let’s check the Hello World of Scala:

object Hello {

    def main(args: Array[String]) = {

        println("Hello, world")

    }

}

This falls somewhat between the Hello Worlds of Java and Kotlin. On the one hand, it requires us to wrap at least the main function of the program in a class, here a singleton object that gets instantiated automatically. On the other hand, it comes with easier accessible globals than Kotlin does.

Scala’s Strengths

Scala uses a more expressive type system than Java, allowing for fewer type annotations and implicit conversions between types.

A big issue with static type systems is converting types when integrating with multiple libraries and frameworks; implicit conversions let you write conversion code in a separate file so they don’t clutter your business logic.

Integrating functional programming more tightly into an object-oriented language was one of the primary goals of Scala. Higher-kinded types, pattern matching, and operator overloading are vital features. So if you’re into functional programming and prefer a more strict approach, Scala is your go-to language!

Scala also improved on common object-oriented problems. While Java solved multiple inheritances by simply denying them entirely and opting for interfaces, Scala took a different route and added traits, which are more restricted than classes and more flexible than interfaces.

Scala’s Weaknesses

Prolonged compile times plagued Scala for years; this led to significant disputes in the Scala community and to the creation of a new compiler that solved this issue in version 3.0.

The mix of programming paradigms isn’t for everyone and comes with a steep learning curve; the talent pool for hiring is thus much smaller than with Java.

Features like implicit conversions and operator overloading lead to more concise code but can often hide important aspects in other files, leading to errors.

Are Mature Scala Tools Available?

In 2018 a team of developers sat together and founded a tooling working group, which focused on improving the sad state of Scala tooling. Overall, Java and Kotlin have a much better posture here, including software powerhouses like Oracle and Google behind them, and Scala has tried to catch up.

Scala Communities

Popular Projects

  • Akka – A framework that implements the actor model in Scala
  • Play Framework – A backend web framework
  • Quill – A framework for domain-specific query languages

IDE Support for Scala

Scala Debugger 

  • JDB – The Java Debugger 
  • Rookout – A Live Debugger 

Minimal JVM Version

The current version of Scala requires at least version 8.

Cloud Support

Scala has explicit support in Spark but can transparently use the Java SDKs of big cloud providers.

Clojure

Clojure is also on the list of JVM-based languages. If you know Lisp, you understand why the JVM needed one. If not, well, then your programming language interests probably aren’t niched enough. Jokes aside, if you buy into the whole simplicity approach of functional programming that Lisp delivers, Clojure might just be the thing for you.

Rich Hickey, an independent software developer, created Clojure in 2007. Before that, he also built Lisp-like programming languages for other runtimes, like the .Net common language runtime.

The goal of Clojure is to enable Lisp developers to harness the power of the Java ecosystem. It’s a dynamically typed Lisp dialect with a heavy focus on functional programming and immutable data structures to help with concurrent programming.

Clojure Hello World

The Clojure Hello World program:

(ns helloworld.core)

(defn -main

  "Program description"

  []

  (println "Hello, World!"))

Clojure has a very peculiar syntax, called S-expressions. There are only lists of words, grouped together inside parentheses. The first word is the function or operator, while any following words are the arguments. That’s all there is; no infix or postfix notation. Everything is a function, and everything is written in that style.

Clojure’s Strengths

Clojure is the only popular functional programming language on the JVM that uses Lisp syntax. So if Lisp is your thing, you should go with Clojure.

The immutable data structures make concurrent programming much more straightforward. If your problem space is heavy in concurrent computing, Clojure could be easier to maintain. 

Clojure’s Weaknesses

The language is a dynamically typed language, which can be problematic for maintenance in the long run. 

The fact that Clojure has Lisp syntax can throw off new programmers. Functional programming alone is a peculiar type of programming, but Lisp syntax takes this to the extreme. Because of this, you should decide to use Clojure only after serious consideration due to the much smaller talent pool.

While the language’s data structures help write concurrent code, low-level code is more challenging. 

Startup times are slower than other JVM languages as well, and debugging was a pain before version 1.10 because of lousy error messages.

Are Mature Clojure Tools Available?

Yes. While the community is smaller than other languages mentioned here, Clojure has a solid tooling foundation. It probably owes this to the fact that Clojure is a Lisp, which has a superpower called homoiconicity. This means its code is written in the data structures of that language. While this feature is often seen as a gimmick by creators of non-homoiconic languages, it has always helped Lisps create reliable tools without much effort.

Clojure Communities

Popular Clojure Projects

Clojure IDE Support

Clojure Debugger 

  • JDB – The Java Debugger
  • Debux 
  • Rookout – A Live Debugger 

Minimal JVM Version

The latest version of Clojure requires at least version 8.

Cloud Support

Like all other JVM languages, Clojure can transparently use the Java SDKs of the big cloud providers.

Groovy

Many developers see Groovy as the small sibling of Java. It was conceived in 2003 as a scripting language that helps to iterate faster and rid the JVM of most of the cumbersome boilerplate code that Java requires you to write.

Two of its main features are dynamic typing and that it doesn’t need to be compiled. Groovy owes its big community to the fact that it is the oldest alternative JVM language and has a flatter learning curve than Java.

If you’re a fan of dynamic typing or just need a well-integrated way of scripting your Java software, Groovy is the way.

Groovy Hello World

Groovy’s Hello World example is the shortest:

println "Hello World!"

Here we can already see Groovy’s heavy emphasis on scripting. Every clutter has been removed, there are no semicolons, and even parentheses around function arguments are optional.

Groovy’s Strengths

Groovy is more lightweight than Java since you do not have to type any annotations. It also includes literals for the collection classes, making them very simple.

You can also interpret Groovy and, in turn, use it as a scripting language. This allows for more use cases than Java, like writing and running code without a Java compiler.

Groovy’s Weakness

Dynamic typing is suitable for fast prototyping and small scripts but is hard to maintain if a project gets too big. Groovy offers static typing now, but it’s an opt-in, which requires more discipline from the programmer’s side.

Groovy was one of the first alternative JVM languages and came into being when the JVM didn’t offer any APIs for dynamic programming. This made the execution of Groovy relatively slow. In recent years and with the addition of more and more alternative languages to the JVM, this has changed, and Groovy’s performance is now comparable to Java. But you should keep this in mind when working with older JVM versions.

Before Groovy version 4, one line of code would compile to a different bytecode depending on its context to optimize performance; this could lead to performance regressions in code lines that didn’t change in a new release.

Groovy also didn’t get enough promotion for app development on Android, so the tooling isn’t as fully-fledged as with Kotlin or Java.

Mature Groovy Tooling Available

Groovy is an exciting language when looking at tooling because Gradle, one of the primary build tools for JVM applications, is written and extended with Groovy. Android, for example, uses Gradle as its build environment.

Gradle helped Groovy tremendously to mature. And being able to have complete control over one of the main tools in the Java ecosystem can give your project an edge in terms of build optimizations. The popularity of Gradle also led to all big IDE projects shipping with a Groovy integration out of the box.

Groovy Communities

Popular Projects

  • Gradle – A build tool
  • Grails – A Rails-like web framework

IDE Support

Debugger 

  • JDB – The Java Debugger 
  • Rookout – A Live Debugger

Minimal Supported JVM Version

The first version of Groovy ran on 1.4, which Oracle hasn’t supported since 2013. So, the current recommended version is 8.

Cloud Support

Groovy can use Java libraries transparently and, in turn, all Java SDKs from major cloud providers.

Other Interesting Languages

With the creation of GraalVM and the Truffle Language Implementation Framework, Oracle made the JVM more open to other programming languages, resulting in a compiler or runtime for every popular programming language that targets the JVM. This allows you to use the Java ecosystem with a programming language you and your team might be more familiar with.

If you need to integrate with the Java ecosystem while having no Java know-how in your company, these compilers and runtimes might be a viable alternative:

  • JavaScript
  • Python
  • Ruby
  • Go
  • R

Conclusion

The Java ecosystem is extensive and offers many libraries and frameworks, but the Java language might not be to everyone’s liking. While it has gotten many updates in recent years, especially for functional programming, writing Java code can still be daunting. 

Luckily, there are many alternative JVM languages to make developers’ lives easier. Kotlin, Scala, and Groovy explicitly try to make Java better, with different approaches—some more imperative, some more functional. And with Clojure, there is even a modern Lisp on the JVM!

If these JVM-specific languages aren’t your thing, or if you simply don’t have enough know-how in-house, compilers are also available for every popular programming language; these are great if you merely want to use your favorite language or don’t know enough about Java.