blob: 22dcc2019b9414c710abc8dd129248fe6e71fba7 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en" data-content_root="" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Memory Management &#8212; Apache Arrow v17.0.0.dev52</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "light";
</script>
<!-- Loaded before other Sphinx assets -->
<link href="../_static/styles/theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/styles/bootstrap.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/styles/pydata-sphinx-theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../_static/vendor/fontawesome/6.5.1/css/all.min.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-solid-900.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-brands-400.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../_static/vendor/fontawesome/6.5.1/webfonts/fa-regular-400.woff2" />
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/theme_overrides.css" />
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae" />
<link rel="preload" as="script" href="../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae" />
<script src="../_static/vendor/fontawesome/6.5.1/js/all.min.js?digest=8d27b9dea8ad943066ae"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'java/memory';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.15.2';
DOCUMENTATION_OPTIONS.theme_switcher_json_url = '/docs/_static/versions.json';
DOCUMENTATION_OPTIONS.theme_switcher_version_match = 'dev/';
DOCUMENTATION_OPTIONS.show_version_warning_banner = true;
</script>
<link rel="canonical" href="https://arrow.apache.org/docs/java/memory.html" />
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="ValueVector" href="vector.html" />
<link rel="prev" title="Installing Java Modules" href="install.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="en"/>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '20']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode="">
<a id="pst-skip-link" class="skip-link" href="#main-content">Skip to main content</a>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>
Back to top
</button>
<input type="checkbox"
class="sidebar-toggle"
name="__primary"
id="__primary"/>
<label class="overlay overlay-primary" for="__primary"></label>
<input type="checkbox"
class="sidebar-toggle"
name="__secondary"
id="__secondary"/>
<label class="overlay overlay-secondary" for="__secondary"></label>
<div class="search-button__wrapper">
<div class="search-button__overlay"></div>
<div class="search-button__search-container">
<form class="bd-search d-flex align-items-center"
action="../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
id="search-input"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form></div>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar">
<div class="bd-header__inner bd-page-width">
<label class="sidebar-toggle primary-toggle" for="__primary">
<span class="fa-solid fa-bars"></span>
</label>
<div class="col-lg-3 navbar-header-items__start">
<div class="navbar-item">
<a class="navbar-brand logo" href="../index.html">
<img src="../_static/arrow.png" class="logo__image only-light" alt="Apache Arrow v17.0.0.dev52 - Home"/>
<script>document.write(`<img src="../_static/arrow-dark.png" class="logo__image only-dark" alt="Apache Arrow v17.0.0.dev52 - Home"/>`);</script>
</a></div>
</div>
<div class="col-lg-9 navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav class="navbar-nav">
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item">
<a class="nav-link nav-internal" href="../format/index.html">
Specifications
</a>
</li>
<li class="nav-item">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links">
Implementations
</button>
<ul id="pst-nav-more-links" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item current active">
<a class="nav-link dropdown-item nav-internal" href="index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
`);
</script>
</div>
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
`);
</script>
</div>
<label class="sidebar-toggle secondary-toggle" for="__secondary" tabindex="0">
<span class="fa-solid fa-outdent"></span>
</label>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<div class="bd-sidebar-primary bd-sidebar">
<div class="sidebar-header-items sidebar-primary__section">
<div class="sidebar-header-items__center">
<div class="navbar-item">
<nav class="navbar-nav">
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item">
<a class="nav-link nav-internal" href="../format/index.html">
Specifications
</a>
</li>
<li class="nav-item">
<a class="nav-link nav-internal" href="../developers/index.html">
Development
</a>
</li>
<li class="nav-item dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links-2">
Implementations
</button>
<ul id="pst-nav-more-links-2" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item current active">
<a class="nav-link dropdown-item nav-internal" href="index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-3"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-3"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-3"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-3">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</span></a>
</li>
</ul></div>
</div>
</div>
<div class="sidebar-primary-items__start sidebar-primary__section">
<div class="sidebar-primary-item">
<nav class="bd-docs-nav bd-links"
aria-label="Section Navigation">
<p class="bd-links__title" role="heading" aria-level="1">Section Navigation</p>
<div class="bd-toc-item navbar-nav"><ul class="current nav bd-sidenav">
<li class="toctree-l1"><a class="reference internal" href="quickstartguide.html">Quick Start Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="overview.html">High-Level Overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="install.html">Installing Java Modules</a></li>
<li class="toctree-l1 current active"><a class="current reference internal" href="#">Memory Management</a></li>
<li class="toctree-l1"><a class="reference internal" href="vector.html">ValueVector</a></li>
<li class="toctree-l1"><a class="reference internal" href="vector_schema_root.html">Tabular Data</a></li>
<li class="toctree-l1"><a class="reference internal" href="table.html">Table</a></li>
<li class="toctree-l1"><a class="reference internal" href="ipc.html">Reading/Writing IPC formats</a></li>
<li class="toctree-l1"><a class="reference internal" href="algorithm.html">Java Algorithms</a></li>
<li class="toctree-l1"><a class="reference internal" href="flight.html">Arrow Flight RPC</a></li>
<li class="toctree-l1"><a class="reference internal" href="flight_sql.html">Arrow Flight SQL</a></li>
<li class="toctree-l1"><a class="reference internal" href="flight_sql_jdbc_driver.html">Arrow Flight SQL JDBC Driver</a></li>
<li class="toctree-l1"><a class="reference internal" href="dataset.html">Dataset</a></li>
<li class="toctree-l1"><a class="reference internal" href="substrait.html">Substrait</a></li>
<li class="toctree-l1"><a class="reference internal" href="cdata.html">C Data Interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="jdbc.html">Arrow JDBC Adapter</a></li>
<li class="toctree-l1"><a class="reference internal" href="reference/index.html">Reference (javadoc)</a></li>
<li class="toctree-l1"><a class="reference external" href="https://arrow.apache.org/cookbook/java/">Java cookbook</a></li>
</ul>
</div>
</nav></div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
</div>
<div id="rtd-footer-container"></div>
</div>
<main id="main-content" class="bd-main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb">
<ul class="bd-breadcrumbs">
<li class="breadcrumb-item breadcrumb-home">
<a href="../index.html" class="nav-link" aria-label="Home">
<i class="fa-solid fa-home"></i>
</a>
</li>
<li class="breadcrumb-item"><a href="index.html" class="nav-link">Java Implementation</a></li>
<li class="breadcrumb-item active" aria-current="page">Memory Management</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<section id="memory-management">
<h1><a class="toc-backref" href="#id3" role="doc-backlink">Memory Management</a><a class="headerlink" href="#memory-management" title="Permalink to this heading">#</a></h1>
<p>The memory modules contain all the functionality that Arrow uses to allocate and deallocate memory. This document is divided in two parts:
The first part, <em>Memory Basics</em>, provides a high-level introduction. The following section, <em>Arrow Memory In-Depth</em>, fills in the details.</p>
<nav class="contents" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><p><a class="reference internal" href="#memory-management" id="id3">Memory Management</a></p>
<ul>
<li><p><a class="reference internal" href="#memory-basics" id="id4">Memory Basics</a></p>
<ul>
<li><p><a class="reference internal" href="#getting-started" id="id5">Getting Started</a></p></li>
<li><p><a class="reference internal" href="#arrowbuf" id="id6">ArrowBuf</a></p>
<ul>
<li><p><a class="reference internal" href="#why-arrow-uses-direct-memory" id="id7">Why Arrow Uses Direct Memory</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#bufferallocator" id="id8">BufferAllocator</a></p></li>
<li><p><a class="reference internal" href="#reference-counting" id="id9">Reference counting</a></p></li>
<li><p><a class="reference internal" href="#development-guidelines" id="id10">Development Guidelines</a></p></li>
<li><p><a class="reference internal" href="#debugging-memory-leaks-allocation" id="id11">Debugging Memory Leaks/Allocation</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#arrow-memory-in-depth" id="id12">Arrow Memory In-Depth</a></p>
<ul>
<li><p><a class="reference internal" href="#design-principles" id="id13">Design Principles</a></p></li>
<li><p><a class="reference internal" href="#reserving-memory" id="id14">Reserving Memory</a></p></li>
<li><p><a class="reference internal" href="#reference-counting-details" id="id15">Reference Counting Details</a></p></li>
<li><p><a class="reference internal" href="#allocation-details" id="id16">Allocation Details</a></p></li>
<li><p><a class="reference internal" href="#object-hierarchy" id="id17">Object Hierarchy</a></p>
<ul>
<li><p><a class="reference internal" href="#memory-perspective" id="id18">Memory Perspective</a></p></li>
<li><p><a class="reference internal" href="#allocator-perspective" id="id19">Allocator Perspective</a></p></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
<section id="memory-basics">
<h2><a class="toc-backref" href="#id4" role="doc-backlink">Memory Basics</a><a class="headerlink" href="#memory-basics" title="Permalink to this heading">#</a></h2>
<p>This section will introduce you to the major concepts in Java’s memory management:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/ArrowBuf.html">ArrowBuf</a></p></li>
<li><p><a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/BufferAllocator.html">BufferAllocator</a></p></li>
<li><p>Reference counting</p></li>
</ul>
<p>It also provides some guidelines for working with memory in Arrow, and describes how to debug memory issues when they arise.</p>
<section id="getting-started">
<h3><a class="toc-backref" href="#id5" role="doc-backlink">Getting Started</a><a class="headerlink" href="#getting-started" title="Permalink to this heading">#</a></h3>
<p>Arrow’s memory management is built around the needs of the columnar format and using off-heap memory.
Arrow Java has its own independent implementation. It does not wrap the C++ implementation, although the framework is flexible enough
to be used with memory allocated in C++ that is used by Java code.</p>
<p>Arrow provides multiple modules: the core interfaces, and implementations of the interfaces.
Users need the core interfaces, and exactly one of the implementations.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">memory-core</span></code>: Provides the interfaces used by the Arrow libraries and applications.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">memory-netty</span></code>: An implementation of the memory interfaces based on the <a class="reference external" href="https://netty.io/wiki/">Netty</a> library.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">memory-unsafe</span></code>: An implementation of the memory interfaces based on the <a class="reference external" href="https://web.archive.org/web/20210929024401/http://www.docjar.com/html/api/sun/misc/Unsafe.java.html">sun.misc.Unsafe</a> library.</p></li>
</ul>
</section>
<section id="arrowbuf">
<h3><a class="toc-backref" href="#id6" role="doc-backlink">ArrowBuf</a><a class="headerlink" href="#arrowbuf" title="Permalink to this heading">#</a></h3>
<p>ArrowBuf represents a single, contiguous region of <a class="reference external" href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html">direct memory</a>. It consists of an address and a length,
and provides low-level interfaces for working with the contents, similar to ByteBuffer.</p>
<p>Unlike (Direct)ByteBuffer, it has reference counting built in, as discussed later.</p>
<section id="why-arrow-uses-direct-memory">
<h4><a class="toc-backref" href="#id7" role="doc-backlink">Why Arrow Uses Direct Memory</a><a class="headerlink" href="#why-arrow-uses-direct-memory" title="Permalink to this heading">#</a></h4>
<ul class="simple">
<li><p>The JVM can optimize I/O operations when using direct memory/direct buffers; it will attempt to avoid copying buffer contents to/from an intermediate buffer. This can speed up IPC in Arrow.</p></li>
<li><p>Since Arrow always uses direct memory, JNI modules can directly wrap native memory addresses instead of copying data. We use this in modules like the C Data Interface.</p></li>
<li><p>Conversely, on the C++ side of the JNI boundary, we can directly access the memory in ArrowBuf without copying data.</p></li>
</ul>
</section>
</section>
<section id="bufferallocator">
<h3><a class="toc-backref" href="#id8" role="doc-backlink">BufferAllocator</a><a class="headerlink" href="#bufferallocator" title="Permalink to this heading">#</a></h3>
<p>The <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/BufferAllocator.html">BufferAllocator</a> is primarily an arena or nursery used for accounting of buffers (ArrowBuf instances).
As the name suggests, it can allocate new buffers associated with itself, but it can also
handle the accounting for buffers allocated elsewhere. For example, it handles the Java-side accounting for
memory allocated in C++ and shared with Java using the C-Data Interface. In the code below it performs an allocation:</p>
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.ArrowBuf</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.BufferAllocator</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.RootAllocator</span><span class="p">;</span>
<span class="k">try</span><span class="p">(</span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">bufferAllocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RootAllocator</span><span class="p">(</span><span class="mi">8</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1024</span><span class="p">)){</span>
<span class="w"> </span><span class="n">ArrowBuf</span><span class="w"> </span><span class="n">arrowBuf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bufferAllocator</span><span class="p">.</span><span class="na">buffer</span><span class="p">(</span><span class="mi">4</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1024</span><span class="p">);</span>
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">arrowBuf</span><span class="p">);</span>
<span class="w"> </span><span class="n">arrowBuf</span><span class="p">.</span><span class="na">close</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>ArrowBuf<span class="o">[</span><span class="m">2</span><span class="o">]</span>,<span class="w"> </span>address:140363641651200,<span class="w"> </span>length:4096
</pre></div>
</div>
<p>The concrete implementation of the BufferAllocator interface is <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/RootAllocator.html">RootAllocator</a>. Applications should generally create
one RootAllocator at the start of the program, and use it through the BufferAllocator interface. Allocators implement
AutoCloseable and must be closed after the application is done with them; this will check that all outstanding memory
has been freed (see the next section).</p>
<p>Arrow provides a tree-based model for memory allocation. The RootAllocator is created first, then more allocators
are created as children of an existing allocator via <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/RootAllocator.html#newChildAllocator-java.lang.String-org.apache.arrow.memory.AllocationListener-long-long-">newChildAllocator</a>. When creating a RootAllocator or a child
allocator, a memory limit is provided, and when allocating memory, the limit is checked. Furthermore, when allocating
memory from a child allocator, those allocations are also reflected in all parent allocators. Hence, the RootAllocator
effectively sets the program-wide memory limit, and serves as the master bookkeeper for all memory allocations.</p>
<p>Child allocators are not strictly required, but can help better organize code. For instance, a lower memory limit can
be set for a particular section of code. The child allocator can be closed when that section completes,
at which point it checks that that section didn’t leak any memory.
Child allocators can also be named, which makes it easier to tell where an ArrowBuf came from during debugging.</p>
</section>
<section id="reference-counting">
<h3><a class="toc-backref" href="#id9" role="doc-backlink">Reference counting</a><a class="headerlink" href="#reference-counting" title="Permalink to this heading">#</a></h3>
<p>Because direct memory is expensive to allocate and deallocate, allocators may share direct buffers. To managed shared buffers
deterministically, we use manual reference counting instead of the garbage collector.
This simply means that each buffer has a counter keeping track of the number of references to
the buffer, and the user is responsible for properly incrementing/decrementing the counter as the buffer is used.</p>
<p>In Arrow, each ArrowBuf has an associated <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/ReferenceManager.html">ReferenceManager</a> that tracks the reference count. You can retrieve
it with ArrowBuf.getReferenceManager(). The reference count is updated using <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/ReferenceManager.html#release--">ReferenceManager.release</a> to decrement the count,
and <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/ReferenceManager.html#retain--">ReferenceManager.retain</a> to increment it.</p>
<p>Of course, this is tedious and error-prone, so instead of directly working with buffers, we typically use
higher-level APIs like ValueVector. Such classes generally implement Closeable/AutoCloseable and will automatically
decrement the reference count when closed.</p>
<p>Allocators implement AutoCloseable as well. In this case, closing the allocator will check that all buffers
obtained from the allocator are closed. If not, <code class="docutils literal notranslate"><span class="pre">close()</span></code> method will raise an exception; this helps track
memory leaks from unclosed buffers.</p>
<p>Reference counting needs to be handled carefully. To ensure that an
independent section of code has fully cleaned up all allocated buffers, use a new child allocator.</p>
</section>
<section id="development-guidelines">
<h3><a class="toc-backref" href="#id10" role="doc-backlink">Development Guidelines</a><a class="headerlink" href="#development-guidelines" title="Permalink to this heading">#</a></h3>
<p>Applications should generally:</p>
<ul class="simple">
<li><p>Use the BufferAllocator interface in APIs instead of RootAllocator.</p></li>
<li><p>Create one RootAllocator at the start of the program and explicitly pass it when needed.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">close()</span></code> allocators after use (whether they are child allocators or the RootAllocator), either manually or preferably via a try-with-resources statement.</p></li>
</ul>
</section>
<section id="debugging-memory-leaks-allocation">
<h3><a class="toc-backref" href="#id11" role="doc-backlink">Debugging Memory Leaks/Allocation</a><a class="headerlink" href="#debugging-memory-leaks-allocation" title="Permalink to this heading">#</a></h3>
<p>In <code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> mode, the allocator and supporting classes will record additional
debug tracking information to better track down memory leaks and issues. To
enable DEBUG mode pass the following system property to the VM when starting
<code class="docutils literal notranslate"><span class="pre">-Darrow.memory.debug.allocator=true</span></code>.</p>
<p>When DEBUG is enabled, a log will be kept of allocations. Configure SLF4J to see these logs (e.g. via Logback/Apache Log4j).
Consider the following example to see how it helps us with the tracking of allocators:</p>
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.ArrowBuf</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.BufferAllocator</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.RootAllocator</span><span class="p">;</span>
<span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">bufferAllocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RootAllocator</span><span class="p">(</span><span class="mi">8</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1024</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">ArrowBuf</span><span class="w"> </span><span class="n">arrowBuf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bufferAllocator</span><span class="p">.</span><span class="na">buffer</span><span class="p">(</span><span class="mi">4</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1024</span><span class="p">);</span>
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">arrowBuf</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Without the debug mode enabled, when we close the allocator, we get this:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="m">11</span>:56:48.944<span class="w"> </span><span class="o">[</span>main<span class="o">]</span><span class="w"> </span>INFO<span class="w"> </span>o.apache.arrow.memory.BaseAllocator<span class="w"> </span>-<span class="w"> </span>Debug<span class="w"> </span>mode<span class="w"> </span>disabled.
ArrowBuf<span class="o">[</span><span class="m">2</span><span class="o">]</span>,<span class="w"> </span>address:140508391276544,<span class="w"> </span>length:4096
<span class="m">16</span>:28:08.847<span class="w"> </span><span class="o">[</span>main<span class="o">]</span><span class="w"> </span>ERROR<span class="w"> </span>o.apache.arrow.memory.BaseAllocator<span class="w"> </span>-<span class="w"> </span>Memory<span class="w"> </span>was<span class="w"> </span>leaked<span class="w"> </span>by<span class="w"> </span>query.<span class="w"> </span>Memory<span class="w"> </span>leaked:<span class="w"> </span><span class="o">(</span><span class="m">4096</span><span class="o">)</span>
Allocator<span class="o">(</span>ROOT<span class="o">)</span><span class="w"> </span><span class="m">0</span>/4096/4096/8192<span class="w"> </span><span class="o">(</span>res/actual/peak/limit<span class="o">)</span>
</pre></div>
</div>
<p>Enabling the debug mode, we get more details:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="m">11</span>:56:48.944<span class="w"> </span><span class="o">[</span>main<span class="o">]</span><span class="w"> </span>INFO<span class="w"> </span>o.apache.arrow.memory.BaseAllocator<span class="w"> </span>-<span class="w"> </span>Debug<span class="w"> </span>mode<span class="w"> </span>enabled.
ArrowBuf<span class="o">[</span><span class="m">2</span><span class="o">]</span>,<span class="w"> </span>address:140437894463488,<span class="w"> </span>length:4096
Exception<span class="w"> </span><span class="k">in</span><span class="w"> </span>thread<span class="w"> </span><span class="s2">&quot;main&quot;</span><span class="w"> </span>java.lang.IllegalStateException:<span class="w"> </span>Allocator<span class="o">[</span>ROOT<span class="o">]</span><span class="w"> </span>closed<span class="w"> </span>with<span class="w"> </span>outstanding<span class="w"> </span>buffers<span class="w"> </span>allocated<span class="w"> </span><span class="o">(</span><span class="m">1</span><span class="o">)</span>.
Allocator<span class="o">(</span>ROOT<span class="o">)</span><span class="w"> </span><span class="m">0</span>/4096/4096/8192<span class="w"> </span><span class="o">(</span>res/actual/peak/limit<span class="o">)</span>
<span class="w"> </span>child<span class="w"> </span>allocators:<span class="w"> </span><span class="m">0</span>
<span class="w"> </span>ledgers:<span class="w"> </span><span class="m">1</span>
<span class="w"> </span>ledger<span class="o">[</span><span class="m">1</span><span class="o">]</span><span class="w"> </span>allocator:<span class="w"> </span>ROOT<span class="o">)</span>,<span class="w"> </span>isOwning:<span class="w"> </span>,<span class="w"> </span>size:<span class="w"> </span>,<span class="w"> </span>references:<span class="w"> </span><span class="m">1</span>,<span class="w"> </span>life:<span class="w"> </span><span class="m">261438177096661</span>..0,<span class="w"> </span>allocatorManager:<span class="w"> </span><span class="o">[</span>,<span class="w"> </span>life:<span class="w"> </span><span class="o">]</span><span class="w"> </span>holds<span class="w"> </span><span class="m">1</span><span class="w"> </span>buffers.
<span class="w"> </span>ArrowBuf<span class="o">[</span><span class="m">2</span><span class="o">]</span>,<span class="w"> </span>address:140437894463488,<span class="w"> </span>length:4096
<span class="w"> </span>reservations:<span class="w"> </span><span class="m">0</span>
</pre></div>
</div>
<p>Additionally, in debug mode, <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/ArrowBuf.html#print-java.lang.StringBuilder-int-org.apache.arrow.memory.BaseAllocator.Verbosity-">ArrowBuf.print()</a> can be used to obtain a debug string.
This will include information about allocation operations on the buffer with stack traces, such as when/where the buffer was allocated.</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.ArrowBuf</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.BufferAllocator</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.RootAllocator</span><span class="p">;</span>
<span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="kd">final</span><span class="w"> </span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">allocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RootAllocator</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="kd">final</span><span class="w"> </span><span class="n">ArrowBuf</span><span class="w"> </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">allocator</span><span class="p">.</span><span class="na">buffer</span><span class="p">(</span><span class="mi">1024</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">StringBuilder</span><span class="w"> </span><span class="n">sb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">StringBuilder</span><span class="p">();</span>
<span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="na">print</span><span class="p">(</span><span class="n">sb</span><span class="p">,</span><span class="w"> </span><span class="cm">/*indent*/</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">sb</span><span class="p">.</span><span class="na">toString</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>ArrowBuf[2], address:140433199984656, length:1024
event log for: ArrowBuf[2]
675959093395667 create()
at org.apache.arrow.memory.util.HistoricalLog$Event.&lt;init&gt;(HistoricalLog.java:175)
at org.apache.arrow.memory.util.HistoricalLog.recordEvent(HistoricalLog.java:83)
at org.apache.arrow.memory.ArrowBuf.&lt;init&gt;(ArrowBuf.java:96)
at org.apache.arrow.memory.BufferLedger.newArrowBuf(BufferLedger.java:271)
at org.apache.arrow.memory.BaseAllocator.bufferWithoutReservation(BaseAllocator.java:300)
at org.apache.arrow.memory.BaseAllocator.buffer(BaseAllocator.java:276)
at org.apache.arrow.memory.RootAllocator.buffer(RootAllocator.java:29)
at org.apache.arrow.memory.BaseAllocator.buffer(BaseAllocator.java:240)
at org.apache.arrow.memory.RootAllocator.buffer(RootAllocator.java:29)
at REPL.$JShell$14.do_it$($JShell$14.java:10)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:566)
at jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:209)
at jdk.jshell.execution.RemoteExecutionControl.invoke(RemoteExecutionControl.java:116)
at jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:119)
at jdk.jshell.execution.ExecutionControlForwarder.processCommand(ExecutionControlForwarder.java:144)
at jdk.jshell.execution.ExecutionControlForwarder.commandLoop(ExecutionControlForwarder.java:262)
at jdk.jshell.execution.Util.forwardExecutionControl(Util.java:76)
at jdk.jshell.execution.Util.forwardExecutionControlAndIO(Util.java:137)
at jdk.jshell.execution.RemoteExecutionControl.main(RemoteExecutionControl.java:70)
</pre></div>
</div>
<p>The BufferAllocator also provides a <code class="docutils literal notranslate"><span class="pre">BufferAllocator.toVerboseString()</span></code> which can be used in
<code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> mode to get extensive stacktrace information and events associated with various Allocator behaviors.</p>
<p>Finally, enabling the <code class="docutils literal notranslate"><span class="pre">TRACE</span></code> logging level will automatically provide this stack trace when the allocator is closed:</p>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="c1">// Assumes use of Logback; adjust for Log4j, etc. as appropriate</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">ch.qos.logback.classic.Level</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">ch.qos.logback.classic.Logger</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.ArrowBuf</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.BufferAllocator</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.apache.arrow.memory.RootAllocator</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">org.slf4j.LoggerFactory</span><span class="p">;</span>
<span class="c1">// Set log level to TRACE to get tracebacks</span>
<span class="p">((</span><span class="n">Logger</span><span class="p">)</span><span class="w"> </span><span class="n">LoggerFactory</span><span class="p">.</span><span class="na">getLogger</span><span class="p">(</span><span class="s">&quot;org.apache.arrow&quot;</span><span class="p">)).</span><span class="na">setLevel</span><span class="p">(</span><span class="n">Level</span><span class="p">.</span><span class="na">TRACE</span><span class="p">);</span>
<span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="kd">final</span><span class="w"> </span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">allocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RootAllocator</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Leak buffer</span>
<span class="w"> </span><span class="n">allocator</span><span class="p">.</span><span class="na">buffer</span><span class="p">(</span><span class="mi">1024</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| Exception java.lang.IllegalStateException: Allocator[ROOT] closed with outstanding buffers allocated (1).
Allocator(ROOT) 0/1024/1024/9223372036854775807 (res/actual/peak/limit)
child allocators: 0
ledgers: 1
ledger[1] allocator: ROOT), isOwning: , size: , references: 1, life: 712040870231544..0, allocatorManager: [, life: ] holds 1 buffers.
ArrowBuf[2], address:139926571810832, length:1024
event log for: ArrowBuf[2]
712040888650134 create()
at org.apache.arrow.memory.util.StackTrace.&lt;init&gt;(StackTrace.java:34)
at org.apache.arrow.memory.util.HistoricalLog$Event.&lt;init&gt;(HistoricalLog.java:175)
at org.apache.arrow.memory.util.HistoricalLog.recordEvent(HistoricalLog.java:83)
at org.apache.arrow.memory.ArrowBuf.&lt;init&gt;(ArrowBuf.java:96)
at org.apache.arrow.memory.BufferLedger.newArrowBuf(BufferLedger.java:271)
at org.apache.arrow.memory.BaseAllocator.bufferWithoutReservation(BaseAllocator.java:300)
at org.apache.arrow.memory.BaseAllocator.buffer(BaseAllocator.java:276)
at org.apache.arrow.memory.RootAllocator.buffer(RootAllocator.java:29)
at org.apache.arrow.memory.BaseAllocator.buffer(BaseAllocator.java:240)
at org.apache.arrow.memory.RootAllocator.buffer(RootAllocator.java:29)
at REPL.$JShell$18.do_it$($JShell$18.java:13)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:566)
at jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:209)
at jdk.jshell.execution.RemoteExecutionControl.invoke(RemoteExecutionControl.java:116)
at jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:119)
at jdk.jshell.execution.ExecutionControlForwarder.processCommand(ExecutionControlForwarder.java:144)
at jdk.jshell.execution.ExecutionControlForwarder.commandLoop(ExecutionControlForwarder.java:262)
at jdk.jshell.execution.Util.forwardExecutionControl(Util.java:76)
at jdk.jshell.execution.Util.forwardExecutionControlAndIO(Util.java:137)
reservations: 0
| at BaseAllocator.close (BaseAllocator.java:405)
| at RootAllocator.close (RootAllocator.java:29)
| at (#8:1)
</pre></div>
</div>
<p>Sometimes, explicitly passing allocators around is difficult. For example, it
can be hard to pass around extra state, like an allocator, through layers of
existing application or framework code. A global or singleton allocator instance
can be useful here, though it should not be your first choice.</p>
<p>How this works:</p>
<ol class="arabic simple">
<li><p>Set up a global allocator in a singleton class.</p></li>
<li><p>Provide methods to create child allocators from the global allocator.</p></li>
<li><p>Give child allocators proper names to make it easier to figure out where
allocations occurred in case of errors.</p></li>
<li><p>Ensure that resources are properly closed.</p></li>
<li><p>Check that the global allocator is empty at some suitable point, such as
right before program shutdown.</p></li>
<li><p>If it is not empty, review the above allocation bugs.</p></li>
</ol>
<div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="c1">//1</span>
<span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">allocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RootAllocator</span><span class="p">();</span>
<span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AtomicInteger</span><span class="w"> </span><span class="n">childNumber</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">AtomicInteger</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">...</span>
<span class="c1">//2</span>
<span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">BufferAllocator</span><span class="w"> </span><span class="nf">getChildAllocator</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">allocator</span><span class="p">.</span><span class="na">newChildAllocator</span><span class="p">(</span><span class="n">nextChildName</span><span class="p">(),</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">Long</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="c1">//3</span>
<span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">nextChildName</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="s">&quot;Allocator-Child-&quot;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">childNumber</span><span class="p">.</span><span class="na">incrementAndGet</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="c1">//4: Business code</span>
<span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="n">BufferAllocator</span><span class="w"> </span><span class="n">allocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GlobalAllocator</span><span class="p">.</span><span class="na">getChildAllocator</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="c1">//5</span>
<span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">checkGlobalCleanUpResources</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">allocator</span><span class="p">.</span><span class="na">getChildAllocators</span><span class="p">().</span><span class="na">isEmpty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">IllegalStateException</span><span class="p">(...);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">allocator</span><span class="p">.</span><span class="na">getAllocatedMemory</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">IllegalStateException</span><span class="p">(...);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="arrow-memory-in-depth">
<h2><a class="toc-backref" href="#id12" role="doc-backlink">Arrow Memory In-Depth</a><a class="headerlink" href="#arrow-memory-in-depth" title="Permalink to this heading">#</a></h2>
<section id="design-principles">
<h3><a class="toc-backref" href="#id13" role="doc-backlink">Design Principles</a><a class="headerlink" href="#design-principles" title="Permalink to this heading">#</a></h3>
<p>Arrow’s memory model is based on the following basic concepts:</p>
<ul class="simple">
<li><p>Memory can be allocated up to some limit. That limit could be a real
limit (OS/JVM) or a locally imposed limit.</p></li>
<li><p>Allocation operates in two phases: accounting then actual allocation.
Allocation could fail at either point.</p></li>
<li><p>Allocation failure should be recoverable. In all cases, the Allocator
infrastructure should expose memory allocation failures (OS or
internal limit-based) as <code class="docutils literal notranslate"><span class="pre">OutOfMemoryException</span></code>s.</p></li>
<li><p>Any allocator can reserve memory when created. This memory shall be
held such that this allocator will always be able to allocate that
amount of memory.</p></li>
<li><p>A particular application component should work to use a local
allocator to understand local memory usage and better debug memory
leaks.</p></li>
<li><p>The same physical memory can be shared by multiple allocators and the
allocator must provide an accounting paradigm for this purpose.</p></li>
</ul>
</section>
<section id="reserving-memory">
<h3><a class="toc-backref" href="#id14" role="doc-backlink">Reserving Memory</a><a class="headerlink" href="#reserving-memory" title="Permalink to this heading">#</a></h3>
<p>Arrow provides two different ways to reserve memory:</p>
<ul class="simple">
<li><p>BufferAllocator accounting reservations: When a new allocator (other
than the <code class="docutils literal notranslate"><span class="pre">RootAllocator</span></code>) is initialized, it can set aside memory
that it will keep locally for its lifetime. This is memory that will
never be released back to its parent allocator until the allocator is
closed.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">AllocationReservation</span></code> via BufferAllocator.newReservation():
Allows a short-term preallocation strategy so that a particular
subsystem can ensure future memory is available to support a
particular request.</p></li>
</ul>
</section>
<section id="reference-counting-details">
<h3><a class="toc-backref" href="#id15" role="doc-backlink">Reference Counting Details</a><a class="headerlink" href="#reference-counting-details" title="Permalink to this heading">#</a></h3>
<p>Typically, the ReferenceManager implementation used is an instance of <a class="reference external" href="https://arrow.apache.org/docs/java/reference/org/apache/arrow/memory/BufferLedger.html">BufferLedger</a>.
A BufferLedger is a ReferenceManager that also maintains the relationship between an <code class="docutils literal notranslate"><span class="pre">AllocationManager</span></code>,
a <code class="docutils literal notranslate"><span class="pre">BufferAllocator</span></code> and one or more individual <code class="docutils literal notranslate"><span class="pre">ArrowBuf</span></code>s</p>
<p>All ArrowBufs (direct or sliced) related to a single BufferLedger/BufferAllocator combination
share the same reference count and either all will be valid or all will be invalid.
For simplicity of accounting, we treat that memory as being used by one
of the BufferAllocators associated with the memory. When that allocator
releases its claim on that memory, the memory ownership is then moved to
another BufferLedger belonging to the same AllocationManager.</p>
</section>
<section id="allocation-details">
<h3><a class="toc-backref" href="#id16" role="doc-backlink">Allocation Details</a><a class="headerlink" href="#allocation-details" title="Permalink to this heading">#</a></h3>
<p>There are several Allocator types in Arrow Java:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">BufferAllocator</span></code> - The public interface application users should be leveraging</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">BaseAllocator</span></code> - The base implementation of memory allocation, contains the meat of the Arrow allocator implementation</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">RootAllocator</span></code> - The root allocator. Typically only one created for a JVM. It serves as the parent/ancestor for child allocators</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ChildAllocator</span></code> - A child allocator that derives from the root allocator</p></li>
</ul>
<p>Many BufferAllocators can reference the same piece of physical memory at the same
time. It is the AllocationManager’s responsibility to ensure that in this situation,
all memory is accurately accounted for from the Root’s perspective
and also to ensure that the memory is correctly released once all
BufferAllocators have stopped using that memory.</p>
<p>For simplicity of accounting, we treat that memory as being used by one
of the BufferAllocators associated with the memory. When that allocator
releases its claim on that memory, the memory ownership is then moved to
another BufferLedger belonging to the same AllocationManager. Note that
because a ArrowBuf.release() is what actually causes memory ownership
transfer to occur, we always proceed with ownership transfer (even if
that violates an allocator limit). It is the responsibility of the
application owning a particular allocator to frequently confirm whether
the allocator is over its memory limit (BufferAllocator.isOverLimit())
and if so, attempt to aggressively release memory to ameliorate the
situation.</p>
</section>
<section id="object-hierarchy">
<h3><a class="toc-backref" href="#id17" role="doc-backlink">Object Hierarchy</a><a class="headerlink" href="#object-hierarchy" title="Permalink to this heading">#</a></h3>
<p>There are two main ways that someone can look at the object hierarchy
for Arrow’s memory management scheme. The first is a memory based
perspective as below:</p>
<section id="memory-perspective">
<h4><a class="toc-backref" href="#id18" role="doc-backlink">Memory Perspective</a><a class="headerlink" href="#memory-perspective" title="Permalink to this heading">#</a></h4>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>+ AllocationManager
|
|-- UnsignedDirectLittleEndian (One per AllocationManager)
|
|-+ BufferLedger 1 ==&gt; Allocator A (owning)
| ` - ArrowBuf 1
|-+ BufferLedger 2 ==&gt; Allocator B (non-owning)
| ` - ArrowBuf 2
|-+ BufferLedger 3 ==&gt; Allocator C (non-owning)
| - ArrowBuf 3
| - ArrowBuf 4
` - ArrowBuf 5
</pre></div>
</div>
<p>In this picture, a piece of memory is owned by an allocator manager. An
allocator manager is responsible for that piece of memory no matter
which allocator(s) it is working with. An allocator manager will have
relationships with a piece of raw memory (via its reference to
UnsignedDirectLittleEndian) as well as references to each
BufferAllocator it has a relationship to.</p>
</section>
<section id="allocator-perspective">
<h4><a class="toc-backref" href="#id19" role="doc-backlink">Allocator Perspective</a><a class="headerlink" href="#allocator-perspective" title="Permalink to this heading">#</a></h4>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>+ RootAllocator
|-+ ChildAllocator 1
| | - ChildAllocator 1.1
| ` ...
|
|-+ ChildAllocator 2
|-+ ChildAllocator 3
| |
| |-+ BufferLedger 1 ==&gt; AllocationManager 1 (owning) ==&gt; UDLE
| | `- ArrowBuf 1
| `-+ BufferLedger 2 ==&gt; AllocationManager 2 (non-owning)==&gt; UDLE
| `- ArrowBuf 2
|
|-+ BufferLedger 3 ==&gt; AllocationManager 1 (non-owning)==&gt; UDLE
| ` - ArrowBuf 3
|-+ BufferLedger 4 ==&gt; AllocationManager 2 (owning) ==&gt; UDLE
| - ArrowBuf 4
| - ArrowBuf 5
` - ArrowBuf 6
</pre></div>
</div>
<p>In this picture, a RootAllocator owns three ChildAllocators. The first
ChildAllocator (ChildAllocator 1) owns a subsequent ChildAllocator.
ChildAllocator has two BufferLedgers/AllocationManager references.
Coincidentally, each of these AllocationManager’s is also associated
with the RootAllocator. In this case, one of the these
AllocationManagers is owned by ChildAllocator 3 (AllocationManager 1)
while the other AllocationManager (AllocationManager 2) is
owned/accounted for by the RootAllocator. Note that in this scenario,
ArrowBuf 1 is sharing the underlying memory as ArrowBuf 3. However the
subset of that memory (e.g. through slicing) might be different. Also
note that ArrowBuf 2 and ArrowBuf 4, 5 and 6 are also sharing the same
underlying memory. Also note that ArrowBuf 4, 5 and 6 all share the same
reference count and fate.</p>
</section>
</section>
</section>
</section>
</article>
<footer class="prev-next-footer">
<div class="prev-next-area">
<a class="left-prev"
href="install.html"
title="previous page">
<i class="fa-solid fa-angle-left"></i>
<div class="prev-next-info">
<p class="prev-next-subtitle">previous</p>
<p class="prev-next-title">Installing Java Modules</p>
</div>
</a>
<a class="right-next"
href="vector.html"
title="next page">
<div class="prev-next-info">
<p class="prev-next-subtitle">next</p>
<p class="prev-next-title">ValueVector</p>
</div>
<i class="fa-solid fa-angle-right"></i>
</a>
</div>
</footer>
</div>
<div class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner">
<div class="sidebar-secondary-item">
<div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
<i class="fa-solid fa-list"></i> On this page
</div>
<nav class="bd-toc-nav page-toc" aria-labelledby="pst-page-navigation-heading-2">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#memory-basics">Memory Basics</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#getting-started">Getting Started</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#arrowbuf">ArrowBuf</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#why-arrow-uses-direct-memory">Why Arrow Uses Direct Memory</a></li>
</ul>
</li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#bufferallocator">BufferAllocator</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#reference-counting">Reference counting</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#development-guidelines">Development Guidelines</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#debugging-memory-leaks-allocation">Debugging Memory Leaks/Allocation</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow-memory-in-depth">Arrow Memory In-Depth</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#design-principles">Design Principles</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#reserving-memory">Reserving Memory</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#reference-counting-details">Reference Counting Details</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#allocation-details">Allocation Details</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#object-hierarchy">Object Hierarchy</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#memory-perspective">Memory Perspective</a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#allocator-perspective">Allocator Perspective</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav></div>
<div class="sidebar-secondary-item">
<div class="tocsection editthispage">
<a href="https://github.com/apache/arrow/edit/main/docs/source/java/memory.rst">
<i class="fa-solid fa-pencil"></i>
Edit on GitHub
</a>
</div>
</div>
</div></div>
</div>
<footer class="bd-footer-content">
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script src="../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae"></script>
<script src="../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae"></script>
<footer class="bd-footer">
<div class="bd-footer__inner bd-page-width">
<div class="footer-items__start">
<div class="footer-item">
<p class="copyright">
© Copyright 2016-2024 Apache Software Foundation.
Apache Arrow, Arrow, Apache, the Apache feather logo, and the Apache Arrow project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.
<br/>
</p>
</div>
<div class="footer-item">
<p class="sphinx-version">
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 6.2.0.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.15.2.
</p></div>
</div>
</div>
</footer>
</body>
</html>