Core Java

Java Runtime Environment Tutorial

In this article, we’re going to discuss Java Runtime Environment, the bundle used to run Java applications and libraries.

1. What is a runtime environment?

The runtime environment is the environment in which a program or application is executed. As soon as a software program is executed, it is in a runtime state.

Java Runtime Environment (JRE) is the software bundle to execute the Java class libraries. This bundle is a bit different from Java Development Kit (JDK), due to it has only the necessary libraries and the Java Virtual Machine (JVM) to execute the Java-based application.

As the runtime environment is just to execute the software, it won’t have some development tools for debugging and compiling.

The first thing we can ask is why not use the JDK already? That’s because, in a production environment, it’s not a good deal to have tools that can expose the application’s source code. So, using a runtime environment is the best option to execute our application and also use just the necessary to take advantage of available resources.

In the next sessions, we’re going to see how to set up and use the JRE and some features present in this environment.

2. Pre-requisites

The JDK already brings the JRE embedded. However, for this article, we’ll use Java SE Runtime Environment 8u281 due to licensing reasons. This version is the last free JRE found today. Download the compatible version for your OS here. I recommend downloading the compressed file, as we’re going to take some work to use together with JDK, if necessary.

The minimum Java version for executing the article’s example is JDK 8 (find here), but we can use the most recently released Java version JDK 16 on Oracle’s official site or the OpenJDK version.

Also, I’m using the most recent IntelliJ version, but you can use any IDE with support for the versions recommended above.

3. Installing and using the JRE

After downloading the JRE package, if you have a JDK configured in your machine, you can walk through item 3.2. The first move is to extract the compressed package (if you downloaded it) in a proper directory.

3.1 Set up environment

When using a Linux or macOS system, we can use the terminal to set up environment variables. Here we’ll define the JAVA_HOME variable to use in our OS.

Setup Linux/MacOS variable

// Linux
$ export JAVA_HOME=/your_jre_extracted_folder/jre1.8.0_281.jre/
// MacOS
$ export JAVA_HOME=/your_jre_extracted_folder/jre1.8.0_281.jre/Contents/Home

On Windows, you go to your Control Panel > System > Advanced system settings > Environment Variables and set the JAVA_HOME variable.

java runtime environment - java_home
JAVA_HOME on Windows

To test the installation, just run the command below to check the version available. Works for all OS.

Check installation

$ java -version
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

3.2 Set up with JDK

To use the JRE together with our JDK, we need to do a little trick. Instead of using the traditional JAVA_HOME variable, we’ll use another variable that indicates the JRE location. For that, I name the variable JRE_HOME.

Setup Linux/MacOS JRE_HOME variable

// Linux
$ export JRE_HOME=/you_jre_extracted_folder/jre1.8.0_281.jre/
// MacOS
$ export JRE_HOME=/you_jre_extracted_folder/jre1.8.0_281.jre/Contents/Home

Linux and macOS have a feature called that makes our life easier. With this command, we can create a shortcut to call the java executor from our JRE_HOME.

Using alias command Linux/MacOS

$ alias jre8=$JRE_HOME/bin/java

Now, instead of using the java -version, we’ll use the alias created above.

Running alias command

$ jre8 -version
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

Almost the same on Windows, but a bit different. We are going to create the JRE_HOME variable as well, but we’ll create a “kind of” alias when creating another variable called jre8 pointing to the previous JRE_HOME.

The place to create the environment variable is the same Control Panel > System > Advanced system settings > Environment Variables.

java runtime environment - jre_home
JRE_HOME on Windows
java runtime environment - jre8
jre8 variable

On the terminal, we’ll call the jre8 using MS-DOS syntax

Running jre on Windows

> %jre8% -version
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

3.3 Running a Java class

To execute a Java class, we’ll need a .class file already compiled. I put a simple class called TestMain on the source code of this article, and you can run it with the command below:

Running Java class

// with JAVA_HOME (any OS)
$ java TestMain
Hello World!
// with JRE_HOME (Linux/MacOS)
$ jre8 TestMain
Hello World!
// with JRE_HOME (Windows)
> %jre8% TestMain

4. Java memory and the JRE

When we talk about the production environment, memory management is a great challenge. JRE has some features that help us on that mission using a few command lines to do it.

4.1 Memory management

Memory management is the process of allocating new objects and removing unused objects to make space for those new object allocations.

There are 3 basic memory management types in Java:

  • Heap and Nursery
  • Object Allocation
  • Garbage Collection

More information and details can be read here. In the next sections, we’ll see the aspects of heap and stack space.

4.2 Heap space

The heap space in Java is the dynamic memory allocation for objects and classes at runtime. To clarify is where the JVM loads the application’s byte codes.

The memory is used as long as the application is running. When an object is created, it is always created in Heap and has global access. That means all objects can be referenced from anywhere in the application.

