{"record":{"id":"6c97e08b17625f76","repo":"MyCATApache/Mycat-Server","slug":"not-enough-memory-to-grow-pointer-array","errorCode":null,"errorMessage":"Not enough memory to grow pointer array","messagePattern":"Not enough memory to grow pointer array","errorType":"exception","errorClass":"OutOfMemoryError","httpStatus":null,"severity":"critical","filePath":"src/main/java/io/mycat/memory/unsafe/utils/sort/UnsafeInMemorySorter.java","lineNumber":195,"sourceCode":"\n  /**\n   * @return the total amount of time spent sorting data (in-memory only).\n   */\n  public long getSortTimeNanos() {\n    return totalSortTimeNanos;\n  }\n\n  public long getMemoryUsage() {\n    return array.size() * 8;\n  }\n\n  public boolean hasSpaceForAnotherRecord() {\n    return pos + 1 < (array.size() / memoryAllocationFactor);\n  }\n\n  public void expandPointerArray(LongArray newArray) {\n    if (newArray.size() < array.size()) {\n      throw new OutOfMemoryError(\"Not enough memory to grow pointer array\");\n    }\n    Platform.copyMemory(\n      array.getBaseObject(),\n      array.getBaseOffset(),\n      newArray.getBaseObject(),\n      newArray.getBaseOffset(),\n      array.size() * (8 / memoryAllocationFactor));\n    consumer.freeLongArray(array);\n    array = newArray;\n  }\n\n  /**\n   * Inserts a record to be sorted. Assumes that the record pointer points to a record length\n   * stored as a 4-byte integer, followed by the record's bytes.\n   *\n   * @param recordPointer pointer to a record in a data page, encoded by {@link DataNodeMemoryManager}.\n   * @param keyPrefix a user-defined key prefix\n   */","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/memory/unsafe/utils/sort/UnsafeInMemorySorter.java#L177-L213","documentation":"UnsafeInMemorySorter.expandPointerArray throws OutOfMemoryError when the replacement LongArray offered for the sorter's pointer/prefix array is smaller than the current one. Growth must never shrink capacity, so the method fails fast rather than truncating in-flight sort records.","triggerScenarios":"Calling expandPointerArray with a newly allocated LongArray whose size < current array.size() — typically when the memory manager could not acquire the requested page size and silently allocated less, or a caller passes a mis-sized array.","commonSituations":"Heavy memory pressure: executor heap fully consumed by cached blocks/pages so the allocator grants a smaller array; misconfigured memory fractions leaving too little execution memory for the sorter to double its pointer array.","solutions":["Free execution memory (unpersist/spill cached data) before the sort so the growth allocation can be full-sized.","Increase execution memory limits (memory fraction / heap size) for the process.","Fix callers to allocate the new array at >= 2x current size and assert size before calling.","Reduce concurrent sorters/tasks competing for the same memory pool.","Enable spilling earlier so the in-memory sorter needs fewer expansions."],"exampleFix":"// before\nLongArray newArr = allocate(someSize);\nsorter.expandPointerArray(newArr);\n// after\nlong newSize = Math.max(sorter.getCurrentArraySize() * 2, minRequired);\nLongArray newArr = allocate(newSize);\nif (newArr.size() < sorter.getCurrentArraySize()) spillAndRetry();\nsorter.expandPointerArray(newArr);","handlingStrategy":"try-catch","validationCode":"LongArray grow = tryAllocate(current * 2);\nif (grow == null || grow.size() < current) { spill(); return; }\nsorter.expandPointerArray(grow);","typeGuard":null,"tryCatchPattern":"try { sorter.expandPointerArray(newArray); } catch (OutOfMemoryError e) { spillCurrentSorter(); freeMemory(); retryExpansion(); }","preventionTips":["Reserve execution memory headroom before large sorts","Spill earlier instead of relying on repeated array growth","Cap concurrent in-memory sorters","Monitor allocator failures in memory manager metrics"],"tags":["out-of-memory","sorting","memory-management"],"backgroundTag":"insufficient-memory","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}