安卓系统:系统何时会卸载类?

7

这是一个非常奇怪的问题。我的应用程序一直运行得很好,但如果我离开手机一两个小时而我的应用程序正在运行,当我稍后回来时,我会遇到以下错误:

java.lang.NoClassDefFoundError: yoga.database.Manager
at
yoga.YogaActivity.openDatabase(YogaActivity.java:294)
at
yoga.YogaActivity.initData(YogaActivity.java:275)
at
yoga.YogaActivity.onCreate(YogaActivity.java:102)
at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.access$2100(ActivityThread.java:116)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4203)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
at dalvik.system.NativeStart.main(Native Method)

我知道在应用程序启动时我的yoga.database.Manager类已经被加载,但是当我离开手机后,该类不知何故被系统卸载了。

Android是否会在一定时间后自动卸载类?当我的类被卸载时我该怎么办?

上述错误导致我的应用程序崩溃,但是我可以轻松地重新启动它并且它可以正常运行。

这个问题主要出现在我的HTC Magic手机上,运行Android 1.6。

2个回答

9
Dalvik虚拟机目前不支持卸载类。即使它可以这样做,也只能在与特定类加载器相关联的所有类可以一次性卸载时才能这样做,而在您的应用程序运行时,这种情况不会发生。
您需要检查logcat输出中有关此异常的错误信息。导致NoClassDefFoundError的一种方法是在涉及的类初始化期间出现故障;如果发生了这种情况,日志中可能会留下痕迹。
(当然,现在logcat输出可能已经消失了,但如果问题可重复,则下次要捕获它。)

谢谢您的输入!我会查看logcat。 - user277827
@fadden,你有关于“Dalvik虚拟机目前不会卸载类。如果它这样做,只能在与特定类加载器相关联的所有类可以一次性卸载时才能这样做”的来源/引用吗? - Pacerier
4
第一部分,我是信息来源——在那时,我主要负责Dalvik运行时(直到2011年初,也就是运行时的开发基本停止并开始专注于现在的ART)。第二部分是类加载器的工作原理。为了卸载一个类,必须没有对它的引用,但每个类都被类加载器引用,而每个类又引用它的加载器。因此,在加载器及其所加载的所有类不可达之前,垃圾回收不会丢弃它们。我没有权威的参考资料可供引用。 - fadden

2

你在使用自定义类加载器玩游戏吗?

我这么问是因为,如果yoga.YogaActivityyoga.database.Manager是同一个Android APK文件中的标准Java类,那么你不应该只有其中一个在内存中而另一个不在。我从未见过Android会单独卸载类 - 至少,在此之前我从未遇到过这个特定的问题。

另外:

我的应用程序在运行时,我离开手机一两个小时

您可能需要澄清您的意思。您是否指您将活动保持在前台?您是否指您按下HOME键,然后数小时后再回来?您是否指其他内容?


2
我遇到过类似的问题。在我的应用中,一个类有静态变量。启动应用程序后关闭屏幕一段时间后发现应用程序处于不可能的状态。具体来说,只修改了一个地方的变量“public static boolean isInitialized = false;”,为true,但却发现它仍然是false,尽管明显已经执行了true赋值。症状与保存静态类的类在长时间内被卸载并重新加载相一致,其中引用该类的活动被杀死,然后稍后重新创建。 - Mesocyclone
4
很可能你的进程被简单地终止然后重新启动了。这种情况经常发生。千万不要将静态数据成员用于除缓存或其他短暂数据之外的任何目的,这点非常重要。 - CommonsWare
2
@Arvis:就如我所写的一样,永远永远不要仅仅依赖于静态数据成员来作为缓存或者其他短暂数据的场所。对于持久化数据,请“依赖”于文件、数据库等等。 - CommonsWare
@CommonsWare 如果需要一个静态的 ThreadExecutorPoolHandler 对象怎么办? - David T.
2
@DavidT.:当进程终止时,它们也会“消失”。特别是静态线程池是一种糟糕的代码气味。 - CommonsWare
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接