Files | Download |
License | BSD 3-clause |
Optimized for... | |
---|---|
OS | Linux* kernel version 4.3 or higher |
Hardware required | Emulated: See How to Emulate Persistent Memory Using Dynamic Random-access Memory (DRAM) |
Software | JDK, Persistent Memory Developers Kit (PMDK) libraries and Persistent Collections for Java* (PCJ) |
Prerequisites | Familiarity with Java |
Summary | This example application demonstrates the usage of PersistentString class and ObjectDirectory collection from the PCJ. |
Introduction
This article and accompanying code sample shows how to create a Hello World application using the PersistentString class and ObjectDirectory collection of the Persistent Collections for Java* (PCJ). The sample writes a “Hello...” message to persistent memory or reads it back with a console notification, depending on user input. You can try this code sample using Intel®Optane™ DC persistent memory, or with emulation of persistent memory using DRAM.
Prerequisites
The article assumes that you have a basic understanding of persistent memory concepts and are familiar with the features of the Persistent Memory Development Kit (PMDK). If not, visit the Intel® Developer Zone’s Persistent Memory site, to find the information you need to get started.
Code Sample Design
The sample accesses the persistent memory region by using a memory-mapped file called a persistent memory heap (in PMDK’s terminology it’s called a pool). The config.properties file, which is stored in the current working directory, defines the path to the persistent memory heap through the option persistent _heap, as well as the size (in our case, 2GB). The sample will automatically use this memory heap to access persistent memory. Here is an example config.properties file:
path=/mnt/mem/persistent_heap
size=2147483648
After creating (or just opening) the heap, define a persistent string “Hello…” using the PCJ PersistentString class. Depending on the option passed in at execution time (“R” for read or “W” for write), the code sample performs a read from or a write to the persistent memory heap. Option “Q” exits the program.
/* This is a simple Java program.
* FileName : "Hello_pcj.java".
*/
import lib.util.persistent.*;
import lib.util.persistent.types.*;
import java.util.Scanner;
class Hello_pcj
{
// Your program begins with a call to main().
// Prints "Hello, Persistent Memory" to the console.
public static void main(String args[])
{
String option = "0";
// Create string
PersistentString msg = new PersistentString("Hello Persistent Memory!!!");
//Create a scanner to read the command-line input
Scanner scanner = new Scanner(System.in);
while (!(option.equals("W") || option.equals("R")
|| option.equals("Q"))) {
//Prompt for user's input
System.out.print("\nEnter <W> for Write to persistent memory, <R> for Read from persistent memory or <Q> to Quit: ");
//Read the input as a String
option = scanner.next();
}
switch(option)
{ case "W":
// Store string into persistent object directory with 'My_String'
ObjectDirectory.put("My_String", msg);
// Print string to console
System.out.printf("\nWrite the (%s) string to persistent memory.\n",msg);
break;
case "R":
// Read string back out from persistent object directory
PersistentString originalMsg = ObjectDirectory.get("My_String", PersistentString.class);
// Validate the string originalMsg with msg
if (!(originalMsg == null) && originalMsg.equals(msg))
// Print string to console
System.out.printf("\nRead the (%s) string from persistent memory.\n",originalMsg);
else
System.out.printf("\nNo (Hello...) string in persistent memory!!!\n");
break;
case "Q":
//Quit the program
break;
default:
System.out.printf("\nUnknown option (%s) string.\n", option);
System.out.printf("\nOptions are <W> or <R>.\n");
break;
}
}
}
Data Structures
The primary data structure for the “Hello” program is implemented by the ObjectDirectory class. This class performs the role of root object for the heap (PCJ gives us a default root class), implemented as a key-value container where keys are strings, and values are pointers to persistent objects.
A Code Walk-through
The persistent string “Hello Persistent Memory!!!” is defined in the main program.
// Create string
PersistentString msg = new PersistentString("Hello Persistent Memory!!!");
Next, the program parses the input from the command line to decide whether to read from or write to persistent memory.
The Write Option
When the program starts, the user is prompted to select one of the options. When the option “W” for writing to persistent memory is selected, the sample uses the ObjectDirectory.put method to carry out the task. As you’ll see in the code, there is no need to open the heap explicitly. After defining the heap and its size in the configuration file described above, PCJ will open it automatically when the program starts. See code snippet below for more details:
Step1 – Write the “Hello…” message to the persistent memory
// Store string into persistent object directory with 'My_String'
ObjectDirectory.put("My_String", msg);
Step 2 – Write the “Hello…” message to console
// Print string to console
System.out.printf("\nWrite the (%s) string to persistent memory.\n", msg);
The Read Option
When the user selects the “R” option at program start to read from persistent memory, the sample uses the ObjectDirectory.get method to carry out the task. As for write, the heap has already been created, and the task can be accomplished in two steps without the need to open the heap explicitly. See the code snippet below for more details:
Step 1. Read the “Hello…” message from the persistent memory
// Read string back out from persistent object directory
PersistentString originalMsg = ObjectDirectory.get("My_String", PersistentString.class);
Step 2. Write the “Hello…” message to console
// Print string to console
System.out.printf("\nRead the (%s) string to persistent memory.\n", msg);
Option “Q” is to Exit the Program
The “Q” option is used to exit the program.
Compile and Run
A Makefile is included to help with compiling and building the binary. Running make compiles it in the current working directory:
$ make
To run the binary after compilation, do this:
$ make run
java -cp .:/home/thai/github/pmdk-examples/lib/pcj/target/classes -Djava.library.path=/home/thai/github/pmdk-examples/lib/pcj/target/cppbuild Hello_pcj
Opening heap... Cleaning up heap... Heap opened.
Enter <W> for Write to persistent memory, <R> for Read from persistent memory or <Q> to Quit: W
Write the (Hello Persistent Memory!!!) string to persistent memory.
$ make run
java -cp .:/home/thai/github/pmdk-examples/lib/pcj/target/classes -Djava.library.path=/home/thai/github/pmdk-examples/lib/pcj/target/cppbuild Hello_pcj
Opening heap... Cleaning up heap... Heap opened.
Enter <W> for Write to persistent memory, <R> for Read from persistent memory or <Q> to Quit: R
Read the (Hello Persistent Memory!!!) string from persistent memory.
$ make run
java -cp .:/home/thai/github/pmdk-examples/lib/pcj/target/classes -Djava.library.path=/home/thai/github/pmdk-examples/lib/pcj/target/cppbuild Hello_pcj
Opening heap... Cleaning up heap... Heap opened.
Enter <W> for Write to persistent memory, <R> for Read from persistent memory or <Q> to Quit: Q
$
Summary
The “Hello…” sample code in this article demonstrates usage of the PMDK PersistentString class and the PCJ ObjectDirectory collection. The code sample is included with this article to make it easy for you to build and run the program yourself. To learn more about PCJ, watch the short video Introducing the Persistent Collections for Java Library and read the article Code Sample: Introduction to Java* API for Persistent Memory Programming. Find more persistent memory programming examples in the PMDK GitHub* repository.
About the Author
Thai Le is a software engineer focusing on storage and performance computing analysis at Intel Corporation. He works in the related field for over 20 years and currently manages a server lab for the data center group.
Steven Briscoe is an industry technical specialist driving the adoption of persistent memory with cloud service providers at Intel Corporation.