High-Performance IBAN processing:
iban-commons

Ultra-fast. Allocation-free. Zero dependencies Java 8+. Immutable. 100% Coverage. PI-tested

Why iban-commons?

Developed with a focus on Clean Code, Compatibility, and Performance, this library is designed for top-performance systems and headache-free operation.

  • 1 Strict ISO 13616 Compliance
  • 2 National Check Digit Validation
  • 3 100% Test Coverage, PI-tested
  • 4 Compatible (Java 8+)
  • 5 Immutable & Thread-safe
  • 6 Zero Dependencies & Small Footprint
  • 7 Simple & intuitive, Android-friendly API
  • 8 Open Source - Free of Charge
Alpine Landscape

Part of the Java Ecosystem

iban-commons is integrated into these open source projects.

Quick Start

Maven Dependency

<dependency>
    <groupId>de.speedbanking</groupId>
    <artifactId>iban-commons</artifactId>
    <version>1.8.7</version>
</dependency>

Java Example

String s = "DE91100000000123456789";

if (Iban.isValid(s)) {
    System.out.println("Valid IBAN: " + s);
}

try {
    Iban iban = Iban.of(s);
    System.out.println("Country Code: " + iban.getCountryCode()); // DE
    System.out.println("Check Digits: " + iban.getCheckDigits()); // 91
    System.out.println("BBAN        : " + iban.getBban());        // 100000000123456789
} catch (InvalidIbanException ex) {
    System.err.println("Invalid IBAN: " + ex);
}
More Examples

What's New in 1.8.7

Allocation-Free Validation Path

IbanValidationResult now caches one singleton per IbanValidationError constant at class-load time. Failed validations on the hot path no longer allocate. Iban.toFormattedString() caches its result in a transient volatile field

Cleaner validate() API

New allocation-free Iban.validate() and Bic.validate() methods throw on invalid input without constructing an instance — ideal for strict input guards.

Internal Refactoring & Correctness

Objects.hash() replaced with the classic Bloch prime-accumulation pattern. IbanRegistry.ALL_COUNTRIES is now a shared, alphabetically pre-sorted array. PMD upgraded to 7.24.0, pitest-maven to 1.23.1.

What's New in 1.8.6

Invalid IBAN Generator

New utilities for generating structurally invalid IBAN strings with controlled sabotage strategies — invaliding check digits, corrupting BBAN segments, and mutating country codes. Purpose-built for negative test suites and fuzz harnesses.

Error-Prone Integration

The build now integrates Error‑Prone with error‑prone‑support, catching bug patterns at compile time that unit tests alone cannot surface. Even stronger code quality enforcement is part of every build, not just CI.

Dedicated JUnit Extensions Module

JUnit 5 extensions (enhanced IBAN and BIC assertions, parameterized test support) have been extracted into a standalone iban-commons-junit sub-module. Test infrastructure is now decoupled from the core library — include it only where needed.

What's New in 1.8.5

Near-Zero Allocation

The entire internal validation pipeline has been migrated from CharSequence to char[] across all country validators and the NationalCheckDigitCalculator SPI. This eliminates virtual dispatch on charAt() and allows the JIT to apply scalar replacement, reducing measured heap allocation to effectively zero (< 0.001 B/op). Backward compatibility is preserved.

Expanded Public API

Bic, IbanRegistry, RandomBic, and the Formatter type are now part of the stable public API. The RandomIban factory methods have been replaced by a fluent builder for more explicit and composable generation.

  • RandomIban.builder()   .country("DE").build()
  • RandomIban.builder()   .sepaOnly().random(rng).build()

Immutable IbanConfig

IbanConfig has been redesigned from a mutable enum to an immutable class using the freeze pattern. Configuration is locked at startup via IbanConfig.freeze(); concurrent reads thereafter require no synchronization and mutation is permanently blocked.

What's New in 1.8.4

Country-Agnostic Random IBANs

Two new factory methods on RandomIban generate valid IBANs without requiring a specific country:

  • RandomIban.of() — any supported country
  • RandomIban.ofSepa() — SEPA countries only

Iso3166Alpha2 Enum & BIC Validation

A new Iso3166Alpha2 enum provides a type-safe representation of all registered ISO 3166 Alpha-2 country codes. BIC country code validation is now backed by this enum, eliminating string-based lookups and tightening correctness guarantees at compile time.

Reduced Bic Memory Footprint

The internal Bic representation has been slimmed down by removing a redundant char[] field and eliminating eager computation of the padded BIC-11 form. Both are now derived on demand, reducing per-instance heap allocation with no change to the public API.

What's New in 1.8.3

Serialization Security

Iban and Bic now use the Serialization Proxy Pattern (Memento). Byte-stream injection attacks are blocked: deserialization always re-validates through the full ISO 7064 Mod 97-10 pipeline. Direct deserialization of raw instances throws InvalidObjectException.

SECURITY.md

Android Compatibility

New null-returning alternatives avoid java.time.YearMonth (requires API 26+):

  • IbanRegistry.getLastUpdateYear()
  • IbanRegistry.getLastUpdateMonth()

Feature Parity

All remaining gaps vs. alternative libraries are now closed. iban-commons leads on country coverage (120 vs. 111), BIC support, rich metadata, random IBAN generation, and validation error detail — now also matching on serialization hardening and Android-friendly API.

Performance

Leading Throughput

Outperforms all tested libraries — reaching 6.0 M ops/s on valid IBANs and over 10.0 M ops/s on invalid ones, where fast-path rejection kicks in.

Up to 3.2× Faster

On the accept path, iban-commons is ~1.9× faster than jbanking, ~2.1× faster than Apache Commons, and ~3.2× faster than Garvelink.

Zero Allocation

Exactly 0 B/op — the allocation-free validation pipeline eliminates all transient heap allocation on both paths. Competitors allocate 149–1,308 B/op.

Throughput Comparison

Operations per second (higher is better) — OpenJDK 25.0.3, Linux, single core
SerialGC  |  -XX:-StackTraceInThrowable  |  JMH: 3 forks × 5 iterations × 2 s  |  2026-05-18

Valid IBANs — accept path

iban-commons ~0 B/op
5,969,030 ops/s
jbanking 285 B/op
3,126,700 ops/s
2,834,814 ops/s
iban4j 1,134 B/op
2,707,556 ops/s
1,853,998 ops/s

Invalid IBANs — rejection path

iban-commons ~0 B/op
10,024,826 ops/s
jbanking 150 B/op
7,410,188 ops/s
6,199,467 ops/s
iban4j 1,308 B/op
1,919,874 ops/s
2,028,735 ops/s

Memory figures (B/op) from JMH gc.alloc.rate.norm profiler. All forks run with -XX:-StackTraceInThrowable to isolate algorithmic cost; exception-heavy libraries (iban4j, Garvelink) benefit from this flag on the rejection path — remove it for production-realistic numbers. Full methodology & raw data →

Balloon Burner

Fueled by Performance