Implementation:Lance format Lance JNI FileReader
| Knowledge Sources | |
|---|---|
| Domains | Java_Bindings, JNI |
| Last Updated | 2026-02-08 19:33 GMT |
Overview
JNI FileReader is the Rust-side JNI binding that wraps the Lance FileReader, providing low-level file reading capabilities including opening Lance files, streaming record batches, retrieving schemas, and counting rows from Java.
Description
The BlockingFileReader struct wraps an Arc<FileReader> and provides synchronous access to Lance file reading operations. It supports:
- File opening via
Java_org_lance_file_LanceFileReader_openNative, which configures an object store, scan scheduler, and file scheduler from a URI and storage options, then opens the file reader asynchronously on the shared Tokio runtime. - Stream reading via
open_stream, which reads record batches with configurable batch size, read parameters, optional projection, and filter expressions. It usesread_stream_projected_blockingon a blocking Tokio task. - Schema retrieval via
schema, which returns the Arrow schema of the file. - Row counting via
num_rows, which returns the total number of rows in the file. - Resource cleanup via
Java_org_lance_file_LanceFileReader_closeNative, which takes ownership of the native reader and drops it.
The module also handles the lifecycle of the native reader handle by attaching it to a Java LanceFileReader object using JNI's set_rust_field mechanism, storing the Rust struct as an opaque field on the Java side.
Usage
Use this module when implementing or extending the Java API for direct Lance file reading (as opposed to dataset-level reading). It provides access to individual Lance files without the dataset metadata layer.
Code Reference
Source Location
java/lance-jni/src/file_reader.rs
Signature
pub struct BlockingFileReader {
pub(crate) inner: Arc<FileReader>,
}
impl BlockingFileReader {
pub fn create(file_reader: Arc<FileReader>) -> Self;
pub fn open_stream(
&self,
batch_size: u32,
read_batch_params: ReadBatchParams,
reader_projection: Option<ReaderProjection>,
filter_expression: FilterExpression,
) -> Result<Box<dyn RecordBatchReader + Send + 'static>>;
pub fn schema(&self) -> Result<SchemaRef>;
pub fn num_rows(&self) -> u64;
}
Import
use crate::file_reader::{BlockingFileReader, NATIVE_READER};
I/O Contract
| Direction | Type | Description |
|---|---|---|
| Input | JString (file URI) |
URI of the Lance file to open (local path or object store URL) |
| Input | JObject (storage options Map) |
Java Map<String, String> for storage configuration
|
| Input | jint (batch size) |
Number of rows per record batch when streaming |
| Input | jint (batch offset/limit) |
Range parameters for partial file reads |
| Output | JObject (Java LanceFileReader) |
Java file reader object with native handle attached |
| Output | Arrow FFI stream | Record batch stream exported via FFI_ArrowArrayStream
|
| Output | Arrow FFI schema | File schema exported via FFI_ArrowSchema
|
| Output | jlong |
Row count as a long integer |
Usage Examples
// Java side: opening and reading a Lance file
import org.lance.file.LanceFileReader;
Map<String, String> storageOptions = new HashMap<>();
LanceFileReader reader = LanceFileReader.open("s3://bucket/data.lance", storageOptions);
long numRows = reader.numRows();
ArrowReader batchReader = reader.read(1024, 0, numRows);
// Rust JNI side: open function pattern
#[no_mangle]
pub extern "system" fn Java_org_lance_file_LanceFileReader_openNative<'local>(
mut env: JNIEnv<'local>,
_reader_class: JObject,
file_uri: JString,
storage_options_obj: JObject,
) -> JObject<'local> {
ok_or_throw!(env, inner_open(&mut env, file_uri, storage_options_obj))
}
Related Pages
- Lance_format_Lance_JNI_BlockingDataset - Dataset-level reader that uses the higher-level dataset API
- Lance_format_Lance_JNI_FFI - JNIEnvExt trait used for type conversions
- Lance_format_Lance_JNI_Utils - Storage options extraction utilities
- Lance_format_Lance_JNI_Traits - IntoJava trait used to convert the reader to a Java object