Skip to content

Commit 4a24f5c

Browse files
committed
Avoid possible NPE in ClassTag cache's weak reference
1 parent d34b9bb commit 4a24f5c

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

library/src/scala/reflect/ClassTag.scala

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,19 @@ object ClassTag {
137137
val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
138138
val Null : ClassTag[scala.Null] = Manifest.Null
139139

140-
private[this] val cache = new ClassValue[jWeakReference[ClassTag[_]]] {
141-
override def computeValue(runtimeClass: jClass[_]): jWeakReference[ClassTag[_]] = {
142-
new jWeakReference(runtimeClass match {
140+
private val cacheDisabledProp = scala.sys.Prop[String]("scala.reflect.classtag.cache.disable")
141+
private[this] object cache extends ClassValue[jWeakReference[ClassTag[_]]] {
142+
override def computeValue(runtimeClass: jClass[_]): jWeakReference[ClassTag[_]] =
143+
new jWeakReference(computeTag(runtimeClass))
144+
145+
def computeTag(runtimeClass: jClass[_]): ClassTag[_] =
146+
runtimeClass match {
143147
case x if x.isPrimitive => primitiveClassTag(runtimeClass)
144148
case ObjectTYPE => ClassTag.Object
145149
case NothingTYPE => ClassTag.Nothing
146150
case NullTYPE => ClassTag.Null
147151
case _ => new GenericClassTag[AnyRef](runtimeClass)
148-
})
149-
}
152+
}
150153

151154
private def primitiveClassTag[T](runtimeClass: Class[_]): ClassTag[_] = runtimeClass match {
152155
case java.lang.Byte.TYPE => ClassTag.Byte
@@ -170,13 +173,17 @@ object ClassTag {
170173
}
171174

172175
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
176+
if (cacheDisabledProp.isSet)
177+
cache.computeTag(runtimeClass1).asInstanceOf[ClassTag[T]]
178+
else {
179+
val ref = cache.get(runtimeClass1).asInstanceOf[jWeakReference[ClassTag[T]]]
180+
var tag = ref.get
181+
if (tag == null) {
182+
cache.remove(runtimeClass1)
183+
tag = cache.computeTag(runtimeClass1).asInstanceOf[ClassTag[T]]
184+
}
185+
tag
178186
}
179-
tag
180187
}
181188

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

0 commit comments

Comments
 (0)