{"record":{"id":"1424661359d66b0c","repo":"hibernate/hibernate-orm","slug":"maximum-capacity-has-to-be-at-least-twice-the-conc","errorCode":null,"errorMessage":"Maximum capacity has to be at least twice the concurrencyLevel","messagePattern":"Maximum capacity has to be at least twice the concurrencyLevel","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/util/collections/BoundedConcurrentHashMap.java","lineNumber":1461,"sourceCode":"\t * internal sizing to try to accommodate this many threads.\n\t * @param evictionStrategy the algorithm used to evict elements from this map\n\t *\n\t * @throws IllegalArgumentException if the initial capacity is negative or the load factor or concurrencyLevel are\n\t * nonpositive.\n\t */\n\tpublic BoundedConcurrentHashMap(\n\t\t\tint capacity, int concurrencyLevel,\n\t\t\tEviction evictionStrategy) {\n\t\tif ( capacity < 0 || concurrencyLevel <= 0 ) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t\tconcurrencyLevel = Math.min( capacity / 2, concurrencyLevel ); // concurrencyLevel cannot be > capacity/2\n\t\tconcurrencyLevel = Math.max( concurrencyLevel, 1 ); // concurrencyLevel cannot be less than 1\n\n\t\t// minimum two elements per segment\n\t\tif ( capacity < concurrencyLevel << 1 && capacity != 1 ) {\n\t\t\tthrow new IllegalArgumentException( \"Maximum capacity has to be at least twice the concurrencyLevel\" );\n\t\t}\n\n\t\tif ( evictionStrategy == null ) {\n\t\t\tthrow new IllegalArgumentException();\n\t\t}\n\n\t\tif ( concurrencyLevel > MAX_SEGMENTS ) {\n\t\t\tconcurrencyLevel = MAX_SEGMENTS;\n\t\t}\n\n\t\t// Find power-of-two sizes best matching arguments\n\t\tint sshift = 0;\n\t\tint ssize = 1;\n\t\twhile ( ssize < concurrencyLevel ) {\n\t\t\t++sshift;\n\t\t\tssize <<= 1;\n\t\t}\n\t\tsegmentShift = 32 - sshift;","sourceCodeStart":1443,"sourceCodeEnd":1479,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/util/collections/BoundedConcurrentHashMap.java#L1443-L1479","documentation":"BoundedConcurrentHashMap is Hibernate's LIRS-backed bounded map (used for the query plan cache). Its segments need at least two slots each, so the constructor first clamps concurrencyLevel to capacity/2 (min 1) and then rejects the pair when capacity < concurrencyLevel << 1 (except the special case capacity == 1). This IllegalArgumentException means the requested capacity cannot host the requested segment count.","triggerScenarios":"new BoundedConcurrentHashMap<>(capacity, concurrencyLevel, evictionStrategy) with capacity smaller than twice concurrencyLevel, e.g. (8, 16), (3, 2) — note 3 < 2*2 and 3 != 1, so it throws; (2, 1) passes after clamping.","commonSituations":"Shrinking Hibernate caches (query plan cache sizing derived from hibernate.query.plan_cache_max_size) or other tuned caches to very small capacities while keeping a default concurrency level of 16; porting constructor arguments from ConcurrentHashMap, which allows any combination.","solutions":["Raise capacity to at least 2 * concurrencyLevel (power-of-two capacity is ideal)","Or lower concurrencyLevel — for small maps 1 or 2 segments are plenty","Check the cache settings that feed these numbers (e.g. plan cache sizing) and recompute them together, not independently"],"exampleFix":"// before: 8 slots cannot host 16 segments\nMap<K, V> cache = new BoundedConcurrentHashMap<>( 8, 16, Eviction.LIRS );\n// after: capacity at least twice the concurrency level\nMap<K, V> cache = new BoundedConcurrentHashMap<>( 32, 16, Eviction.LIRS );","handlingStrategy":"validation","validationCode":"// Validate before constructing a bounded concurrent map\nstatic <K, V> BoundedConcurrentHashMap<K, V> boundedMap(int capacity, int concurrencyLevel, Eviction eviction) {\n    if ( capacity < 0 ) throw new IllegalArgumentException(\"capacity must be >= 0\");\n    concurrencyLevel = Math.min( Math.max( Math.min( capacity / 2, concurrencyLevel ), 1 ), capacity == 1 ? 1 : capacity / 2 );\n    if ( capacity != 1 && capacity < concurrencyLevel << 1 ) {\n        concurrencyLevel = Math.max( 1, capacity / 2 ); // clamp instead of throwing\n    }\n    return new BoundedConcurrentHashMap<>( capacity, concurrencyLevel, eviction );\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Choose capacity as a power of two at least 2x the concurrency level (default 16 segments -> capacity >= 32)","Derive both values from one sizing knob instead of independent config keys","When shrinking caches for tests, shrink concurrency first, capacity second"],"tags":["hibernate","cache","constructor-validation","configuration","collections"],"backgroundTag":"invalid-configuration-value","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}