Also, the memory is divided into three parts called generations:

  • Young generation – this is where all new objects are allocated and aged. A minor Garbage collection occurs when this fills up.
  • Old or Tenured Generation – this is where long surviving objects are stored. When objects are stored in the Young Generation, a threshold for the object’s age is set and when that threshold is reached, the object is moved to the old generation.
  • Permanent Generation – this consists of JVM metadata for the runtime classes and application methods.

By default, the JVM heap size is 1GB. To configure the heap size of the application, we can use this set of options among JRE java command:

  • -Xms : To set an initial java heap size
  • -Xmx : To set maximum java heap size
  • -Xss : To set the Java thread stack size
  • -Xmn : For setting the size of young generation, rest of the space goes for old generation

In the example below, we’re setting 100 megabytes (m) as the maximum to our application running.

Setting heap size

// with JAVA_HOME (any OS)
$ java -Xmx100m TestMain
Hello World!
// with JRE_HOME (Linux/MacOS)
$ jre8 -Xmx100m TestMain
Hello World!
// with JRE_HOME (Windows)
> %jre8% -Xmx100m TestMain

We can also set a start memory and limit the heap.

Setting heap size start and maximum

// with JAVA_HOME (any OS)
$ java -Xms512m -Xmx1024m TestMain
Hello World!
// with JRE_HOME (Linux/MacOS)
$ jre8 -Xms512m -Xmx1024m TestMain
Hello World!
// with JRE_HOME (Windows)
> %jre8% -Xms512m -Xmx1024m TestMain

4.3 Stack space

The stack space is the temporary memory where variable values are stored when their methods are invoked. When the method ends, that block will be erased. The next method invoked will use that empty block.

This concept is called Last-In-First-Out (LIFO), which means whenever a new method is called, it’ll be inserted on the top of the stack to the application access.

Using the -Xss option we can set our stack on Java application. In the next example, we’re setting 512 kilobytes (k):

Setting heap size start and maximum

// with JAVA_HOME (any OS)
$ java -Xss512k TestMain
Hello World!
// with JRE_HOME (Linux/MacOS)
$ jre8 -Xss512k TestMain
Hello World!
// with JRE_HOME (Windows)
> %jre8% -Xss512k TestMain

4.4 Application monitoring

As JRE is a bundle to only run Java applications, some tools as monitoring aren’t included. However, we can use some JVM options to do a kind of monitoring in our Java applications.

The command below helps to see the allocation of heap space.

Dumping heap space

// with JAVA_HOME (any OS)
$ java -Xloggc:output.log -XX:+PrintGCDetails -Xms256m -Xmx512m TestMain
// with JRE_HOME (Linux/MacOS)
$ jre8 -Xloggc:output.log -XX:+PrintGCDetails -Xms256m -Xmx512m TestMain
// with JRE_HOME (Windows)
> %jre8% -Xloggc:output.log -XX:+PrintGCDetails -Xms256m -Xmx512m TestMain

The command writes the output with the option -Xloggc:output.log. In this file, we will see how JVM manages the initial (-XX:InitialHeapSize) and maximum (-XX:MaxHeapSize) memory allocation. Also, we see some information about Garbage Collection dealing with heap space.

output

Java HotSpot(TM) 64-Bit Server VM (25.281-b09) for bsd-amd64 JRE (1.8.0_281-b09), built on Dec  9 2020 12:44:49 by "java_re" with gcc 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)
Memory: 4k page, physical 8388608k(33900k free)

/proc/meminfo:

CommandLine flags: -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=536870912 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Heap
 PSYoungGen      total 76288K, used 3932K [0x00000007b5580000, 0x00000007baa80000, 0x00000007c0000000)
  eden space 65536K, 6% used [0x00000007b5580000,0x00000007b5957240,0x00000007b9580000)
  from space 10752K, 0% used [0x00000007ba000000,0x00000007ba000000,0x00000007baa80000)
  to   space 10752K, 0% used [0x00000007b9580000,0x00000007b9580000,0x00000007ba000000)
 ParOldGen       total 175104K, used 0K [0x00000007a0000000, 0x00000007aab00000, 0x00000007b5580000)
  object space 175104K, 0% used [0x00000007a0000000,0x00000007a0000000,0x00000007aab00000)
 Metaspace       used 2511K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 267K, capacity 386K, committed 512K, reserved 1048576K

More options can be explored here in Oracle’s JVM HotSpot Debugging.

Note: the command above is deprecated since Java 9. An alternative way is using the -Xlog:gc option from Java 9 and newer versions.

5. Summary

In summary, we’ve seen the differences between the JRE bundle and JDK. Further, we could install and set up the standalone JRE, and change some settings to use it instead of JDK.

Also, we could check how memory management works using some command option lines introduced in JRE to handle JVM memory use and do a kind of monitoring too.

7. Download the Source Code

Download
You can download the full source code of this example here: Java Runtime Environment Tutorial

Last updated on Jan. 13th, 2021

Sergio Lauriano Junior

Sergio is graduated in Software Development in the University City of São Paulo (UNICID). During his career, he get involved in a large number of projects such as telecommunications, billing, data processing, health and financial services. Currently, he works in financial area using mainly Java and IBM technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button