Tess4J OCR Parser

Advanced users only. Tess4JParser loads the Tesseract native library into your JVM through JNA. Running it safely means locating and linking the right platform-specific native libraries, reasoning about the Java/native boundary, and accepting that a fault in native code can crash the whole JVM.

If that doesn’t describe you, don’t reach for this parser — and that’s perfectly fine. TesseractOCRParser does the same OCR by running the tesseract command-line program in a separate process: no native linking, far easier to set up, and a Tesseract crash can never take down your application. Choose Tess4JParser only with a measured need for in-process OCR throughput and the expertise to run native bindings safely.

Tess4JParser calls the Tesseract native library in-process via Tess4J and JNA instead of spawning a tesseract child process per image. That removes the per-file process-spawn overhead and can be significantly faster on large batches.

The native Tesseract handle is not thread-safe, so the parser keeps a configurable pool of Tesseract instances that threads borrow and return; the parser itself is safe for concurrent use.

Run this parser in a forked JVM using tika-pipes, ideally inside a Docker container. A segfault or memory leak in the native Tesseract or Leptonica code takes down whatever JVM loaded it. Do not put it in a long-lived application server process.

Module dependency

The parser lives in the tika-parser-tess4j-module artifact:

<dependency>
  <groupId>org.apache.tika</groupId>
  <artifactId>tika-parser-tess4j-module</artifactId>
  <version>4.0.0</version>
</dependency>

Prerequisites

You must have the Tesseract and Leptonica shared libraries installed on the machine where the parser runs. The tess4j jar bundles Windows DLLs only — on macOS and Linux you are responsible for installing the native libraries yourself.

  • Debian / Ubuntu: apt-get install libtesseract-dev libleptonica-dev tesseract-ocr-eng

  • RHEL / Fedora: dnf install tesseract-devel leptonica-devel tesseract-langpack-eng

  • macOS (Homebrew): brew install tesseract

You also need the tessdata language files. The dataPath configuration option must point to the directory containing them (e.g., /usr/share/tesseract-ocr/5/tessdata).

Native library path (jna.library.path)

JNA must be able to find libtesseract and libleptonica at runtime. The tess4j jar does not bundle these libraries for macOS or Linux. If JNA cannot find them on the default library search path, the parser will silently disable itself.

You have several options:

  1. Set nativeLibPath in the parser configuration (recommended). The parser will prepend this to the jna.library.path system property at initialization time.

  2. Set the jna.library.path JVM system property yourself, e.g., -Djna.library.path=/opt/homebrew/lib.

  3. Install the libraries into a directory that is already on the default search path (e.g., /usr/lib).

You are on your own here. The correct path depends entirely on your OS, distribution, and how you installed Tesseract. Common values:

Platform Typical nativeLibPath

Debian / Ubuntu

/usr/lib/x86_64-linux-gnu

RHEL / Fedora

/usr/lib64

macOS (Homebrew, Apple Silicon)

/opt/homebrew/lib

macOS (Homebrew, Intel)

/usr/local/lib

Docker (see below)

/usr/lib/x86_64-linux-gnu

Basic Configuration

{
  "parsers": [
    {
      "tess4j-parser": {
        "dataPath": "/usr/share/tesseract-ocr/5/tessdata",
        "nativeLibPath": "/usr/lib/x86_64-linux-gnu",
        "poolSize": 4
      }
    }
  ]
}

Full Configuration

{
  "parsers": [
    {
      "tess4j-parser": {
        "dataPath": "/usr/share/tesseract-ocr/5/tessdata",
        "nativeLibPath": "/usr/lib/x86_64-linux-gnu",
        "language": "eng",
        "pageSegMode": 1,
        "ocrEngineMode": 3,
        "poolSize": 4,
        "timeoutMillis": 120000,
        "dpi": 300,
        "minFileSizeToOcr": 0,
        "maxFileSizeToOcr": 2147483647,
        "maxImagePixels": 100000000,
        "skipOcr": false
      }
    }
  ]
}

Configuration options reference

Property Default Description

dataPath

"" (empty)

Path to the tessdata directory containing language data files. Required on macOS and Linux.

nativeLibPath

"" (empty)

Path to the directory containing libtesseract and libleptonica shared libraries. Prepended to jna.library.path at initialization time.

language

"eng"

Tesseract language(s). Multiple languages separated by + (e.g., eng+fra).

pageSegMode

1

Page segmentation mode (0-13). 1 = automatic with OSD.

ocrEngineMode

3

OCR engine mode. 0 = legacy, 1 = LSTM only, 2 = legacy + LSTM, 3 = default (whatever is available).

poolSize

2

Number of Tesseract instances in the pool. Set this to the number of threads that will call the parser concurrently. Each instance consumes native memory.

timeoutMillis

120000

Timeout (milliseconds) applied both to waiting for a pooled Tesseract instance and to each image’s OCR call. Each is budgeted separately up to this value, clipped to whatever remains of the task’s total budget.

dpi

300

DPI for image rendering.

minFileSizeToOcr

0

Minimum input file size in bytes. Smaller files are skipped.

maxFileSizeToOcr

52428800 (50 MB)

Maximum input file size in bytes. Larger files are skipped.

maxImagePixels

100000000 (100 megapixels)

Maximum decoded-image area. Larger images are skipped. Guards against decompression-bomb inputs that would blow up memory before OCR even starts.

skipOcr

false

Runtime kill-switch to disable the parser entirely.

Because this parser loads native code into the JVM, the safest deployment is a Docker container running tika-pipes with forked JVMs. If the native code crashes, only the fork dies — tika-pipes will respawn it automatically.

A minimal Dockerfile:

FROM eclipse-temurin:21-jre

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        libtesseract-dev \
        libleptonica-dev \
        tesseract-ocr-eng && \
    rm -rf /var/lib/apt/lists/*

# Copy your tika-pipes application and config
COPY target/tika-pipes-app.jar /app/tika-pipes-app.jar
COPY tika-config.json /app/tika-config.json

WORKDIR /app
ENTRYPOINT ["java", "-jar", "tika-pipes-app.jar"]

Use the basic configuration above with those container paths.

Set poolSize equal to the number of forked parser threads to maximize throughput without over-allocating native memory.

Tess4J vs. TesseractOCRParser

Aspect TesseractOCRParser Tess4JParser

How it calls Tesseract

Spawns a new tesseract child process per image

Calls the native library in-process via JNA

Startup overhead

Process fork + exec per file

One-time JNA initialization; pooled thereafter

Thread safety

Naturally safe (separate processes)

Safe via pooled instances

Crash isolation

Child process crashes do not affect the JVM

A native crash will take down the JVM

Dependencies

tesseract binary on PATH

libtesseract + libleptonica shared libraries + JNA

Best for

Safety-first deployments, light OCR workloads

High-throughput batch processing in Docker / tika-pipes

Per-request configuration

In-process, place a Tess4JConfig on the ParseContext:

Tess4JConfig override = new Tess4JConfig();
override.setLanguage("fra");
override.setPageSegMode(6);

ParseContext context = new ParseContext();
context.set(Tess4JConfig.class, override);
In caller-supplied JSON config — the tika-server /config endpoints, tika-grpc’s parse_context_jsondataPath and nativeLibPath are locked at parser initialization, and setting either throws TikaConfigException. They point at native code, so a caller must not be able to move them.