Skip to content

Memory leak in TypeTag cache #11767

@zsxwing

Description

@zsxwing

We found a memory leak after upgrading from Scala 2.12.8 to Scala 2.12.10. After investigation,
we realized that the root cause is scala/scala#8112 and confirmed disabling this cache can stop the memory leak.

After digging into codes, we think there are two issues here :

  • It caches TypeTagImpl using the typeCreator's class. However, the class of typeCreator can be the same when there are multiple JavaMirrors. Hence, the cache may return a TypeTagImpl that ties to an incorrect JavaMirror (It's cached by a previous JavaMirror).
  • TypeTagImpl has a strong reference to typeTagCache (TypeTagImpl -> JavaMirror -> typeTagCache -> java.lang.ClassValue.Identity). As java.lang.ClassValue.Identity is the key type and TypeTagImpl is the value type of WeakHashMap (inside ClassValue), the current pattern is exactly WeakHashMap's doc asks to not do: Thus care should be taken to ensure that value objects do not strongly refer to their own keys, either directly or indirectly, since that will prevent the keys from being discarded.
    Right now, as long as typeCreator's class and its ClassValueMap(WeakHashMap) is not GCed, TypeTagImpl and JavaMirror will not be GCed even if there is no other place using them. As typeCreator's class can be loaded by the root class loader (e.g., it's inside a jar on the classpath), if we cache a TypeTagImpl with such TypeCreator, TypeTagImpl and JavaMirror will never be GCed.

Thanks @rednaxelafx for helping me debug this issue.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions