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.
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.
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 download 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.
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.
On the terminal, we’ll call the jre8 using MS-DOS syntaxRunning 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 with JRE
- -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 application, 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.
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.
6. More articles
- How to update Java for Windows 10, macOS, and Android
- Online Java Compiler – What options are there
- Java Tutorial for Beginners (with video)
- Best Way to Learn Java Programming Online
- Download and Install Java Development Kit (JDK) 13
- How to Check Java version in Windows, Linux, MacOS
- What is Java used for
7. Download the Source Code
You can download the full source code of this example here: Java Runtime Environment Tutorial