Skip to content

Commit d34b9bb

Browse files
committed
fix ClassTag cache leak
JDK issues about the problem: * https://bugs.openjdk.java.net/browse/JDK-8136353
1 parent 0926d73 commit d34b9bb

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

library/src/scala/reflect/ClassTag.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package scala
1414
package reflect
1515

1616
import java.lang.{ Class => jClass }
17+
import java.lang.ref.{WeakReference => jWeakReference}
1718

1819
import scala.collection.mutable
1920
import scala.runtime.BoxedUnit
@@ -136,15 +137,15 @@ object ClassTag {
136137
val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
137138
val Null : ClassTag[scala.Null] = Manifest.Null
138139

139-
private[this] val cache = new ClassValue[ClassTag[_]] {
140-
override def computeValue(runtimeClass: jClass[_]): ClassTag[_] = {
141-
runtimeClass match {
140+
private[this] val cache = new ClassValue[jWeakReference[ClassTag[_]]] {
141+
override def computeValue(runtimeClass: jClass[_]): jWeakReference[ClassTag[_]] = {
142+
new jWeakReference(runtimeClass match {
142143
case x if x.isPrimitive => primitiveClassTag(runtimeClass)
143144
case ObjectTYPE => ClassTag.Object
144145
case NothingTYPE => ClassTag.Nothing
145146
case NullTYPE => ClassTag.Null
146147
case _ => new GenericClassTag[AnyRef](runtimeClass)
147-
}
148+
})
148149
}
149150

150151
private def primitiveClassTag[T](runtimeClass: Class[_]): ClassTag[_] = runtimeClass match {
@@ -168,7 +169,15 @@ object ClassTag {
168169
}
169170
}
170171

171-
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = cache.get(runtimeClass1).asInstanceOf[ClassTag[T]]
172+
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = {
173+
val ref = cache.get(runtimeClass1).asInstanceOf[jWeakReference[ClassTag[T]]]
174+
var tag = ref.get
175+
if (tag == null) {
176+
cache.remove(runtimeClass1)
177+
tag = cache.get(runtimeClass1).asInstanceOf[jWeakReference[ClassTag[T]]].get
178+
}
179+
tag
180+
}
172181

173182
def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass)
174183
}

0 commit comments

Comments
 (0)