Implementation of an in-memory object graph store, dubbed ϵStore. Our key innovation is a storage model -- epsilon store -- that equates an object on the heap to a node in a graph store. Thus any object on the heap (without changes) can be a part of one, or multiple, graph stores, and vice versa, any node in a graph store can be accessed like any other object on the heap. ϵStore uses a subset of the Cypher query language to query the graph store. By design, the result of any query is a table of references to objects on the heap, which users can manipulate the same way as any other object on the heap in their programs.
If you want to run in an isolated container, skip installing Java, Maven, and the other tools in Prerequisites. Docker installs those dependencies and ϵStore during the build. Start a shell with:
docker build -t estore .
docker run --rm -it -p 1234:1234 estorePort 1234 is mapped to the host. Inside the container, run
./s exec_estore and query the server as described under Running the
Application.
-
Capturing a Java object graph and querying it with Cypher-like syntax.
Person charlie = new Person("Charlie", 25); Person bob = new Person("Bob", 30, charlie); Person alice = new Person("Alice", 28, bob); Estore db = new Estore("exampleDb"); db.captureAll(alice); // MATCH finds Person objects; RETURN puts them in column p Table result = db.query("MATCH (p:`org.estore.example.Person`) RETURN p"); result.print(); Person p = (Person) result.get("p").get(0); System.out.println(p.name + ", " + p.age); System.out.println(p.friend.name);
aliceis an ordinary JavaPersonobject (name"Alice", age 28). Itsfriendfield points to Bob, and Bob'sfriendfield points to Charlie, so the in-memory graph is Alice → Bob → Charlie.captureAll(alice)walks that graph from Alice and stores every reachable object. The query finds thosePersonobjects (MATCH) and returns them as a table column namedp(RETURN). Cells in that table are the same heap objects, so they can be printed, cast toPerson, and used like any other Java object — including followingfriendin ordinary Java. -
Querying object relationships.
Table friends = db.query("MATCH (a:`org.estore.example.Person`)-[:friend]->(b:`org.estore.example.Person`) RETURN a, b"); for (int i = 0; i < friends.getSize(); i++) { Person a = (Person) friends.get("a").get(i); Person b = (Person) friends.get("b").get(i); System.out.println(a.name + " → " + b.name); }
-[:friend]->follows thefriendfield between capturedPersonobjects and returns each matched pair. The loop casts those cells back toPersonand prints the names.
After packaging (see the next section), ϵStore can be used in a Maven project.
The client jar can be added as a dependency to a third-party project by adding the following to its pom.
<dependency>
<groupId>org.estore</groupId>
<artifactId>estore</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath><!-- ENTER full path to client jar including jar name --></systemPath>
</dependency>The project requires the following dependencies:
- Java 8
- Maven
- wget
- zstd
- tar
- gzip
- nc for the quick query test
Run the installation script to automatically install all required dependencies:
./s install_depsThis will check for and install any missing dependencies on your system.
Alternatively, verify your dependencies are correctly installed:
./s check_depsOn Debian/Ubuntu, run install_deps with sudo. On macOS, use Homebrew
instead (brew install openjdk@8 maven wget zstd).
Compile the estore project:
./s compile_estoreTo compile and install the complete project:
./s install_estoreExecute the test suite:
mvn -pl estore test verifyThe JaCoCo code coverage report is generated at estore/target/site/jacoco/index.html.
Start the estore server and query it over the network:
./s exec_estoreIn another terminal, send a Cypher-like query over TCP (default port 1234):
echo 'MATCH (n) RETURN n' | nc localhost 1234Example output:
╔═════════╗
║ n ║
╠═════════╣
║ (empty) ║
╚═════════╝
Send q to stop the server.
Auto-format Java code according to project standards:
mvn spotless:apply
mvn verifyPerform a complete setup with dependency checks and full installation:
./s end_to_endThis repository contains code related to the following publication:
@inproceedings{ThimmaiahETAL25eStore,
author = {Thimmaiah, Aditya and Yi, Zijian and Kenis, Joseph and Rossbach, Christopher J. and Gligoric, Milos},
title = {In-memory Object Graph Stores},
booktitle = {European Conference on Object-Oriented Programming},
pages = {30:1--30:30},
year = {2025},
}