4

scala.ref.WeakReferenceで遊んでみたいと思います。しかし、大きなことを実装しようとする前に、scala コンソールで動作を確認してみたいと思います。いくつか試してみましたが、逆参照するオブジェクトを取得できませんでした。これが私の試みの1つです:

> class A
defined class A

> class B(var value: A)
defined class B

> new B(new A)
res0: B = B@c8aeb3

> new scala.ref.WeakReference(res0.value)
res1: scala.ref.WeakReference[A] = scala.ref.WeakReferenceWithWrapper@16a5d72

> res0.value = new A

> res1.get // Here I hope to get None
res3: Option[A] = Some(A@135707c)

以下の oxbow_lakes によって別の試行が行われます。

java.lang.System.gcまた、無駄にガベージ コレクターを明示的に実行しようとしました (呼び出し)。

のコンテンツを逆参照する方法はありますres1か?

4

4 に答える 4

5
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A  
defined class A

scala> class B(var value: A)
defined class B

scala> new B(new A)
res0: B = B@4223d9b

scala> new scala.ref.WeakReference(res0.value)
res1: scala.ref.WeakReference[A] = scala.ref.WeakReferenceWithWrapper@20eb607d

scala> res0.value = new A

scala> System gc

scala> res1 get
res3: Option[A] = None

ちなみに、明示的な なしでスクリプトとして実行するとSystem gc、参照も削除されません。したがって、私にとっては、これは REPL の問題ではなく、弱参照とガベージ コレクターが機能する方法にすぎません。

于 2010-12-09T15:39:38.197 に答える
1

でコードを実行すると、再割り当てした後でも参照scala -Xprint:parserの古い値を保持しているものがわかります。var

ここでは単純化して、次の 2 行のコードを実行します。

var b=1
b=2

そして、これがScalaが出力するものです:

scala> var b=1
[[syntax trees at end of parser]]// Scala source: <console>
package <empty> {
  object line2$object extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.ScalaObject {
      def <init>() = {
        super.<init>();
        ()
      };
      object $iw extends scala.ScalaObject {
        def <init>() = {
          super.<init>();
          ()
        };
        var b = 1                                ///// YOUR CODE HERE
      }
    }
  }
}

[[syntax trees at end of parser]]// Scala source: <console>
package <empty> {                                /////THIS IS AN object
                                                 /////SO PRESUMABLY IT CAN'T BE GC'ED
  object RequestResult$line2$object extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val scala_repl_value = {                 /////THIS LAZY VAL
      scala_repl_result;                          /////WILL REFERENCE THE OLD VALUE
      line2$object.$iw.$iw.b                      /////EVEN AFTER YOU REASSIGN THE var
    };
    val scala_repl_result: String = {
      line2$object.$iw.$iw;
      "".$plus("b: Int = ").$plus(scala.runtime.ScalaRunTime.stringOf(line2$object.$iw.$iw.b))
    }
  }
}

b: Int = 1

scala> b=2
[[syntax trees at end of parser]]// Scala source: <console>
package <empty> {
  object line3$object extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.ScalaObject {
      def <init>() = {
        super.<init>();
        ()
      };
      import line2$object.$iw.$iw.b;              ///// I DON'T THINK THIS (ORDINARILY ILLEGAL)
                                                  ///// import CONTRIBUTES TO THE PROBLEM
      object $iw extends scala.ScalaObject {
        def <init>() = {
          super.<init>();
          ()
        };
        b = 2;                                    /////YOUR CODE HERE
        val synthvar$0 = b
      }
    }
  }
}

[[syntax trees at end of parser]]// Scala source: <console>
package <empty> {
  object RequestResult$line3$object extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val scala_repl_value = {
      scala_repl_result;
      line3$object.$iw.$iw.synthvar$0
    };
    val scala_repl_result: String = {
      line3$object.$iw.$iw;
      "".$plus("b: Int = ").$plus(line3$object.$iw.$iw.synthvar$0).$plus("\012")
    }
  }
}

b: Int = 2

編集: Debilskiの回答に追加するには、次の解決策を使用すると、REPLが古い値への参照を保持しなくても、変数を何度でも再割り当てできると思います:

class A
class B{
   var _value:A = new A
   def value = _value
   def pleaseUpdate( closure: B => Unit ) = closure(this)
}

コンテナ オブジェクトを次のように定義します。

val b=new B

そして、その中にある変数を更新したいときはいつでも:

b.pleaseUpdate( _._value = new A )
于 2010-12-09T16:17:21.673 に答える
0

Java API ドキュメントから:

gc メソッドを呼び出すということは、Java 仮想マシンが未使用のオブジェクトをリサイクルして、現在占有しているメモリをすばやく再利用できるようにすることを示唆しています。メソッド呼び出しから制御が戻ると、Java 仮想マシンは破棄されたすべてのオブジェクトからスペースを再利用するために最善を尽くしています。

私の逸話的な経験では、これは、特に使用可能なメモリに関してプレッシャーがない場合、本当に完全なコレクションをトリガーすることはめったにないことを意味します。力を入れれば溜まる。GC が提供するよりも決定論的な動作を期待していると思います。

Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> var s = new String("Hello, world!")         
s: java.lang.String = Hello, world!

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

scala> val w = new WeakReference(s)  
w: scala.ref.WeakReference[java.lang.String] = scala.ref.WeakReferenceWithWrapper@663f3fbd

scala> s = null
s: java.lang.String = null

scala> Array.ofDim[Byte](1024*1024)
res1: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> Array.ofDim[Byte](1024*1024)
res2: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> Array.ofDim[Byte](1024*1024)
res3: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> Array.ofDim[Byte](1024*1024)
res4: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> Array.ofDim[Byte](1024*1024)
res5: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> Array.ofDim[Byte](1024*1024)
res6: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
scala> System.gc

scala> var g = w.get
g: Option[java.lang.String] = None
于 2010-12-09T15:47:19.000 に答える
0

私の考えは、 a をvar明示的に使用して に設定することでしたnull:

scala> var b = new B(new A)
b: B = B@45033fb5

scala> new scala.ref.WeakReference(b.value)
res0: scala.ref.WeakReference[A] = scala.ref.WeakReferenceWithWrapper@6a7be687

scala> b = null
b: B = null

scala> res0.get
res1: Option[A] = Some(A@79f71773)

ただし、それでも機能しません。REPL は、参照を保持しているカバーの下で処理を行っていると思われます。したがって、References の使用をテストするためにこれを使用することはお勧めしません。

于 2010-12-09T13:44:56.983 に答える