High-Performance IBAN processing:
iban-commons

Ultra-fast. Low-memory. Zero dependencies. Java 8+. Clean code. Immutable. 100% Coverage.

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-compatible API
  • 8 Open Source & Free of Charge
Alpine Landscape

Quick Start

Maven Dependency

<dependency>
    <groupId>de.speedbanking</groupId>
    <artifactId>iban-commons</artifactId>
    <version>1.8.5</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.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.util.Optional (requires Android API 24+) and java.time.YearMonth (requires API 26+):

  • Iban.tryParseOrNull(input)
  • Bic.tryParseOrNull(input)
  • 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.

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.5

Near-Zero Allocation

The entire internal validation pipeline has been migrated from CharSequence to char[] across all 80+ 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.

Performance

Leading Throughput

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

Up to 2.5× Faster

On the accept path, iban-commons is ~1.3× faster than jbanking, ~1.7× faster than Apache Commons, and ~2.5× faster than Garvelink.

Near-Zero Allocation

Effectively 0 B/op — the char[] validation pipeline introduced in 1.8.5 eliminates all transient heap allocation. Competitors allocate 154–1,133 B/op.

Throughput Comparison

Operations per second (higher is better) — Intel i7-1165G7 @ 2.80 GHz, OpenJDK 21.0.7, Linux, single core (taskset -c 0)
ParallelGC  |  -XX:-StackTraceInThrowable  |  JMH: 2 forks × 4–5 iterations × 2 s  |  2026-04-19

Valid IBANs — accept path

iban-commons ~0 B/op
5,591,566 ops/s
jbanking 298 B/op
4,278,475 ops/s
3,208,846 ops/s
iban4j 1,133 B/op
2,870,107 ops/s
2,269,465 ops/s

Invalid IBANs — rejection path

iban-commons ~0 B/op
10,740,280 ops/s
jbanking 154 B/op
7,880,633 ops/s
6,531,841 ops/s
iban4j 1,156 B/op
1,801,759 ops/s
2,250,043 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