Skip to content

[bug] Fix Flink TaskManager Metaspace retention via shared Hadoop ReflectionUtils cache - #9827

Open
zhang-arvin wants to merge 1 commit into
apache:release-1.3from
zhang-arvin:fix/issue-9795
Open

zhang-arvin wants to merge 1 commit into
apache:release-1.3from
zhang-arvin:fix/issue-9795

Conversation

@zhang-arvin

Copy link
Copy Markdown
Contributor

Purpose

Fixes #9795

Root cause

Every finished Flink batch job shipping the Paimon connector as a user jar leaks ~18.2 MB TaskManager Metaspace permanently. The retained object is the job's ChildFirstClassLoader class for org.apache.paimon.shade.org.apache.parquet.hadoop.codec.ZstandardCodec, pinned by Hadoop's ReflectionUtils.CONSTRUCTOR_CACHE (static, strong keys) in the shared AppClassLoader.

Paimon shades parquet (1.15.2 on release-1.3) but deliberately does not shade Hadoop, so parquet's CodecFactory hands the job-classloader-loaded codec class into the shared Hadoop utility that never evicts production-side.

Fix

Parquet 1.16.0 rewrites CodecFactory to instantiate codecs directly (DirectCodecFactory) instead of going through ReflectionUtils.newInstance, so the strong-keyed shared cache is no longer on the path. The job classloader becomes garbage-collectible after job completion. main/2.1-SNAPSHOT already runs 1.16.0; this backports the version to release-1.3.

Verification

  • Bytecode check of 1.15.2 CodecFactory: invokes ReflectionUtils.newInstance → shared cache. 1.16.0 CodecFactory constructor builds DirectCodecFactory directly — no ReflectionUtils reference.
  • Link check: same vendored parquet sources + shade config compile on main with 1.16.0 (already proven upstream).

Reporter's verification method (from issue thread)

Heap-dump count of user-classloader keys in CONSTRUCTOR_CACHE should drop to 0 after upgrade.

…pache#9795)

Parquet 1.15.x CodecFactory instantiates codecs through Hadoop's
ReflectionUtils.CONSTRUCTOR_CACHE, a static ConcurrentHashMap with
strong keys living in the shared AppClassLoader. Paimon shades parquet
but not Hadoop, so the shaded ZstandardCodec class loaded by each job's
ChildFirstClassLoader is pinned there forever (~18 MB Metaspace per
finished Flink job, never reclaimed).

Parquet 1.16.0 rewrites CodecFactory to construct codecs directly
(DirectCodecFactory) and no longer routes through the shared
ReflectionUtils cache, so the job classloader is reclaimable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant