Table of Contents
Fetching ...

Object Graph Programming

Aditya Thimmaiah, Leonidas Lampropoulos, Christopher J. Rossbach, Milos Gligoric

TL;DR

This work introduces Object Graph Programming (OGO), a paradigm that treats the JVM's in‑memory object heap as a property graph and exposes declarative querying and updating via Cypher. The authors implement two Java prototypes: an in‑memory engine (OGO^Mem) and a Neo4j-based pipeline (OGO^Neo) that translates object graphs into a graph database for Cypher execution. They formalize OGO with Featherweight Java semantics and demonstrate practical utility by rewriting hundreds of assertions and implementing library methods in OGO, then evaluating performance across open‑source projects. Results indicate that the in‑memory approach delivers strong performance, while the Neo4j variant provides rich tooling and debugging capabilities, with an open-source release enabling broader adoption and experimentation.

Abstract

We introduce Object Graph Programming (OGO), which enables reading and modifying an object graph (i.e., the entire state of the object heap) via declarative queries. OGO models the objects and their relations in the heap as an object graph thereby treating the heap as a graph database: each node in the graph is an object (e.g., an instance of a class or an instance of a metadata class) and each edge is a relation between objects (e.g., a field of one object references another object). We leverage Cypher, the most popular query language for graph databases, as OGO's query language. Unlike LINQ, which uses collections (e.g., List) as a source of data, OGO views the entire object graph as a single "collection". OGO is ideal for querying collections (just like LINQ), introspecting the runtime system state (e.g., finding all instances of a given class or accessing fields via reflection), and writing assertions that have access to the entire program state. We prototyped OGO for Java in two ways: (a) by translating an object graph into a Neo4j database on which we run Cypher queries, and (b) by implementing our own in-memory graph query engine that directly queries the object heap. We used OGO to rewrite hundreds of statements in large open-source projects into OGO queries. We report our experience and performance of our prototypes.

Object Graph Programming

TL;DR

This work introduces Object Graph Programming (OGO), a paradigm that treats the JVM's in‑memory object heap as a property graph and exposes declarative querying and updating via Cypher. The authors implement two Java prototypes: an in‑memory engine (OGO^Mem) and a Neo4j-based pipeline (OGO^Neo) that translates object graphs into a graph database for Cypher execution. They formalize OGO with Featherweight Java semantics and demonstrate practical utility by rewriting hundreds of assertions and implementing library methods in OGO, then evaluating performance across open‑source projects. Results indicate that the in‑memory approach delivers strong performance, while the Neo4j variant provides rich tooling and debugging capabilities, with an open-source release enabling broader adoption and experimentation.

Abstract

We introduce Object Graph Programming (OGO), which enables reading and modifying an object graph (i.e., the entire state of the object heap) via declarative queries. OGO models the objects and their relations in the heap as an object graph thereby treating the heap as a graph database: each node in the graph is an object (e.g., an instance of a class or an instance of a metadata class) and each edge is a relation between objects (e.g., a field of one object references another object). We leverage Cypher, the most popular query language for graph databases, as OGO's query language. Unlike LINQ, which uses collections (e.g., List) as a source of data, OGO views the entire object graph as a single "collection". OGO is ideal for querying collections (just like LINQ), introspecting the runtime system state (e.g., finding all instances of a given class or accessing fields via reflection), and writing assertions that have access to the entire program state. We prototyped OGO for Java in two ways: (a) by translating an object graph into a Neo4j database on which we run Cypher queries, and (b) by implementing our own in-memory graph query engine that directly queries the object heap. We used OGO to rewrite hundreds of statements in large open-source projects into OGO queries. We report our experience and performance of our prototypes.
Paper Structure (15 sections, 2 equations, 10 figures, 4 tables)

This paper contains 15 sections, 2 equations, 10 figures, 4 tables.

Figures (10)

  • Figure 1: Creating and querying instances and relations between instances using OGO. Graphs above queries visualize the results of those queries. (a) The $\mathtt{CREATE}$ clause is first used to create instances of $\mathtt{BinaryTree}$ and $\mathtt{Node}$ followed by which a $\mathtt{MERGE}$ clause is used to create relations between the created instances. The reference to the created $\mathtt{BinaryTree}$ instance (reachable from all instances created by the $\mathtt{CREATE}$ clause under transitive closure) is returned at the end of the query to prevent the created instances from being garbage collected. (b) The query pattern is undirected and unconstrained in terms of the instance $\mathtt{type}$ being matched and their distance from n (root) and hence all reachable objects are returned. This is particularly useful for identifying object confinement issues. (c) The query pattern is directed and constrained to $\mathtt{Node}$ instances reachable from n through fields $\mathtt{left}$ or $\mathtt{right}$ that are exactly 2 hops away.
  • Figure 2: Methods from Java collections framework using OGO. (a) The nested static class $\mathtt{Node}$ stores a key-value pair and the reference field $\mathtt{table}$ stores all the entries in the map. (b) The imperative implementation of $\mathtt{containsKey}$ uses the $\mathtt{getNode}$ method. (c) OGO (OGO$^{Mem}$) can also be used to invoke instance methods as shown in the $\mathtt{WHERE}$ clause.
  • Figure 3: OGO API available via the $\mathtt{OGO\xspace}$ class. Bounded queries (lines \ref{['line:bounded_query']}, \ref{['line:bounded_query_object']}, \ref{['line:other_query_begin']} and \ref{['line:bounded_query_long']}) contain an additional root argument that constraints the query execution to a subgraph (limited to only objects reachable from the root argument under transitive closure) of the JVM heap object graph.
  • Figure 4: Overview of OGO (and two implementations: OGO$^{Neo}$ and OGO$^{Mem}$).
  • Figure 5: An example class, its test class and the corresponding object graph shown as a property graph. (c) instances of Node, BinaryTree and java.lang.Class are shown colored black, blue and grey. The local variable references are shown as dashed edges. Reference fields ( left,right) are mapped as node relations whereas primitive( value,size) and String fields are mapped as node properties.
  • ...and 5 more figures