Android System.gc()导致从活动的第二次启动开始减速
我遇到了一个非常奇怪的现象(测试设备:HTC Desire HD,Android 2.3.5)。我知道Android System.gc()导致从活动的第二次启动开始减速,android,android-layout,garbage-collection,android-view,Android,Android Layout,Garbage Collection,Android View,我遇到了一个非常奇怪的现象(测试设备:HTC Desire HD,Android 2.3.5)。我知道System.gc()是不必要和不受鼓励的,我不想提出其他建议,但重点是它也不应该引起问题(也就是说,它最多应该是无用的) 我有一个应用程序,它的视图层次结构中包含一个GLSurfaceView。GLSurfaceView被实例化并添加到活动.onCreate()中。通常,应用程序的工作方式如下: mGameThread.pause(); // gameThread is my custom t
System.gc()
是不必要和不受鼓励的,我不想提出其他建议,但重点是它也不应该引起问题(也就是说,它最多应该是无用的)
我有一个应用程序,它的视图层次结构中包含一个GLSurfaceView
。GLSurfaceView
被实例化并添加到活动.onCreate()
中。通常,应用程序的工作方式如下:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
GLSurfaceView
设置为视图。可见
GLSurfaceView上玩内置游戏
activity.finish()
被调用)Activity.onPause()
如下所示:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
到目前为止一切正常。但是,在我将以下代码添加到onPause()
(针对用户从主菜单退出游戏的情况)后,会出现问题:
详细说明:如果活动是第一次启动的(=即应用程序进程以前不存在),则一切正常。但是,从活动的第二次开始(=第一次从主菜单退出后,即在第一次activity.finish()
)之后,GLSurfaceView的帧率降低40-50%,内置游戏变慢
如果删除System.gc()
调用,问题就会消失。此外,如果我执行以下操作,也可以解决问题:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
if (isFinishing()) {
// 1. get layout root of View hierarchy
// 2. recursively remove (detach) all Views
// 3. call GC
System.gc();
}
我没有添加具体的代码,因为它很复杂,所以我使用了注释。如果我只是通过removeView()
分离GLSurfaceView
,这是不够的。需要清除整个视图层次结构
请注意,我找不到任何内存泄漏(通过drawables/statics等没有活动泄漏)。此外,当然,当应用程序关闭时,游戏线程会正确退出(我只是没有包括它的源代码)
有什么想法吗,猜猜看?显然,System.gc()
似乎给Android的活动/布局破坏机制带来了一些问题。同样,正如我所说,如果我删除System.gc()
,问题就会消失。我有Android游戏编程的经验。我过去常常清除层次结构中的所有视图,因为在运行线程时,如果调用System.gc(),有时线程会引用一些视图,即使调用System.gc(),该视图也不会被删除,如果您一次又一次地玩这个游戏,您会注意到堆内存开始增长
这取决于内存泄漏,如果您泄漏了一些KB内存,则需要更多时间才能使游戏崩溃。使用Eclipse内存分析器(eclipsemat)
并比较堆栈的最佳方法
步骤1:
当你第一次开始游戏时,拍摄记忆快照
第二步:
在第二次开始游戏时拍摄记忆快照
第三步:
现在比较两个快照堆栈,它将告诉您区别
这是一个非常有用的工具。我在游戏中遇到了巨大的内存问题。我用这个很棒的工具修复了它们。
遵循此只是为了让它更复杂:如果我在Debug.startMethodTracing()和Debug.stopMethodTracing()之间围绕onPause()的主体“,问题消失了!也就是说,当我试图分析以发现问题时,问题消失了。您是否尝试过删除-if isFinished语句并将其移动到onDestroy?也许这很有帮助@Martijn Van Mierloo:是的,但没有帮助。我尝试了所有这些定位方法。我在某个地方读到,onDestroy()和onPause()不是清理的理想场所,因为onDestroy()保证在每次完成活动时都会被调用,它可能在下次开始活动时被调用,因此,如果will调用的是onDestroy,那么onCreate。我在Apache攻击中遇到了我。好的,清理工作的最佳位置是onStop(),所以试着把它放在那里……关于android内存管理的讨论真的很好:如果你正在清空资源,那么你应该调用System.gc()。如果调用System.gc(),可能会出现某些资源处于释放其资源之间的情况,但正如您调用System.gc()时,它的finalize()方法已被调用,因此它不会被gc收集,因为finalize()是在gc收集对象时被调用的,如果它已经被调用,它将不会被垃圾收集。我不是一个以英语为母语的人,我试着用我能用的最好的方式让你们理解。谢谢,这一点更清楚,但他们(通常)会否定什么呢?GL纹理以本机方式存储,可以通过相应的GL调用删除。那么它们是什么呢?tex-coord缓冲区和类似的东西都是纯(int)Java数组。根布局设置为空;2.GC被调用,FielalIZE()被调用,但是我们处于释放资源的中间,所以布局没有被收集;3.当GC再次尝试释放它时,finalize()将不会被调用(因为它只能调用一次),因此只有托管端会被释放,并且不会释放本机端(=本机Android surface)结果:bug出现在Desire HD(Android 2.3.5)上,而不会出现在三星Galaxy S3(Android 4.0.3)上。关于launchMode:我知道它是如何工作的。但我认为它不应该参与其中,也就是说,如果改变启动模式可以解决问题,那么它(最多)就是一个解决办法,但问题的根源在于其他地方。(可能与您所写的终结器问题有关。)