From 5559930eabc0bb064f7a1f79eb98ea0d99562b1e Mon Sep 17 00:00:00 2001
From: David Li
Date: Thu, 23 Jan 2025 23:45:20 -0500
Subject: [PATCH] GH-546: Migrate Sphinx documentation (#553)
Fixes #546.
---------
Co-authored-by: Sutou Kouhei
---
.github/workflows/rc.yml | 47 +-
.gitignore | 1 +
dev/release/rat_exclude_files.txt | 1 +
docs/Makefile | 20 +
docs/README.md | 28 +
docs/requirements.txt | 28 +
docs/source/_static/.gitignore | 0
docs/source/algorithm.rst | 92 +++
docs/source/cdata.rst | 468 +++++++++++++
docs/source/conf.py | 51 ++
docs/source/dataset.rst | 309 +++++++++
docs/source/developers/building.rst | 624 ++++++++++++++++++
docs/source/developers/development.rst | 197 ++++++
.../developers/img/conbench_benchmark.png | Bin 0 -> 141075 bytes
docs/source/developers/img/conbench_runs.png | Bin 0 -> 62681 bytes
docs/source/developers/img/conbench_ui.png | Bin 0 -> 70336 bytes
docs/source/developers/index.rst | 28 +
docs/source/flight.rst | 239 +++++++
docs/source/flight_sql.rst | 32 +
docs/source/flight_sql_jdbc_driver.rst | 175 +++++
docs/source/index.rst | 48 ++
docs/source/install.rst | 230 +++++++
docs/source/ipc.rst | 202 ++++++
docs/source/jdbc.rst | 278 ++++++++
docs/source/memory.rst | 499 ++++++++++++++
docs/source/overview.rst | 90 +++
docs/source/quickstartguide.rst | 314 +++++++++
docs/source/reference/index.rst | 21 +
docs/source/substrait.rst | 201 ++++++
docs/source/table.rst | 378 +++++++++++
docs/source/vector.rst | 366 ++++++++++
docs/source/vector_schema_root.rst | 163 +++++
32 files changed, 5126 insertions(+), 4 deletions(-)
create mode 100644 docs/Makefile
create mode 100644 docs/README.md
create mode 100644 docs/requirements.txt
create mode 100644 docs/source/_static/.gitignore
create mode 100644 docs/source/algorithm.rst
create mode 100644 docs/source/cdata.rst
create mode 100644 docs/source/conf.py
create mode 100644 docs/source/dataset.rst
create mode 100644 docs/source/developers/building.rst
create mode 100644 docs/source/developers/development.rst
create mode 100644 docs/source/developers/img/conbench_benchmark.png
create mode 100644 docs/source/developers/img/conbench_runs.png
create mode 100644 docs/source/developers/img/conbench_ui.png
create mode 100644 docs/source/developers/index.rst
create mode 100644 docs/source/flight.rst
create mode 100644 docs/source/flight_sql.rst
create mode 100644 docs/source/flight_sql_jdbc_driver.rst
create mode 100644 docs/source/index.rst
create mode 100644 docs/source/install.rst
create mode 100644 docs/source/ipc.rst
create mode 100644 docs/source/jdbc.rst
create mode 100644 docs/source/memory.rst
create mode 100644 docs/source/overview.rst
create mode 100644 docs/source/quickstartguide.rst
create mode 100644 docs/source/reference/index.rst
create mode 100644 docs/source/substrait.rst
create mode 100644 docs/source/table.rst
create mode 100644 docs/source/vector.rst
create mode 100644 docs/source/vector_schema_root.rst
diff --git a/.github/workflows/rc.yml b/.github/workflows/rc.yml
index 61281964..9dc04fee 100644
--- a/.github/workflows/rc.yml
+++ b/.github/workflows/rc.yml
@@ -421,8 +421,8 @@ jobs:
- name: Prepare docs
run: |
mkdir -p docs
- cp -a target/site/apidocs docs/reference
- tar -cvzf docs.tar.gz docs
+ cp -a target/site/apidocs reference
+ tar -cvzf reference.tar.gz reference
- name: Upload binaries
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
@@ -431,8 +431,46 @@ jobs:
- name: Upload docs
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
- name: release-docs
- path: docs.tar.gz
+ name: reference
+ path: reference.tar.gz
+ docs:
+ name: Docs
+ needs:
+ - binaries
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
+ with:
+ cache: 'pip'
+ - name: Download source archive
+ uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ with:
+ name: release-source
+ - name: Download Javadocs
+ uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ with:
+ name: reference
+ - name: Extract source archive
+ run: |
+ tar -xf apache-arrow-java-*.tar.gz --strip-components=1
+ - name: Build
+ run: |
+ cd docs
+ python -m venv venv
+ source venv/bin/activate
+ pip install -r requirements.txt
+ make html
+ tar -xf ../reference.tar.gz -C build/html
+ - name: Compress into single artifact to keep directory structure
+ run: tar -cvzf html.tar.gz -C docs/build html
+ - name: Upload artifacts
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
+ with:
+ name: release-html
+ path: html.tar.gz
verify:
name: Verify
needs:
@@ -473,6 +511,7 @@ jobs:
name: Upload
if: github.ref_type == 'tag'
needs:
+ - docs
- verify
runs-on: ubuntu-latest
permissions:
diff --git a/.gitignore b/.gitignore
index 205be77e..b57597af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
/dev/release/apache-rat-0.16.1.jar
/dev/release/filtered_rat.txt
/dev/release/rat.xml
+/docs/build/
CMakeCache.txt
CMakeFiles/
Makefile
diff --git a/dev/release/rat_exclude_files.txt b/dev/release/rat_exclude_files.txt
index 8efd379a..8324d32c 100644
--- a/dev/release/rat_exclude_files.txt
+++ b/dev/release/rat_exclude_files.txt
@@ -17,3 +17,4 @@
.gitmodules
dataset/src/test/resources/data/student.csv
+docs/Makefile
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 00000000..a4de0bff
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?= -W
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..70c2ef2a
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,28 @@
+
+
+# Documentation
+
+Build with Sphinx.
+
+```bash
+cd docs
+pip install -r requirements.txt
+make html
+```
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 00000000..fa2d0bbe
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+furo==2024.8.6
+myst-parser==4.0.0
+Sphinx==8.1.3
+sphinx-autobuild==2024.10.3
+sphinx-basic-ng==1.0.0b2
+sphinxcontrib-applehelp==2.0.0
+sphinxcontrib-devhelp==2.0.0
+sphinxcontrib-htmlhelp==2.1.0
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==2.0.0
+sphinxcontrib-serializinghtml==2.0.0
diff --git a/docs/source/_static/.gitignore b/docs/source/_static/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/source/algorithm.rst b/docs/source/algorithm.rst
new file mode 100644
index 00000000..d4838967
--- /dev/null
+++ b/docs/source/algorithm.rst
@@ -0,0 +1,92 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+Java Algorithms
+===============
+
+Arrow's Java library provides algorithms for some commonly-used
+functionalities. The algorithms are provided in the ``org.apache.arrow.algorithm``
+package of the ``algorithm`` module.
+
+Comparing Vector Elements
+-------------------------
+
+Comparing vector elements is the basic for many algorithms. Vector
+elements can be compared in one of the two ways:
+
+1. **Equality comparison**: there are two possible results for this type of comparisons: ``equal`` and ``unequal``.
+Currently, this type of comparison is supported through the ``org.apache.arrow.vector.compare.VectorValueEqualizer``
+interface.
+
+2. **Ordering comparison**: there are three possible results for this type of comparisons: ``less than``, ``equal to``
+and ``greater than``. This comparison is supported by the abstract class ``org.apache.arrow.algorithm.sort.VectorValueComparator``.
+
+We provide default implementations to compare vector elements. However, users can also define ways
+for customized comparisons.
+
+Vector Element Search
+---------------------
+
+A search algorithm tries to find a particular value in a vector. When successful, a vector index is
+returned; otherwise, a ``-1`` is returned. The following search algorithms are provided:
+
+1. **Linear search**: this algorithm simply traverses the vector from the beginning, until a match is
+found, or the end of the vector is reached. So it takes ``O(n)`` time, where ``n`` is the number of elements
+in the vector. This algorithm is implemented in ``org.apache.arrow.algorithm.search.VectorSearcher#linearSearch``.
+
+2. **Binary search**: this represents a more efficient search algorithm, as it runs in ``O(log(n))`` time.
+However, it is only applicable to sorted vectors. To get a sorted vector,
+one can use one of our sorting algorithms, which will be discussed in the next section. This algorithm
+is implemented in ``org.apache.arrow.algorithm.search.VectorSearcher#binarySearch``.
+
+3. **Parallel search**: when the vector is large, it takes a long time to traverse the elements to search
+for a value. To make this process faster, one can split the vector into multiple partitions, and perform the
+search for each partition in parallel. This is supported by ``org.apache.arrow.algorithm.search.ParallelSearcher``.
+
+4. **Range search**: for many scenarios, there can be multiple matching values in the vector.
+If the vector is sorted, the matching values reside in a contiguous region in the vector. The
+range search algorithm tries to find the upper/lower bound of the region in ``O(log(n))`` time.
+An implementation is provided in ``org.apache.arrow.algorithm.search.VectorRangeSearcher``.
+
+Vector Sorting
+--------------
+
+Given a vector, a sorting algorithm turns it into a sorted one. The sorting criteria must
+be specified by some ordering comparison operation. The sorting algorithms can be
+classified into the following categories:
+
+1. **In-place sorter**: an in-place sorter performs the sorting by manipulating the original
+vector, without creating any new vector. So it just returns the original vector after the sorting operations.
+Currently, we have ``org.apache.arrow.algorithm.sort.FixedWidthInPlaceVectorSorter`` for in-place
+sorting in ``O(nlog(n))`` time. As the name suggests, it only supports fixed width vectors.
+
+2. **Out-of-place sorter**: an out-of-place sorter does not mutate the original vector. Instead,
+it copies vector elements to a new vector in sorted order, and returns the new vector.
+We have ``org.apache.arrow.algorithm.sort.FixedWidthInPlaceVectorSorter.FixedWidthOutOfPlaceVectorSorter``
+and ``org.apache.arrow.algorithm.sort.FixedWidthInPlaceVectorSorter.VariableWidthOutOfPlaceVectorSorter``
+for fixed width and variable width vectors, respectively. Both algorithms run in ``O(nlog(n))`` time.
+
+3. **Index sorter**: this sorter does not actually sort the vector. Instead, it returns an integer
+vector, which correspond to indices of vector elements in sorted order. With the index vector, one can
+easily construct a sorted vector. In addition, some other tasks can be easily achieved, like finding the ``k`` th
+smallest value in the vector. Index sorting is supported by ``org.apache.arrow.algorithm.sort.IndexSorter``,
+which runs in ``O(nlog(n))`` time. It is applicable to vectors of any type.
+
+Other Algorithms
+----------------
+
+Other algorithms include vector deduplication, dictionary encoding, etc., in the ``algorithm`` module.
diff --git a/docs/source/cdata.rst b/docs/source/cdata.rst
new file mode 100644
index 00000000..9643d88d
--- /dev/null
+++ b/docs/source/cdata.rst
@@ -0,0 +1,468 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+================
+C Data Interface
+================
+
+Arrow supports exchanging data without copying or serialization within the same process
+through :external+arrow:ref:`c-data-interface`, even between different language runtimes.
+
+Java to Python
+--------------
+
+See :external+arrow:doc:`python/integration/python_java` to implement Java to
+Python communication using the C Data Interface.
+
+Java to C++
+-----------
+
+See :external+arrow:doc:`developers/cpp/building` to build the Arrow C++ libraries:
+
+.. code-block:: shell
+
+ $ git clone https://github.com/apache/arrow.git
+ $ cd arrow/cpp
+ $ mkdir build # from inside the `cpp` subdirectory
+ $ cd build
+ $ cmake .. --preset ninja-debug-minimal
+ $ cmake --build .
+ $ tree debug/
+ debug/
+ ├── libarrow.800.0.0.dylib
+ ├── libarrow.800.dylib -> libarrow.800.0.0.dylib
+ └── libarrow.dylib -> libarrow.800.dylib
+
+Share an Int64 array from C++ to Java
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**C++ Side**
+
+Implement a function in CDataCppBridge.h that exports an array via the C Data Interface:
+
+.. code-block:: cpp
+
+ #include
+ #include
+ #include
+
+ void FillInt64Array(const uintptr_t c_schema_ptr, const uintptr_t c_array_ptr) {
+ arrow::Int64Builder builder;
+ builder.Append(1);
+ builder.Append(2);
+ builder.Append(3);
+ builder.AppendNull();
+ builder.Append(5);
+ builder.Append(6);
+ builder.Append(7);
+ builder.Append(8);
+ builder.Append(9);
+ builder.Append(10);
+ std::shared_ptr array = *builder.Finish();
+
+ struct ArrowSchema* c_schema = reinterpret_cast(c_schema_ptr);
+ auto c_schema_status = arrow::ExportType(*array->type(), c_schema);
+ if (!c_schema_status.ok()) c_schema_status.Abort();
+
+ struct ArrowArray* c_array = reinterpret_cast(c_array_ptr);
+ auto c_array_status = arrow::ExportArray(*array, c_array);
+ if (!c_array_status.ok()) c_array_status.Abort();
+ }
+
+**Java Side**
+
+For this example, we will use `JavaCPP`_ to call our C++ function from Java,
+without writing JNI bindings ourselves.
+
+.. code-block:: xml
+
+
+
+ 4.0.0
+
+ org.example
+ java-cdata-example
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+ 9.0.0
+
+
+
+ org.bytedeco
+ javacpp
+ 1.5.7
+
+
+ org.apache.arrow
+ arrow-c-data
+ ${arrow.version}
+
+
+ org.apache.arrow
+ arrow-vector
+ ${arrow.version}
+
+
+ org.apache.arrow
+ arrow-memory-core
+ ${arrow.version}
+
+
+ org.apache.arrow
+ arrow-memory-netty
+ ${arrow.version}
+
+
+ org.apache.arrow
+ arrow-format
+ ${arrow.version}
+
+
+
+
+.. code-block:: java
+
+ import org.bytedeco.javacpp.annotation.Platform;
+ import org.bytedeco.javacpp.annotation.Properties;
+ import org.bytedeco.javacpp.tools.InfoMap;
+ import org.bytedeco.javacpp.tools.InfoMapper;
+
+ @Properties(
+ target = "CDataJavaToCppExample",
+ value = @Platform(
+ include = {
+ "CDataCppBridge.h"
+ },
+ compiler = {"cpp17"},
+ linkpath = {"/arrow/cpp/build/debug/"},
+ link = {"arrow"}
+ )
+ )
+ public class CDataJavaConfig implements InfoMapper {
+
+ @Override
+ public void map(InfoMap infoMap) {
+ }
+ }
+
+.. code-block:: shell
+
+ # Compile our Java code
+ $ javac -cp javacpp-1.5.7.jar CDataJavaConfig.java
+
+ # Generate CDataInterfaceLibrary
+ $ java -jar javacpp-1.5.7.jar CDataJavaConfig.java
+
+ # Generate libjniCDataInterfaceLibrary.dylib
+ $ java -jar javacpp-1.5.7.jar CDataJavaToCppExample.java
+
+ # Validate libjniCDataInterfaceLibrary.dylib created
+ $ otool -L macosx-x86_64/libjniCDataJavaToCppExample.dylib
+ macosx-x86_64/libjniCDataJavaToCppExample.dylib:
+ libjniCDataJavaToCppExample.dylib (compatibility version 0.0.0, current version 0.0.0)
+ @rpath/libarrow.800.dylib (compatibility version 800.0.0, current version 800.0.0)
+ /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1200.3.0)
+ /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0)
+
+**Java Test**
+
+Let's create a Java class to test our bridge:
+
+.. code-block:: java
+
+ import org.apache.arrow.c.ArrowArray;
+ import org.apache.arrow.c.ArrowSchema;
+ import org.apache.arrow.c.Data;
+ import org.apache.arrow.memory.BufferAllocator;
+ import org.apache.arrow.memory.RootAllocator;
+ import org.apache.arrow.vector.BigIntVector;
+
+ public class TestCDataInterface {
+ public static void main(String[] args) {
+ try(
+ BufferAllocator allocator = new RootAllocator();
+ ArrowSchema arrowSchema = ArrowSchema.allocateNew(allocator);
+ ArrowArray arrowArray = ArrowArray.allocateNew(allocator)
+ ){
+ CDataJavaToCppExample.FillInt64Array(
+ arrowSchema.memoryAddress(), arrowArray.memoryAddress());
+ try(
+ BigIntVector bigIntVector = (BigIntVector) Data.importVector(
+ allocator, arrowArray, arrowSchema, null)
+ ){
+ System.out.println("C++-allocated array: " + bigIntVector);
+ }
+ }
+ }
+ }
+
+.. code-block:: shell
+
+ C++-allocated array: [1, 2, 3, null, 5, 6, 7, 8, 9, 10]
+
+Share an Int32 array from Java to C++
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Java Side**
+
+For this example, we will build a JAR with all dependencies bundled.
+
+.. code-block:: xml
+
+
+
+ 4.0.0
+ org.example
+ cpptojava
+ 1.0-SNAPSHOT
+
+ 8
+ 8
+ 9.0.0
+
+
+
+ org.apache.arrow
+ arrow-c-data
+ ${arrow.version}
+
+
+ org.apache.arrow
+ arrow-memory-netty
+ ${arrow.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+.. code-block:: java
+
+ import org.apache.arrow.c.ArrowArray;
+ import org.apache.arrow.c.ArrowSchema;
+ import org.apache.arrow.c.Data;
+ import org.apache.arrow.memory.BufferAllocator;
+ import org.apache.arrow.memory.RootAllocator;
+ import org.apache.arrow.vector.FieldVector;
+ import org.apache.arrow.vector.IntVector;
+ import org.apache.arrow.vector.VectorSchemaRoot;
+
+ import java.util.Arrays;
+
+ public class ToBeCalledByCpp {
+ final static BufferAllocator allocator = new RootAllocator();
+
+ /**
+ * Create a {@link FieldVector} and export it via the C Data Interface
+ * @param schemaAddress Schema memory address to wrap
+ * @param arrayAddress Array memory address to wrap
+ */
+ public static void fillVector(long schemaAddress, long arrayAddress){
+ try (ArrowArray arrow_array = ArrowArray.wrap(arrayAddress);
+ ArrowSchema arrow_schema = ArrowSchema.wrap(schemaAddress) ) {
+ Data.exportVector(allocator, populateFieldVectorToExport(), null, arrow_array, arrow_schema);
+ }
+ }
+
+ /**
+ * Create a {@link VectorSchemaRoot} and export it via the C Data Interface
+ * @param schemaAddress Schema memory address to wrap
+ * @param arrayAddress Array memory address to wrap
+ */
+ public static void fillVectorSchemaRoot(long schemaAddress, long arrayAddress){
+ try (ArrowArray arrow_array = ArrowArray.wrap(arrayAddress);
+ ArrowSchema arrow_schema = ArrowSchema.wrap(schemaAddress) ) {
+ Data.exportVectorSchemaRoot(allocator, populateVectorSchemaRootToExport(), null, arrow_array, arrow_schema);
+ }
+ }
+
+ private static FieldVector populateFieldVectorToExport(){
+ IntVector intVector = new IntVector("int-to-export", allocator);
+ intVector.allocateNew(3);
+ intVector.setSafe(0, 1);
+ intVector.setSafe(1, 2);
+ intVector.setSafe(2, 3);
+ intVector.setValueCount(3);
+ System.out.println("[Java] FieldVector: \n" + intVector);
+ return intVector;
+ }
+
+ private static VectorSchemaRoot populateVectorSchemaRootToExport(){
+ IntVector intVector = new IntVector("age-to-export", allocator);
+ intVector.setSafe(0, 10);
+ intVector.setSafe(1, 20);
+ intVector.setSafe(2, 30);
+ VectorSchemaRoot root = new VectorSchemaRoot(Arrays.asList(intVector));
+ root.setRowCount(3);
+ System.out.println("[Java] VectorSchemaRoot: \n" + root.contentToTSVString());
+ return root;
+ }
+ }
+
+Build the JAR and copy it to the C++ project.
+
+.. code-block:: shell
+
+ $ mvn clean install
+ $ cp target/cpptojava-1.0-SNAPSHOT-jar-with-dependencies.jar /cpptojava.jar
+
+**C++ Side**
+
+This application uses JNI to call Java code, but transfers data (zero-copy) via the C Data Interface instead.
+
+.. code-block:: cpp
+
+ #include
+ #include
+
+ #include
+ #include
+
+ JNIEnv *CreateVM(JavaVM **jvm) {
+ JNIEnv *env;
+ JavaVMInitArgs vm_args;
+ JavaVMOption options[2];
+ options[0].optionString = "-Djava.class.path=cpptojava.jar";
+ options[1].optionString = "-DXcheck:jni:pedantic";
+ vm_args.version = JNI_VERSION_10;
+ vm_args.nOptions = 2;
+ vm_args.options = options;
+ int status = JNI_CreateJavaVM(jvm, (void **) &env, &vm_args);
+ if (status < 0) {
+ std::cerr << "\n<<<<< Unable to Launch JVM >>>>>\n" << std::endl;
+ return nullptr;
+ }
+ return env;
+ }
+
+ int main() {
+ JNIEnv *env;
+ JavaVM *jvm;
+ env = CreateVM(&jvm);
+ if (env == nullptr) return EXIT_FAILURE;
+ jclass javaClassToBeCalledByCpp = env->FindClass("ToBeCalledByCpp");
+ if (javaClassToBeCalledByCpp != nullptr) {
+ jmethodID fillVector = env->GetStaticMethodID(javaClassToBeCalledByCpp,
+ "fillVector",
+ "(JJ)V");
+ if (fillVector != nullptr) {
+ struct ArrowSchema arrowSchema;
+ struct ArrowArray arrowArray;
+ std::cout << "\n<<<<< C++ to Java for Arrays >>>>>\n" << std::endl;
+ env->CallStaticVoidMethod(javaClassToBeCalledByCpp, fillVector,
+ static_cast(reinterpret_cast(&arrowSchema)),
+ static_cast(reinterpret_cast(&arrowArray)));
+ auto resultImportArray = arrow::ImportArray(&arrowArray, &arrowSchema);
+ std::shared_ptr array = resultImportArray.ValueOrDie();
+ std::cout << "[C++] Array: " << array->ToString() << std::endl;
+ } else {
+ std::cerr << "Could not find fillVector method\n" << std::endl;
+ return EXIT_FAILURE;
+ }
+ jmethodID fillVectorSchemaRoot = env->GetStaticMethodID(javaClassToBeCalledByCpp,
+ "fillVectorSchemaRoot",
+ "(JJ)V");
+ if (fillVectorSchemaRoot != nullptr) {
+ struct ArrowSchema arrowSchema;
+ struct ArrowArray arrowArray;
+ std::cout << "\n<<<<< C++ to Java for RecordBatch >>>>>\n" << std::endl;
+ env->CallStaticVoidMethod(javaClassToBeCalledByCpp, fillVectorSchemaRoot,
+ static_cast(reinterpret_cast(&arrowSchema)),
+ static_cast(reinterpret_cast(&arrowArray)));
+ auto resultImportVectorSchemaRoot = arrow::ImportRecordBatch(&arrowArray, &arrowSchema);
+ std::shared_ptr recordBatch = resultImportVectorSchemaRoot.ValueOrDie();
+ std::cout << "[C++] RecordBatch: " << recordBatch->ToString() << std::endl;
+ } else {
+ std::cerr << "Could not find fillVectorSchemaRoot method\n" << std::endl;
+ return EXIT_FAILURE;
+ }
+ } else {
+ std::cout << "Could not find ToBeCalledByCpp class\n" << std::endl;
+ return EXIT_FAILURE;
+ }
+ jvm->DestroyJavaVM();
+ return EXIT_SUCCESS;
+ }
+
+CMakeLists.txt definition file:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.19)
+ project(cdatacpptojava)
+ find_package(JNI REQUIRED)
+ find_package(Arrow REQUIRED)
+ message(STATUS "Arrow version: ${ARROW_VERSION}")
+ include_directories(${JNI_INCLUDE_DIRS})
+ set(CMAKE_CXX_STANDARD 17)
+ add_executable(${PROJECT_NAME} main.cpp)
+ target_link_libraries(cdatacpptojava PRIVATE Arrow::arrow_shared)
+ target_link_libraries(cdatacpptojava PRIVATE ${JNI_LIBRARIES})
+
+**Result**
+
+.. code-block:: text
+
+ <<<<< C++ to Java for Arrays >>>>>
+ [Java] FieldVector:
+ [1, 2, 3]
+ [C++] Array: [
+ 1,
+ 2,
+ 3
+ ]
+
+ <<<<< C++ to Java for RecordBatch >>>>>
+ [Java] VectorSchemaRoot:
+ age-to-export
+ 10
+ 20
+ 30
+
+ [C++] RecordBatch: age-to-export: [
+ 10,
+ 20,
+ 30
+ ]
+
+.. _`JavaCPP`: https://github.com/bytedeco/javacpp
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 00000000..166a3bc4
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'arrow-java'
+copyright = '2025, Apache Arrow Developers'
+author = 'Apache Arrow Developers'
+release = '18.1.0'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = ["sphinx.ext.intersphinx"]
+
+templates_path = ['_templates']
+exclude_patterns = []
+
+# -- Intersphinx -------------------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
+
+intersphinx_mapping = {
+ 'arrow': ('https://arrow.apache.org/docs/', None),
+ 'cookbook': ('https://arrow.apache.org/cookbook/java/', None),
+}
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'furo'
+html_static_path = ['_static']
diff --git a/docs/source/dataset.rst b/docs/source/dataset.rst
new file mode 100644
index 00000000..deaa0095
--- /dev/null
+++ b/docs/source/dataset.rst
@@ -0,0 +1,309 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+=======
+Dataset
+=======
+
+.. warning::
+
+ Experimental: The Java module ``dataset`` is currently under early
+ development. API might be changed in each release of Apache Arrow until it
+ gets mature.
+
+Dataset is an universal layer in Apache Arrow for querying data in different
+formats or in different partitioning strategies. Usually the data to be queried
+is supposed to be located from a traditional file system, however Arrow Dataset
+is not designed only for querying files but can be extended to serve all
+possible data sources such as from inter-process communication or from other
+network locations, etc.
+
+Getting Started
+===============
+
+Currently supported file formats are:
+
+- Apache Arrow (``.arrow``)
+- Apache ORC (``.orc``)
+- Apache Parquet (``.parquet``)
+- Comma-Separated Values (``.csv``)
+- Line-delimited JSON Values (``.json``)
+
+Below shows a simplest example of using Dataset to query a Parquet file in Java:
+
+.. code-block:: Java
+
+ // read data from file /opt/example.parquet
+ String uri = "file:/opt/example.parquet";
+ ScanOptions options = new ScanOptions(/*batchSize*/ 32768);
+ try (
+ BufferAllocator allocator = new RootAllocator();
+ DatasetFactory datasetFactory = new FileSystemDatasetFactory(
+ allocator, NativeMemoryPool.getDefault(),
+ FileFormat.PARQUET, uri);
+ Dataset dataset = datasetFactory.finish();
+ Scanner scanner = dataset.newScan(options);
+ ArrowReader reader = scanner.scanBatches()
+ ) {
+ List batches = new ArrayList<>();
+ while (reader.loadNextBatch()) {
+ try (VectorSchemaRoot root = reader.getVectorSchemaRoot()) {
+ final VectorUnloader unloader = new VectorUnloader(root);
+ batches.add(unloader.getRecordBatch());
+ }
+ }
+
+ // do something with read record batches, for example:
+ analyzeArrowData(batches);
+
+ // finished the analysis of the data, close all resources:
+ AutoCloseables.close(batches);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+.. note::
+ ``ArrowRecordBatch`` is a low-level composite Arrow data exchange format
+ that doesn't provide API to read typed data from it directly.
+ It's recommended to use utilities ``VectorLoader`` to load it into a schema
+ aware container ``VectorSchemaRoot`` by which user could be able to access
+ decoded data conveniently in Java.
+
+ The ``ScanOptions batchSize`` argument takes effect only if it is set to a value
+ smaller than the number of rows in the recordbatch.
+
+.. seealso::
+ Load record batches with :doc:`VectorSchemaRoot `.
+
+Schema
+======
+
+Schema of the data to be queried can be inspected via method
+``DatasetFactory#inspect()`` before actually reading it. For example:
+
+.. code-block:: Java
+
+ // read data from local file /opt/example.parquet
+ String uri = "file:/opt/example.parquet";
+ BufferAllocator allocator = new RootAllocator(Long.MAX_VALUE);
+ DatasetFactory factory = new FileSystemDatasetFactory(allocator,
+ NativeMemoryPool.getDefault(), FileFormat.PARQUET, uri);
+
+ // inspect schema
+ Schema schema = factory.inspect();
+
+For some of the data format that is compatible with a user-defined schema, user
+can use method ``DatasetFactory#inspect(Schema schema)`` to create the dataset:
+
+.. code-block:: Java
+
+ Schema schema = createUserSchema()
+ Dataset dataset = factory.finish(schema);
+
+Otherwise when the non-parameter method ``DatasetFactory#inspect()`` is called,
+schema will be inferred automatically from data source. The same as the result
+of ``DatasetFactory#inspect()``.
+
+Also, if projector is specified during scanning (see next section
+:ref:`java-dataset-projection`), the actual schema of output data can be got
+within method ``Scanner::schema()``:
+
+.. code-block:: Java
+
+ Scanner scanner = dataset.newScan(
+ new ScanOptions(32768, Optional.of(new String[] {"id", "name"})));
+ Schema projectedSchema = scanner.schema();
+
+.. _java-dataset-projection:
+
+Projection (Subset of Columns)
+==============================
+
+User can specify projections in ScanOptions. For example:
+
+.. code-block:: Java
+
+ String[] projection = new String[] {"id", "name"};
+ ScanOptions options = new ScanOptions(32768, Optional.of(projection));
+
+If no projection is needed, leave the optional projection argument absent in
+ScanOptions:
+
+.. code-block:: Java
+
+ ScanOptions options = new ScanOptions(32768, Optional.empty());
+
+Or use shortcut constructor:
+
+.. code-block:: Java
+
+ ScanOptions options = new ScanOptions(32768);
+
+Then all columns will be emitted during scanning.
+
+Projection (Produce New Columns) and Filters
+============================================
+
+User can specify projections (new columns) or filters in ScanOptions using Substrait. For example:
+
+.. code-block:: Java
+
+ ByteBuffer substraitExpressionFilter = getSubstraitExpressionFilter();
+ ByteBuffer substraitExpressionProject = getSubstraitExpressionProjection();
+ // Use Substrait APIs to create an Expression and serialize to a ByteBuffer
+ ScanOptions options = new ScanOptions.Builder(/*batchSize*/ 32768)
+ .columns(Optional.empty())
+ .substraitExpressionFilter(substraitExpressionFilter)
+ .substraitExpressionProjection(getSubstraitExpressionProjection())
+ .build();
+
+.. seealso::
+
+ :doc:`Executing Projections and Filters Using Extended Expressions `
+ Projections and Filters using Substrait.
+
+Read Data from HDFS
+===================
+
+``FileSystemDataset`` supports reading data from non-local file systems. HDFS
+support is included in the official Apache Arrow Java package releases and
+can be used directly without re-building the source code.
+
+To access HDFS data using Dataset API, pass a general HDFS URI to
+``FilesSystemDatasetFactory``:
+
+.. code-block:: Java
+
+ String uri = "hdfs://{hdfs_host}:{port}/data/example.parquet";
+ BufferAllocator allocator = new RootAllocator(Long.MAX_VALUE);
+ DatasetFactory factory = new FileSystemDatasetFactory(allocator,
+ NativeMemoryPool.getDefault(), FileFormat.PARQUET, uri);
+
+Native Memory Management
+========================
+
+To gain better performance and reduce code complexity, Java
+``FileSystemDataset`` internally relies on C++
+``arrow::dataset::FileSystemDataset`` via JNI.
+As a result, all Arrow data read from ``FileSystemDataset`` is supposed to be
+allocated off the JVM heap. To manage this part of memory, an utility class
+``NativeMemoryPool`` is provided to users.
+
+As a basic example, by using a listenable ``NativeMemoryPool``, user can pass
+a listener hooking on C++ buffer allocation/deallocation:
+
+.. code-block:: Java
+
+ AtomicLong reserved = new AtomicLong(0L);
+ ReservationListener listener = new ReservationListener() {
+ @Override
+ public void reserve(long size) {
+ reserved.getAndAdd(size);
+ }
+
+ @Override
+ public void unreserve(long size) {
+ reserved.getAndAdd(-size);
+ }
+ };
+ NativeMemoryPool pool = NativeMemoryPool.createListenable(listener);
+ FileSystemDatasetFactory factory = new FileSystemDatasetFactory(allocator,
+ pool, FileFormat.PARQUET, uri);
+
+
+Also, it's a very common case to reserve the same amount of JVM direct memory
+for the data read from datasets. For this use a built-in utility
+class ``DirectReservationListener`` is provided:
+
+.. code-block:: Java
+
+ NativeMemoryPool pool = NativeMemoryPool.createListenable(
+ DirectReservationListener.instance());
+
+This way, once the allocated byte count of Arrow buffers reaches the limit of
+JVM direct memory, ``OutOfMemoryError: Direct buffer memory`` will
+be thrown during scanning.
+
+.. note::
+ The default instance ``NativeMemoryPool.getDefaultMemoryPool()`` does
+ nothing on buffer allocation/deallocation. It's OK to use it in
+ the case of POC or testing, but for production use in complex environment,
+ it's recommended to manage memory by using a listenable memory pool.
+
+.. note::
+ The ``BufferAllocator`` instance passed to ``FileSystemDatasetFactory``'s
+ constructor is also aware of the overall memory usage of the produced
+ dataset instances. Once the Java buffers are created the passed allocator
+ will become their parent allocator.
+
+Usage Notes
+===========
+
+Native Object Resource Management
+---------------------------------
+
+As another result of relying on JNI, all components related to
+``FileSystemDataset`` should be closed manually or use try-with-resources to
+release the corresponding native objects after using. For example:
+
+.. code-block:: Java
+
+ String uri = "file:/opt/example.parquet";
+ ScanOptions options = new ScanOptions(/*batchSize*/ 32768);
+ try (
+ BufferAllocator allocator = new RootAllocator();
+ DatasetFactory factory = new FileSystemDatasetFactory(
+ allocator, NativeMemoryPool.getDefault(),
+ FileFormat.PARQUET, uri);
+ Dataset dataset = factory.finish();
+ Scanner scanner = dataset.newScan(options)
+ ) {
+
+ // do something
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+If user forgets to close them then native object leakage might be caused.
+
+BatchSize
+---------
+
+The ``batchSize`` argument of ``ScanOptions`` is a limit on the size of an individual batch.
+
+For example, let's try to read a Parquet file with gzip compression and 3 row groups:
+
+.. code-block::
+
+ # Let configure ScanOptions as:
+ ScanOptions options = new ScanOptions(/*batchSize*/ 32768);
+
+ $ parquet-tools meta data4_3rg_gzip.parquet
+ file schema: schema
+ age: OPTIONAL INT64 R:0 D:1
+ name: OPTIONAL BINARY L:STRING R:0 D:1
+ row group 1: RC:4 TS:182 OFFSET:4
+ row group 2: RC:4 TS:190 OFFSET:420
+ row group 3: RC:3 TS:179 OFFSET:838
+
+Here, we set the batchSize in ScanOptions to 32768. Because that's greater
+than the number of rows in the next batch, which is 4 rows because the first
+row group has only 4 rows, then the program gets only 4 rows. The scanner
+will not combine smaller batches to reach the limit, but it will split
+large batches to stay under the limit. So in the case the row group had more
+than 32768 rows, it would get split into blocks of 32768 rows or less.
diff --git a/docs/source/developers/building.rst b/docs/source/developers/building.rst
new file mode 100644
index 00000000..f9ef7dae
--- /dev/null
+++ b/docs/source/developers/building.rst
@@ -0,0 +1,624 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+.. highlight:: console
+
+.. _building-arrow-java:
+
+===================
+Building Arrow Java
+===================
+
+.. contents::
+
+System Setup
+============
+
+Arrow Java uses the `Maven `_ build system.
+
+Building requires:
+
+* JDK 11+
+* Maven 3+
+
+.. note::
+ CI will test all supported JDK LTS versions, plus the latest non-LTS version.
+
+Building
+========
+
+All the instructions below assume that you have cloned the Arrow git
+repository:
+
+.. code-block::
+
+ $ git clone https://github.com/apache/arrow.git
+ $ cd arrow
+ $ git submodule update --init --recursive
+
+These are the options available to compile Arrow Java modules with:
+
+* Maven build tool.
+* Docker Compose.
+* Archery.
+
+Building Java Modules
+---------------------
+
+To build the default modules, go to the project root and execute:
+
+Maven
+~~~~~
+
+.. code-block::
+
+ $ cd arrow/java
+ $ export JAVA_HOME=
+ $ java --version
+ $ mvn clean install
+
+Docker compose
+~~~~~~~~~~~~~~
+
+.. code-block::
+
+ $ cd arrow/java
+ $ export JAVA_HOME=
+ $ java --version
+ $ docker compose run java
+
+Archery
+~~~~~~~
+
+.. code-block::
+
+ $ cd arrow/java
+ $ export JAVA_HOME=
+ $ java --version
+ $ archery docker run java
+
+Building JNI Libraries (\*.dylib / \*.so / \*.dll)
+--------------------------------------------------
+
+First, we need to build the `C++ shared libraries`_ that the JNI bindings will use.
+We can build these manually or we can use `Archery`_ to build them using a Docker container
+(This will require installing Docker, Docker Compose, and Archery).
+
+.. note::
+ If you are building on Apple Silicon, be sure to use a JDK version that was compiled
+ for that architecture. See, for example, the `Azul JDK `_.
+
+ If you are building on Windows OS, see :ref:`Developing on Windows `.
+
+Maven
+~~~~~
+
+- To build only the JNI C Data Interface library (macOS / Linux):
+
+ .. code-block:: text
+
+ $ cd arrow/java
+ $ export JAVA_HOME=
+ $ java --version
+ $ mvn generate-resources -Pgenerate-libs-cdata-all-os -N
+ $ ls -latr ../java-dist/lib
+ |__ arrow_cdata_jni/
+
+- To build only the JNI C Data Interface library (Windows):
+
+ .. code-block::
+
+ $ cd arrow/java
+ $ mvn generate-resources -Pgenerate-libs-cdata-all-os -N
+ $ dir "../java-dist/bin"
+ |__ arrow_cdata_jni/
+
+- To build all JNI libraries (macOS / Linux) except the JNI C Data Interface library:
+
+ .. code-block:: text
+
+ $ cd arrow/java
+ $ export JAVA_HOME=
+ $ java --version
+ $ mvn generate-resources -Pgenerate-libs-jni-macos-linux -N
+ $ ls -latr java-dist/lib
+ |__ arrow_dataset_jni/
+ |__ arrow_orc_jni/
+ |__ gandiva_jni/
+
+- To build all JNI libraries (Windows) except the JNI C Data Interface library:
+
+ .. code-block::
+
+ $ cd arrow/java
+ $ mvn generate-resources -Pgenerate-libs-jni-windows -N
+ $ dir "../java-dist/bin"
+ |__ arrow_dataset_jni/
+
+CMake
+~~~~~
+
+- To build only the JNI C Data Interface library (macOS / Linux):
+
+ .. code-block:: text
+
+ $ cd arrow
+ $ mkdir -p java-dist java-cdata
+ $ cmake \
+ -S java \
+ -B java-cdata \
+ -DARROW_JAVA_JNI_ENABLE_C=ON \
+ -DARROW_JAVA_JNI_ENABLE_DEFAULT=OFF \
+ -DBUILD_TESTING=OFF \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=java-dist
+ $ cmake --build java-cdata --target install --config Release
+ $ ls -latr java-dist/lib
+ |__ arrow_cdata_jni/
+
+- To build only the JNI C Data Interface library (Windows):
+
+ .. code-block:: text
+
+ $ cd arrow
+ $ mkdir java-dist, java-cdata
+ $ cmake ^
+ -S java ^
+ -B java-cdata ^
+ -DARROW_JAVA_JNI_ENABLE_C=ON ^
+ -DARROW_JAVA_JNI_ENABLE_DEFAULT=OFF ^
+ -DBUILD_TESTING=OFF ^
+ -DCMAKE_BUILD_TYPE=Release ^
+ -DCMAKE_INSTALL_PREFIX=java-dist
+ $ cmake --build java-cdata --target install --config Release
+ $ dir "java-dist/bin"
+ |__ arrow_cdata_jni/
+
+- To build all JNI libraries (macOS / Linux) except the JNI C Data Interface library:
+
+ .. code-block:: text
+
+ $ cd arrow
+ $ brew bundle --file=cpp/Brewfile
+ # Homebrew Bundle complete! 25 Brewfile dependencies now installed.
+ $ brew uninstall aws-sdk-cpp
+ # (We can't use aws-sdk-cpp installed by Homebrew because it has
+ # an issue: https://github.com/aws/aws-sdk-cpp/issues/1809 )
+ $ export JAVA_HOME=
+ $ mkdir -p java-dist cpp-jni
+ $ cmake \
+ -S cpp \
+ -B cpp-jni \
+ -DARROW_BUILD_SHARED=OFF \
+ -DARROW_CSV=ON \
+ -DARROW_DATASET=ON \
+ -DARROW_DEPENDENCY_SOURCE=BUNDLED \
+ -DARROW_DEPENDENCY_USE_SHARED=OFF \
+ -DARROW_FILESYSTEM=ON \
+ -DARROW_GANDIVA=ON \
+ -DARROW_GANDIVA_STATIC_LIBSTDCPP=ON \
+ -DARROW_JSON=ON \
+ -DARROW_ORC=ON \
+ -DARROW_PARQUET=ON \
+ -DARROW_S3=ON \
+ -DARROW_SUBSTRAIT=ON \
+ -DARROW_USE_CCACHE=ON \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=java-dist \
+ -DCMAKE_UNITY_BUILD=ON
+ $ cmake --build cpp-jni --target install --config Release
+ $ cmake \
+ -S java \
+ -B java-jni \
+ -DARROW_JAVA_JNI_ENABLE_C=OFF \
+ -DARROW_JAVA_JNI_ENABLE_DEFAULT=ON \
+ -DBUILD_TESTING=OFF \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=java-dist \
+ -DCMAKE_PREFIX_PATH=$PWD/java-dist \
+ -DProtobuf_ROOT=$PWD/../cpp-jni/protobuf_ep-install \
+ -DProtobuf_USE_STATIC_LIBS=ON
+ $ cmake --build java-jni --target install --config Release
+ $ ls -latr java-dist/lib/
+ |__ arrow_dataset_jni/
+ |__ arrow_orc_jni/
+ |__ gandiva_jni/
+
+- To build all JNI libraries (Windows) except the JNI C Data Interface library:
+
+ .. code-block::
+
+ $ cd arrow
+ $ mkdir java-dist, cpp-jni
+ $ cmake ^
+ -S cpp ^
+ -B cpp-jni ^
+ -DARROW_BUILD_SHARED=OFF ^
+ -DARROW_CSV=ON ^
+ -DARROW_DATASET=ON ^
+ -DARROW_DEPENDENCY_USE_SHARED=OFF ^
+ -DARROW_FILESYSTEM=ON ^
+ -DARROW_GANDIVA=OFF ^
+ -DARROW_JSON=ON ^
+ -DARROW_ORC=ON ^
+ -DARROW_PARQUET=ON ^
+ -DARROW_S3=ON ^
+ -DARROW_SUBSTRAIT=ON ^
+ -DARROW_USE_CCACHE=ON ^
+ -DARROW_WITH_BROTLI=ON ^
+ -DARROW_WITH_LZ4=ON ^
+ -DARROW_WITH_SNAPPY=ON ^
+ -DARROW_WITH_ZLIB=ON ^
+ -DARROW_WITH_ZSTD=ON ^
+ -DCMAKE_BUILD_TYPE=Release ^
+ -DCMAKE_INSTALL_PREFIX=java-dist ^
+ -DCMAKE_UNITY_BUILD=ON ^
+ -GNinja
+ $ cd cpp-jni
+ $ ninja install
+ $ cd ../
+ $ cmake ^
+ -S java ^
+ -B java-jni ^
+ -DARROW_JAVA_JNI_ENABLE_C=OFF ^
+ -DARROW_JAVA_JNI_ENABLE_DATASET=ON ^
+ -DARROW_JAVA_JNI_ENABLE_DEFAULT=ON ^
+ -DARROW_JAVA_JNI_ENABLE_GANDIVA=OFF ^
+ -DARROW_JAVA_JNI_ENABLE_ORC=ON ^
+ -DBUILD_TESTING=OFF ^
+ -DCMAKE_BUILD_TYPE=Release ^
+ -DCMAKE_INSTALL_PREFIX=java-dist ^
+ -DCMAKE_PREFIX_PATH=$PWD/java-dist
+ $ cmake --build java-jni --target install --config Release
+ $ dir "java-dist/bin"
+ |__ arrow_orc_jni/
+ |__ arrow_dataset_jni/
+
+Archery
+~~~~~~~
+
+.. code-block:: text
+
+ $ cd arrow
+ $ archery docker run java-jni-manylinux-2014
+ $ ls -latr java-dist
+ |__ arrow_cdata_jni/
+ |__ arrow_dataset_jni/
+ |__ arrow_orc_jni/
+ |__ gandiva_jni/
+
+Building Java JNI Modules
+-------------------------
+
+- To compile the JNI bindings, use the ``arrow-c-data`` Maven profile:
+
+ .. code-block::
+
+ $ cd arrow/java
+ $ mvn -Darrow.c.jni.dist.dir=/java-dist/lib -Parrow-c-data clean install
+
+- To compile the JNI bindings for ORC / Gandiva / Dataset, use the ``arrow-jni`` Maven profile:
+
+ .. code-block::
+
+ $ cd arrow/java
+ $ mvn \
+ -Darrow.cpp.build.dir=/java-dist/lib/ \
+ -Darrow.c.jni.dist.dir=/java-dist/lib/ \
+ -Parrow-jni clean install
+
+Testing
+=======
+
+By default, Maven uses the same Java version to both build the code and run the tests.
+
+It is also possible to use a different JDK version for the tests. This requires Maven
+toolchains to be configured beforehand, and then a specific test property needs to be set.
+
+Configuring Maven toolchains
+----------------------------
+
+To be able to use a JDK version for testing, it needs to be registered first in Maven ``toolchains.xml``
+configuration file usually located under ``${HOME}/.m2`` with the following snippet added to it:
+
+ .. code-block::
+
+
+
+
+ [...]
+
+
+ jdk
+
+ 21
+ temurin
+
+
+ path/to/jdk/home
+
+
+
+ [...]
+
+
+
+Testing with a specific JDK
+---------------------------
+
+To run Arrow tests with a specific JDK version, use the ``arrow.test.jdk-version`` property.
+
+For example, to run Arrow tests with JDK 17, use the following snippet:
+
+ .. code-block::
+
+ $ cd arrow/java
+ $ mvn -Darrow.test.jdk-version=17 clean verify
+
+IDE Configuration
+=================
+
+IntelliJ
+--------
+
+To start working on Arrow in IntelliJ: build the project once from the command
+line using ``mvn clean install``. Then open the ``java/`` subdirectory of the
+Arrow repository, and update the following settings:
+
+* In the Files tool window, find the path ``vector/target/generated-sources``,
+ right click the directory, and select Mark Directory as > Generated Sources
+ Root. There is no need to mark other generated sources directories, as only
+ the ``vector`` module generates sources.
+* For JDK 11, due to an `IntelliJ bug
+ `__, you must go into
+ Settings > Build, Execution, Deployment > Compiler > Java Compiler and disable
+ "Use '--release' option for cross-compilation (Java 9 and later)". Otherwise
+ you will get an error like "package sun.misc does not exist".
+* You may want to disable error-prone entirely if it gives spurious
+ warnings (disable both error-prone profiles in the Maven tool window
+ and "Reload All Maven Projects").
+* If using IntelliJ's Maven integration to build, you may need to change
+ ```` to ``false`` in the pom.xml files due to an `IntelliJ bug
+ `__.
+* To enable debugging JNI-based modules like ``dataset``,
+ activate specific profiles in the Maven tab under "Profiles".
+ Ensure the profiles ``arrow-c-data``, ``arrow-jni``, ``generate-libs-cdata-all-os``,
+ ``generate-libs-jni-macos-linux``, and ``jdk11+`` are enabled, so that the
+ IDE can build them and enable debugging.
+
+You may not need to update all of these settings if you build/test with the
+IntelliJ Maven integration instead of with IntelliJ directly.
+
+Common Errors
+=============
+
+* When working with the JNI code: if the C++ build cannot find dependencies, with errors like these:
+
+ .. code-block::
+
+ Could NOT find Boost (missing: Boost_INCLUDE_DIR system filesystem)
+ Could NOT find Lz4 (missing: LZ4_LIB)
+ Could NOT find zstd (missing: ZSTD_LIB)
+
+ Specify that the dependencies should be downloaded at build time (more details at `Dependency Resolution`_):
+
+ .. code-block::
+
+ -Dre2_SOURCE=BUNDLED \
+ -DBoost_SOURCE=BUNDLED \
+ -Dutf8proc_SOURCE=BUNDLED \
+ -DSnappy_SOURCE=BUNDLED \
+ -DORC_SOURCE=BUNDLED \
+ -DZLIB_SOURCE=BUNDLED
+
+.. _Archery: https://github.com/apache/arrow/blob/main/dev/archery/README.md
+.. _Dependency Resolution: https://arrow.apache.org/docs/developers/cpp/building.html#individual-dependency-resolution
+.. _C++ shared libraries: https://arrow.apache.org/docs/cpp/build_system.html
+
+
+Installing Nightly Packages
+===========================
+
+.. warning::
+ These packages are not official releases. Use them at your own risk.
+
+Arrow nightly builds are posted on the mailing list at `builds@arrow.apache.org`_.
+The artifacts are uploaded to GitHub. For example, for 2022/07/30, they can be found at `GitHub Nightly`_.
+
+
+Installing from Apache Nightlies
+--------------------------------
+1. Look up the nightly version number for the Arrow libraries used.
+
+ For example, for ``arrow-memory``, visit https://nightlies.apache.org/arrow/java/org/apache/arrow/arrow-memory/ and see what versions are available (e.g. 9.0.0.dev501).
+2. Add Apache Nightlies Repository to the Maven/Gradle project.
+
+ .. code-block:: xml
+
+
+ 9.0.0.dev501
+
+ ...
+
+
+ arrow-apache-nightlies
+ https://nightlies.apache.org/arrow/java
+
+
+ ...
+
+
+ org.apache.arrow
+ arrow-vector
+ ${arrow.version}
+
+
+ ...
+
+Installing Manually
+-------------------
+
+1. Decide nightly packages repository to use, for example: https://github.com/ursacomputing/crossbow/releases/tag/nightly-packaging-2022-07-30-0-github-java-jars
+2. Add packages to your pom.xml, for example: flight-core (it depends on: arrow-format, arrow-vector, arrow-memory-core and arrow-memory-netty).
+
+ .. code-block:: xml
+
+
+ 8
+ 8
+ 9.0.0.dev501
+
+
+
+
+ org.apache.arrow
+ flight-core
+ ${arrow.version}
+
+
+
+3. Download the necessary pom and jar files to a temporary directory:
+
+ .. code-block:: shell
+
+ $ mkdir nightly-packaging-2022-07-30-0-github-java-jars
+ $ cd nightly-packaging-2022-07-30-0-github-java-jars
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-java-root-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-format-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-format-9.0.0.dev501.jar
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-vector-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-vector-9.0.0.dev501.jar
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-memory-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-memory-core-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-memory-netty-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-memory-core-9.0.0.dev501.jar
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-memory-netty-9.0.0.dev501.jar
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/arrow-flight-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/flight-core-9.0.0.dev501.pom
+ $ wget https://github.com/ursacomputing/crossbow/releases/download/nightly-packaging-2022-07-30-0-github-java-jars/flight-core-9.0.0.dev501.jar
+ $ tree
+ .
+ ├── arrow-flight-9.0.0.dev501.pom
+ ├── arrow-format-9.0.0.dev501.jar
+ ├── arrow-format-9.0.0.dev501.pom
+ ├── arrow-java-root-9.0.0.dev501.pom
+ ├── arrow-memory-9.0.0.dev501.pom
+ ├── arrow-memory-core-9.0.0.dev501.jar
+ ├── arrow-memory-core-9.0.0.dev501.pom
+ ├── arrow-memory-netty-9.0.0.dev501.jar
+ ├── arrow-memory-netty-9.0.0.dev501.pom
+ ├── arrow-vector-9.0.0.dev501.jar
+ ├── arrow-vector-9.0.0.dev501.pom
+ ├── flight-core-9.0.0.dev501.jar
+ └── flight-core-9.0.0.dev501.pom
+
+4. Install the artifacts to the local Maven repository with ``mvn install:install-file``:
+
+ .. code-block:: shell
+
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-java-root-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-java-root -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-format-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-format -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-format-9.0.0.dev501.jar" -DgroupId=org.apache.arrow -DartifactId=arrow-format -Dversion=9.0.0.dev501 -Dpackaging=jar
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-vector-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-vector -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-vector-9.0.0.dev501.jar" -DgroupId=org.apache.arrow -DartifactId=arrow-vector -Dversion=9.0.0.dev501 -Dpackaging=jar
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-memory-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-memory -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-memory-core-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-memory-core -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-memory-netty-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-memory-netty -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-memory-core-9.0.0.dev501.jar" -DgroupId=org.apache.arrow -DartifactId=arrow-memory-core -Dversion=9.0.0.dev501 -Dpackaging=jar
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-memory-netty-9.0.0.dev501.jar" -DgroupId=org.apache.arrow -DartifactId=arrow-memory-netty -Dversion=9.0.0.dev501 -Dpackaging=jar
+ $ mvn install:install-file -Dfile="$(pwd)/arrow-flight-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=arrow-flight -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/flight-core-9.0.0.dev501.pom" -DgroupId=org.apache.arrow -DartifactId=flight-core -Dversion=9.0.0.dev501 -Dpackaging=pom
+ $ mvn install:install-file -Dfile="$(pwd)/flight-core-9.0.0.dev501.jar" -DgroupId=org.apache.arrow -DartifactId=flight-core -Dversion=9.0.0.dev501 -Dpackaging=jar
+
+5. Validate that the packages were installed:
+
+ .. code-block:: shell
+
+ $ tree ~/.m2/repository/org/apache/arrow
+ .
+ ├── arrow-flight
+ │ ├── 9.0.0.dev501
+ │ │ └── arrow-flight-9.0.0.dev501.pom
+ ├── arrow-format
+ │ ├── 9.0.0.dev501
+ │ │ ├── arrow-format-9.0.0.dev501.jar
+ │ │ └── arrow-format-9.0.0.dev501.pom
+ ├── arrow-java-root
+ │ ├── 9.0.0.dev501
+ │ │ └── arrow-java-root-9.0.0.dev501.pom
+ ├── arrow-memory
+ │ ├── 9.0.0.dev501
+ │ │ └── arrow-memory-9.0.0.dev501.pom
+ ├── arrow-memory-core
+ │ ├── 9.0.0.dev501
+ │ │ ├── arrow-memory-core-9.0.0.dev501.jar
+ │ │ └── arrow-memory-core-9.0.0.dev501.pom
+ ├── arrow-memory-netty
+ │ ├── 9.0.0.dev501
+ │ │ ├── arrow-memory-netty-9.0.0.dev501.jar
+ │ │ └── arrow-memory-netty-9.0.0.dev501.pom
+ ├── arrow-vector
+ │ ├── 9.0.0.dev501
+ │ │ ├── _remote.repositories
+ │ │ ├── arrow-vector-9.0.0.dev501.jar
+ │ │ └── arrow-vector-9.0.0.dev501.pom
+ └── flight-core
+ ├── 9.0.0.dev501
+ │ ├── flight-core-9.0.0.dev501.jar
+ │ └── flight-core-9.0.0.dev501.pom
+
+6. Compile your project like usual with ``mvn clean install``.
+
+.. _builds@arrow.apache.org: https://lists.apache.org/list.html?builds@arrow.apache.org
+.. _GitHub Nightly: https://github.com/ursacomputing/crossbow/releases/tag/nightly-packaging-2022-07-30-0-github-java-jars
+
+Installing Staging Packages
+===========================
+
+.. warning::
+ These packages are not official releases. Use them at your own risk.
+
+Arrow staging builds are created when a Release Candidate (RC) is being prepared. This allows users to test the RC in their applications before voting on the release.
+
+
+Installing from Apache Staging
+--------------------------------
+1. Look up the next version number for the Arrow libraries used.
+
+2. Add Apache Staging Repository to the Maven/Gradle project.
+
+ .. code-block:: xml
+
+
+ 9.0.0
+
+ ...
+
+
+ arrow-apache-staging
+ https://repository.apache.org/content/repositories/staging
+
+
+ ...
+
+
+ org.apache.arrow
+ arrow-vector
+ ${arrow.version}
+
+
+ ...
diff --git a/docs/source/developers/development.rst b/docs/source/developers/development.rst
new file mode 100644
index 00000000..dd183925
--- /dev/null
+++ b/docs/source/developers/development.rst
@@ -0,0 +1,197 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+.. highlight:: console
+
+======================
+Development Guidelines
+======================
+
+.. contents::
+
+Logger Abstraction
+==================
+
+Apache Arrow Java uses the SLF4J API, so please configure SLF4J to see logs (e.g. via Logback/Apache Log4j):
+
+1. If no jar dependencies are added by the user via Logback or Apache Log4j then SLF4J will default
+ to no-operation (NOP) logging.
+
+2. If a user adds any dependencies via Logback or Apache Log4j but does not configure/add/define
+ logback.xml/log4j2.xml, then logs will default to DEBUG mode.
+
+3. To disable debug logs, the user must define their own rules within their logback.xml/log4j2.xml
+ and define their own loggers.
+
+Unit Testing
+============
+Unit tests are run by Maven during the build.
+
+To speed up the build, you can skip them by passing -DskipTests.
+
+.. code-block::
+
+ $ cd arrow/java
+ $ mvn \
+ -Darrow.cpp.build.dir=../java-dist/lib -Parrow-jni \
+ -Darrow.c.jni.dist.dir=../java-dist/lib -Parrow-c-data \
+ clean install
+
+Performance Testing
+===================
+
+The ``arrow-performance`` module contains benchmarks.
+
+Let's configure our environment to run performance tests:
+
+- Install `benchmark`_
+- Install `archery`_
+
+In case you need to see your performance tests on the UI, then, configure (optional):
+
+- Install `conbench`_
+
+Lets execute benchmark tests:
+
+.. code-block::
+
+ $ cd benchmarks
+ $ conbench java-micro --help
+ $ conbench java-micro
+ --iterations=1
+ --commit=e90472e35b40f58b17d408438bb8de1641bfe6ef
+ --java-home=
+ --src=
+ --benchmark-filter=org.apache.arrow.adapter.AvroAdapterBenchmarks.testAvroToArrow
+ Benchmark Mode Cnt Score Error Units
+ AvroAdapterBenchmarks.testAvroToArrow avgt 725545.783 ns/op
+ Time to POST http://localhost:5000/api/login/ 0.14911699295043945
+ Time to POST http://localhost:5000/api/benchmarks/ 0.06116318702697754
+
+Then go to: http://127.0.0.1:5000/ to see reports:
+
+UI Home:
+
+.. image:: img/conbench_ui.png
+
+UI Runs:
+
+.. image:: img/conbench_runs.png
+
+UI Benchmark:
+
+.. image:: img/conbench_benchmark.png
+
+Integration Testing
+===================
+
+Integration tests can be run :ref:`via Archery `.
+For example, assuming you only built Arrow Java and want to run the IPC
+integration tests, you would do:
+
+.. code-block:: console
+
+ $ archery integration --run-ipc --with-java 1
+
+Code Style
+==========
+
+The current Java code follows the `Google Java Style`_ with Apache license headers.
+
+Java code style is checked by `Spotless`_ during the build, and the continuous integration build will verify
+that changes adhere to the style guide.
+
+Automatically fixing code style issues
+--------------------------------------
+
+- You can check the style without building the project with ``mvn spotless:check``.
+- You can autoformat the source with ``mvn spotless:apply``.
+
+Example:
+
+.. code-block:: bash
+
+ The following files had format violations:
+ src/main/java/org/apache/arrow/algorithm/rank/VectorRank.java
+ @@ -15,7 +15,6 @@
+ ·*·limitations·under·the·License.
+ ·*/
+
+ -
+ package·org.apache.arrow.algorithm.rank;
+
+ import·java.util.stream.IntStream;
+ Run 'mvn spotless:apply' to fix these violations.
+
+Code Formatter for Intellij IDEA and Eclipse
+--------------------------------------------
+
+Follow the instructions to set up google-java-format for:
+
+- `Eclipse`_
+- `IntelliJ`_
+
+
+Checkstyle
+----------
+
+Checkstyle is also used for general linting. The configuration is located at `checkstyle`_.
+You can also just check the style without building the project.
+This checks the code style of all source code under the current directory or from within an individual module.
+
+.. code-block::
+
+ $ mvn checkstyle:check
+
+Maven ``pom.xml`` style is enforced with Spotless using `Apache Maven pom.xml guidelines`_
+You can also just check the style without building the project.
+This checks the style of all pom.xml files under the current directory or from within an individual module.
+
+.. code-block::
+
+ $ mvn spotless:check
+
+This applies the style to all pom.xml files under the current directory or from within an individual module.
+
+.. code-block::
+
+ $ mvn spotless:apply
+
+.. _benchmark: https://github.com/ursacomputing/benchmarks
+.. _archery: https://github.com/apache/arrow/blob/main/dev/conbench_envs/README.md#L188
+.. _conbench: https://github.com/conbench/conbench
+.. _checkstyle: https://github.com/apache/arrow/blob/main/java/dev/checkstyle/checkstyle.xml
+.. _Apache Maven pom.xml guidelines: https://maven.apache.org/developers/conventions/code.html#pom-code-convention
+.. _Spotless: https://github.com/diffplug/spotless
+.. _Google Java Style: https://google.github.io/styleguide/javaguide.html
+.. _Eclipse: https://github.com/google/google-java-format?tab=readme-ov-file#eclipse
+.. _IntelliJ: https://github.com/google/google-java-format?tab=readme-ov-file#intellij-android-studio-and-other-jetbrains-ides
+
+Build Caching
+=============
+
+Build caching is done through Develocity (formerly Maven Enterprise). To force
+a build without the cache, run::
+
+ mvn clean install -Ddevelocity.cache.local.enabled=false -Ddevelocity.cache.remote.enabled=false
+
+This can be useful to make sure you see all warnings from ErrorProne, for example.
+
+ErrorProne
+==========
+
+ErrorProne should be disabled for generated code.
diff --git a/docs/source/developers/img/conbench_benchmark.png b/docs/source/developers/img/conbench_benchmark.png
new file mode 100644
index 0000000000000000000000000000000000000000..3adf3e8cd4fde3f16a81b4619de5d6937f9a6b2e
GIT binary patch
literal 141075
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