This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Zero-Allocation Hashing is a Java library providing fast, non-cryptographic hash functions that allocate zero objects during hash computation. It implements multiple algorithms (CityHash, FarmHash, MurmurHash3, xxHash, XXH3, wyHash, MetroHash) for hashing byte sequences from various sources (arrays, buffers, CharSequence, raw memory). The corresponding Java class for MurmurHash3 is MurmurHash_3.
Target: Java 8+ (supports JDK 8, 11, 17, 21+)
# Run full build with tests
mvn verify
# Run tests only
mvn test
# Run specific test class
mvn test -Dtest=LongHashFunctionTest
# Run specific test method
mvn test -Dtest=LongHashFunctionTest#testHashBytes
# Clean build
mvn clean install
# Generate javadoc
mvn javadoc:javadoc
# Run quality profile (Checkstyle + SpotBugs); requires JDK 11+
mvn -Pquality verifyLongHashFunction (src/main/java/net/openhft/hashing/LongHashFunction.java)
- Primary facade for 64-bit hashes
- Factory methods:
city_1_1(),farmNa(),farmUo(),murmur_3(),xx(),xx3(),xx128low(),wy_3(),metro() - All instances are immutable and thread-safe
- Seeds are baked into instances at construction time
LongTupleHashFunction (src/main/java/net/openhft/hashing/LongTupleHashFunction.java)
- Multi-word hash results (128-bit and beyond)
- Uses reusable
long[]buffers to maintain zero-allocation guarantee - Caller must manage/reuse result arrays
Access<T> (src/main/java/net/openhft/hashing/Access.java)
- Strategy pattern abstracting byte sequence reading from different sources
- Implementations:
UnsafeAccess(heap arrays),ByteBufferAccess,CharSequenceAccess,CompactLatin1CharSequenceAccess - Handles byte-order normalisation via
Access.byteOrder(input, desiredOrder) - Algorithms are written once against
Accessinterface, work with all input types
Byte Order Handling
- All algorithms normalise to Little-Endian internally (ADR-002)
- Ensures cross-platform deterministic results (x86 vs s390x)
- Performance penalty on Big-Endian platforms due to byte-swapping
UnsafeAccess (src/main/java/net/openhft/hashing/UnsafeAccess.java)
- Wraps
sun.misc.Unsafefor zero-copy memory reads - Enables "type punning" (reading bytes as longs) efficiently
- Requires
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMEDon Java 9+
String Hashing Runtime Adaptation (src/main/java/net/openhft/hashing/Util.java)
VALID_STRING_HASHselects correct strategy at JVM initialisation- Handles: HotSpot (pre-compact, compact strings), OpenJ9, Zing, unknown VMs
- Uses reflection to access internal
String.valuefield (ADR-004) - Fallback:
UnknownJvmStringHashfor unrecognized JVMs
All live in package-private classes with factory methods exposed via LongHashFunction:
CityAndFarmHash_1_1- CityHash64 v1.1, FarmHash NA/UOMurmurHash_3- 64-bit and 128-bit variantsXxHash- XXH64XXH3- XXH3 64-bit and 128-bitWyHash- wyHash v3MetroHash- metrohash64_2
- Use British English: "organisation", "licence", "optimisation", "normalise", "initialise" (NOT "organization", "license", "optimization")
- Technical US spellings allowed: "synchronized", "byte"
- ISO-8859-1 only (code-points 0-255) except in string literals
- NO smart quotes, non-breaking spaces, accented characters in code/docs
- Use textual forms: "micro-second", ">=", ":alpha:" instead of Unicode
DO:
- Document behavioural contracts, edge-cases, thread-safety, units, performance characteristics
- Explain constraints via
@param, conditions via@throws - Keep first sentence short (becomes summary line)
DON'T:
- Restate the obvious ("Gets the value", "Sets the name")
- Duplicate parameter names/types without additional explanation
- Leave autogenerated Javadoc for trivial getters/setters
- Zero-allocation in steady state (one-time allocation during class loading permitted)
- Validate array offsets/lengths via
Util.checkArrayOffsto prevent crashes - Assume raw memory addresses are pre-validated by caller
- No ThreadLocal usage (containerisation requirement)
- Immutable, stateless hash function instances
- Keep AsciiDoc files synchronized with code/tests
- Update
src/main/docs/*.adocwhen changing features, requirements, or implementations - See
AGENTS.mdfor company-wide documentation standards - Reference decisions in commit messages (e.g., "Implements ADR-003")
- Thoroughly tested on LTS JDKs: 8, 11, 17, 21
- Test both Little-Endian and Big-Endian platforms
- JDK 9+ runs tests twice: with and without
-XX:-CompactStrings(see pom.xml profiles) - All tests use JUnit 4 (supports Java 7+)
- Subject line <= 72 chars, imperative mood: "Fix roll-cycle offset in ExcerptAppender"
- Body format: root cause -> fix -> measurable impact
- Run
mvn verifybefore committing - Reference JIRA/GitHub issues
- Use ASCII bullet points in commit bodies
- Main branch for PRs: ea (not master)
src/main/java/net/openhft/hashing/
Access.java - Core abstraction for byte sequence reading
LongHashFunction.java - Primary 64-bit hash facade
LongTupleHashFunction.java - Multi-word hash facade
DualHashFunction.java - Bridges 128-bit -> 64-bit views
UnsafeAccess.java - sun.misc.Unsafe wrapper
[Algorithm Implementations]
CityAndFarmHash_1_1.java
MurmurHash_3.java
XxHash.java
XXH3.java
WyHash.java
MetroHash.java
[Memory Access Strategies]
ByteBufferAccess.java
CharSequenceAccess.java
CompactLatin1CharSequenceAccess.java
[String Hashing Adapters]
StringHash.java
ModernHotSpotStringHash.java
ModernCompactStringHash.java
HotSpotPrior7u6StringHash.java
UnknownJvmStringHash.java
[Utilities]
Util.java - Runtime detection, validation
Primitives.java - Byte-order normalization
Maths.java - Low-level arithmetic helpers
src/main/docs/
project-requirements.adoc - Functional/non-functional requirements
decision-log.adoc - Architecture Decision Records (ADRs)
architecture-overview.adoc - System architecture details
algorithm-profiles.adoc - Per-algorithm characteristics
testing-strategy.adoc - Test coverage approach
- Create package-private class implementing the algorithm
- Extend
LongHashFunctionorLongTupleHashFunction - Use
Access<T>abstraction for all memory reads - Normalize to Little-Endian via
Access.byteOrder(input, LITTLE_ENDIAN) - Add factory methods to
LongHashFunctionfacade - Add tests validating against reference implementation
- Update
algorithm-profiles.adocwith characteristics
// Example from Access.java documentation
class Pair {
long first, second;
static final long pairDataOffset =
theUnsafe.objectFieldOffset(Pair.class.getDeclaredField("first"));
static long hashPair(Pair pair, LongHashFunction hashFunction) {
return hashFunction.hash(pair, Access.unsafe(), pairDataOffset, 16L);
}
}Requires JVM flags for internal API access:
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens java.base/sun.nio.ch=ALL-UNNAMEDSee src/main/docs/decision-log.adoc for the canonical ADR list (ADR-001 through ADR-006). Reference ADR IDs in commit messages where relevant.
- Javadoc: https://javadoc.io/doc/net.openhft/zero-allocation-hashing/latest
- GitHub: https://github.com/OpenHFT/Zero-Allocation-Hashing
- Issues: https://github.com/OpenHFT/Zero-Allocation-Hashing/issues
- Release Notes: https://chronicle.software/release-notes/
- Company Guidelines: See
AGENTS.mdfor Chronicle Software standards