help with weak references

91 views
Skip to first unread message

lalg...@gmail.com

unread,
Jan 4, 2016, 6:02:27 AM1/4/16
to scala-language
Weak references don't seem to be eagerly collected as the following script illustrates. Why?

---------------------
Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.ref.WeakReference
import scala.ref.WeakReference

scala> val rq = new scala.ref.ReferenceQueue[List[Int]]
rq: scala.ref.ReferenceQueue[List[Int]] = java.lang.ref.ReferenceQueue@ba2f4ec

scala> case class WR(a: List[Int]) { val wr = new WeakReference(a, rq)}
defined class WR

scala> val wr = WR((0 until 5).toList)
wr: WR = WR(List(0, 1, 2, 3, 4))

scala> val x = wr.wr.get
x: Option[List[Int]] = Some(List(0, 1, 2, 3, 4))

scala> val x = 3      // re-define x
x: Int = 3

scala>  System.gc()

scala> val x = wr.wr.get
x: Option[List[Int]] = Some(List(0, 1, 2, 3, 4))  // <<------ should have been None

scala>

Andrew Phillips

unread,
Jan 4, 2016, 7:15:21 AM1/4/16
to scala-language
scala>  System.gc()

scala> val x = wr.wr.get
x: Option[List[Int]] = Some(List(0, 1, 2, 3, 4))  // <<------ should have been None

Have you been able to observe the behaviour you're expecting with equivalent Java code? I'm asking because, from what I can see, the System.gc documentation [1] doesn't make any guarantees that weak references will be collected - or, at least, that they will have been collected when the call returns.

If you wait a while longer or add a loop to create "more garbage", does the behaviour change?

Regards

ap

Jasper-M

unread,
Jan 4, 2016, 10:08:06 AM1/4/16
to scala-language
Two things:
  - I'm not sure but I don't think redefining x is enough to convince the jvm that the first reference is unreachable,
  - val wr still refers to an object that refers to the list (the val `a` of case class WR).

Op maandag 4 januari 2016 12:02:27 UTC+1 schreef lalg...@gmail.com:

Jasper-M

unread,
Jan 4, 2016, 10:26:17 AM1/4/16
to scala-language
To illustrate my comments.

scala>  import scala.ref.WeakReference
import scala.ref.WeakReference

scala>  val rq = new scala.ref.ReferenceQueue[List[Int]]
rq: scala.ref.ReferenceQueue[List[Int]] = java.lang.ref.ReferenceQueue@2efbfe50

scala>  class WR(a: List[Int]) { val wr = new WeakReference(a, rq)}
defined class WR

scala> val wr = new WR((0 until 5).toList) //example 1
wr: WR = WR@6b931b97

scala> println(wr.wr.get)
Some(List(0, 1, 2, 3, 4))

scala> System.gc()

scala> println(wr.wr.get)
None

scala> val wr = new WR((0 until 5).toList) //example 2
wr: WR = WR@7675f36f

scala> val x = wr.wr.get
x: Option[List[Int]] = Some(List(0, 1, 2, 3, 4))

scala> val x = 3
x: Int = 3

scala> System.gc()

scala> println(wr.wr.get)
Some(List(0, 1, 2, 3, 4))

Since WR is now a normal class no reference to the list is kept and the object gets garbage collected.
In the second example it doesn't get garbage collected because x is shadowed but still exists. The JVM doesn't know that in the context of the REPL it has become unreachable.


Op maandag 4 januari 2016 16:08:06 UTC+1 schreef Jasper-M:

Oliver Ruebenacker

unread,
Jan 4, 2016, 3:49:17 PM1/4/16
to scala-l...@googlegroups.com

     Hello,

  Are weak references expected to be collected eagerly?

     Best, Oliver

--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

Rex Kerr

unread,
Jan 4, 2016, 4:16:20 PM1/4/16
to scala-l...@googlegroups.com
Weak references cleared in GC cycles, but pretty aggressively (as if they were regular garbage).  The expectation is that they're gone after a single full GC (but maybe not finalized etc). Soft references tend to hang around unless the GC isn't freeing up enough.  The precise behavior is not specified in the javadocs (save that soft references are guaranteed to be cleared before an OutOfMemory error is thrown).

  --Rex

lalg...@gmail.com

unread,
Jan 4, 2016, 9:41:50 PM1/4/16
to scala-language

Thanks for nailing this Jasper-M.

A class (versus case class) is necessary, and if one really wanted to bind variables one could use a var as in:

var x = wr.get.get
x = null
System.gc()
println(wr.get.get) // <---- prints None.

However, the above defeats having a REPL. If one were manipulating 'big-data', then the growing lexical scope from the interactive session would keep holding onto inaccessible values.

Is this a bug?

Seth Tisue

unread,
Jan 4, 2016, 10:01:53 PM1/4/16
to scala-language
On Monday, January 4, 2016 at 9:41:50 PM UTC-5, lalgeo78@... wrote:

Is this a bug?

Let's call it a missing feature. Ticket is https://issues.scala-lang.org/browse/SI-4331
Reply all
Reply to author
Forward
0 new messages