JavaData & JavaAn Introduction to Dynamic Language Support in JVM

An Introduction to Dynamic Language Support in JVM

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

JVM has been extended to support modern dynamic languages, also called scripting languages, since version 6. The release of Java 8 gave more impetus on this frontier. The necessity of this support is felt because Java as a language is inherently statically typed. Everything is decided at the compile time. The behavior of the dynamic language, on the other hand, is defined at runtime. As a result, its support by the JVM opened new horizons for Java programmers, where we can combine both the static and dynamic aspects of the platform and use it effectively in a Java application. This article skims over the list of dynamic language support in JVM.

Dynamic Language Support

A statically typed language means that all the typed information—such as the class, its members, function parameters, return type values, and so forth—are all decided at compile time. The Java compiler uses this information to generate the bytecode. The JVM simply interprets them during execution.

A dynamic language (scripting language), on the other hand, does all the type checking at runtime by the script engine. There is no separate compilation step. A sequence of instructions is executed by the interpreter, and then parses it to generate the intermediate code. The variables are stored in the symbol table while they are compiled into Java bytecode used by the JVM. The character of the dynamic languages is that, once the code is written, it can be deployed immediately. Because it is interpreted, it is easy to debug with almost no waiting time. In Java, the package javax.script provides all the classes and interfaces, called the Java Scripting API, in support of dynamic languages.

There are arguably many advantages and disadvantages to both types of language, static or dynamic. But, the point is that Java until now could not reap the benefits due to its static nature. It was not an easy job to rebuild JVM with the special support. Perhaps, the real challenge is in implementing a runtime system that can choose the appropriate implementation of a method call after the compilation process has ended. Here, we introduce some of the popular dynamic language support by the JVM.

JavaScript in JVM

JavaScript is the most popular scripting language supported by the Java Scripting API. All of today’s Web browsers understand this language. The eval method from the ScriptEngine interface can be used to execute a script written in plain Java String.

package com.mano.example;
import javax.script.*;
public class ScriptingDemo {
   public static void main(String[] args) {
      final ScriptEngineManager manager = new
         ScriptEngineManager();
      final ScriptEngine engine =
         manager.getEngineByName("js");
      try {
         System.out.println(engine.eval("engine.getClass()
            .getSimpleName()"));
         System.out.println(engine.eval("5+5"));
         engine.put("x", 123423558);
         engine.put("y", 4);
         engine.eval("var result = x.toExponential(y);");
         System.out.println(engine.get("result"));
      }catch (ScriptException e) {
         e.printStackTrace();
      }
   }
}

We also can use Reader to execute a script stored in the network or in a file. Storing scripts in a separate file has an advantage; we can debug and modify the script separately without any need to recompile the Java code. But, for short scripts, it is all right to put JavaScript in a String object.

package com.mano.example;
import javax.script.*;
import java.io.*;
import java.nio.file.*;
public class ScriptingDemo {
   public static void main(String[] args) {
      finalScriptEngineManager manager = new
         ScriptEngineManager();
      final ScriptEngine engine =
         manager.getEngineByName("js");
      Path scriptFile = Paths.get("sample.js");
      try {
         Reader reader = Files.newBufferedReader(scriptFile);
         engine.eval(reader);
      }catch(IOException | ScriptException e) {
         e.printStackTrace();
      }
   }
}

Note that, although calling a script through eval, it does not share state with the evaluator. It is a self-contained piece of code. The underlying script engine used by JVM is Nashorn, but soon it would be replaced by GraalVM. From the point of view of the API, there would not be any difference, but, from the point of view of performance and extensibility, GraalVM would make a difference.

There is command line tool called jjs (deprecated) in the bin/ folder of the JDK installation. This tool can be used to execute JavaScript file directly. Such as,

$ jjs sample.js

Although the example illustrated here is trivial, we can do a lot more and combine JavaScript and Java in a more meaningful way.

Groovy on JVM

Apache Groovy as a dynamic language has been used side by side with Java for quite some time. It is powerful, optionally typed with static typing and compilation capabilities. It integrates pretty well with Java program and can be used in a similar way as JavaScript. It was designed as an extension of Java. The language, object model, and the runtime libraries carry the legacy. It supports both static and dynamic typing and has native support for XML and HTML, regular expressions, lists, and associative arrays. Notice that the following code is actually a Groovy script and not Java. The syntax is kind of similar. Naturally, Java programmers have a quick grasp with an almost flat learning curve. The Groovy scripting engine has full access to the Java Standard API Library; therefore, it does not require any additional bindings to invoke the Java API Date functionality, as follows.

package com.mano.example
class SimpleApp {
   static void main(String[] args){

      Date date = new Date();
      System.out.println(date.toString());
      for(int i=0;i<10;i++)
      println(i)
   }
}

The code can be executed from the command line as follows.

$ groovy SimpleApp.groovy

There is groovyc, the Groovy compiler to compile Groovy sources into bytecode, much like javac. It simply creates a class file which then can be run like any other class file JVM typically runs. It is a command line tool and the easiest way to compile and run a Groovy script. Something like this,

$ groovyc sample.groovy

Ruby on JVM

Ruby used to be a popular dynamic language used in the Web development arena. Recently, it has brought some significant innovation for modern Web application development. The Ruby implementation for JVM platform is called JRuby. It is known for high performance and multithreading capabilities with a host of libraries derived from both Java and Ruby. Similar to Groovy, this brings great interoperability between Java and Ruby.

A simple method in JRuby to implements factorial is as follows:

def fact(num)
   if num==0
      return 1
   else
      return num*fact(num-1)
   end
end

Python on JVM

Python, as an object-oriented dynamic language, has recently gained a lot of attraction. It is widely used by the scientific community and is widely known for its large library base and frameworks from Web development to natural language processing. The JVM implementation of Python is called Jython.

If the power of Groovy is its syntactical similarity with Java, the power of Python is its simplicity of syntax. Following is a very trivial demonstration.

print "This is a simple code to demonstrate Jython"
i = 0
while i<10:
   i = i+1
   print "Value of i = ",i

The interesting aspect of Python is that people use it for the sake of simplicity. There is ample documentation and help available as we need them. With the help of Jython, we can integrate the ability of Python into an existing Java application quite seamlessly.

Conclusion

Java applications now have the leverage to enrich with extensible dynamic language support. Apart from these, there are many other languages supported by JVM. To name a few more: Clojure, Kotlin, and Scala. Surely more are going to be added in the future. The deprecation of Nashorn and incorporation of GraalVM would perhaps bring new things into the spectrum of language support. Now, a Java application can get the benefits of many languages clustered into one friendly environment. Perhaps the aim is to make JVM a language-independent platform as well.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories