浏览以下链接:GLSurfaceView code sample
具体来说,请查看该页面第二个代码块中的以下函数:
public boolean onTouchEvent(final MotionEvent event) {
queueEvent(new Runnable() {
public void run() {
mRenderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);
}
});
return true;
}
让我感到困惑的是,anon Runnable引用了非常本地的“event”对象,但是queueEvent实际上最终在一个完全独立的线程上运行Runnable,因此很可能在“event”的特定实例很长之后很久死了,这显然是一个问题。或者情况是,在“事件”对象的引用计数上,某种local-ref-in-anon-class用法实际上是+1,这样只要anon Runnable仍在呼吸,它就会一直存在?< / p>
此外,MotionEven被宣布为final的事实是否与所有这些有关?
P.S。 作为一个相关的问题(虽然这不是我主要考虑的问题),如果不是(或者除了)“event”之外我们想要在anon类中引用一些类似“int x”的原语,那么会发生什么呢? (因为你不能+1原语的引用计数)。
答案 0 :(得分:4)
是的,Runnable
会保留对MotionEvent
的引用。在MotionEvent
可收集之前,Runnable
无法进行垃圾回收。
只能在内部类中引用final
个局部变量。
顺便说一句,不要假设使用引用计数;现在大多数垃圾收集者都不使用引用计数。
答案 1 :(得分:3)
Java不使用引用计数来进行垃圾回收。我不太清楚JVM如何实现这种闭包,但我只能假定匿名类实例包含对event
的引用。既然如此,只要匿名的Runnable是活着的,那么它引用的所有东西都是活着的(这些东西所引用的东西都是活着的等等)。
对于原始类型,它们只是直接复制到字段中。因此,只要它被引用然后被垃圾收集,就没有“引用”需要生存的东西;它们只是包含它们的对象的一部分。每次你对int 287“做一个新的引用”时,并不是存在一个存储287的地方你现在有另一个引用,你只有另一个存储单词存储287.所以无论何时287你都没关系最初是你的,取消分配,你的是完全独立的。
答案 2 :(得分:2)
如果变量被声明为final,则只能引用该变量,并且线程将保留对它的引用,从而阻止它被垃圾回收。