- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想我追踪到了内存泄漏,并想确认我认为 Android 的 Binder 是如何实现的。在这种情况下,我有一个服务和一个 Activity ,每个都在自己的进程中。我创建了一个 AIDL,它允许我通过 ipc 方法将回调对象从 Activity 传递到服务,然后在服务完成请求的任务时调用回调。
很长一段时间我都在想:如果我将一个新的回调对象传递给服务并且我没有在我的 Activity 中保留指向回调对象的指针为什么垃圾收集器不继续进行并在我的 Activity 进程中收集回调?既然这似乎没有发生,JVM 如何知道何时在我的 Activity 中垃圾收集回调。
我想答案是Binder系统在Activity进程中保留了一个指向我的Callback的指针,直到Service进程中对应的Callback对象调用了它的finalize()方法,然后发送消息给Activity释放指针。 这是正确的吗?如果不是,它是如何工作的?
我相信它会导致有趣的情况,如果 Activity 中的回调指向非常占用内存的东西,则在收集服务中的回调之前不会收集它。如果 Service 的内存不低,它可能很长时间都不会收集回调,并且回调可能会在 Activity 中累积,直到 Activity 中出现 OutOfMemoryError。
最佳答案
Yury 非常正确。
我的服务启动了一个线程来保存回调,当线程完成其工作时它调用回调并且线程结束。当回调被调用时,它可能会在我的 Activity 中做一点点工作然后返回,此时我的 Activity 进程中没有指向回调的指针。
但是,Activity 中的回调对象将继续被 Android 的绑定(bind)器系统指向,直到 Service 中相应的回调对象被垃圾回收。
如果 Activity 进程中的回调对象控制了一些消耗大量内存的其他对象,那么我就会无缘无故地浪费我的 Activity 进程中的内存,甚至可能会出现 OutOfMemoryError。 解决方案是在我的回调类中创建一个名为 destory()
的简单方法来清空所有回调的字段并在我完成回调时调用该方法。
如果回调类是一个非静态内部类,您可能需要考虑将其更改为静态内部类,并在构造函数中传入父类,这样您也可以在 中取消它destory()
方法。
这引发了一个有趣的想法,如果非静态内部回调类的父类是一个 Activity,并且在回调通过绑定(bind)器发送之后但在调用之前发生了配置更改(例如屏幕旋转)那时回调将在执行时指向一个旧的 Activity 对象!
更新:我在 Binder.java 中发现了这段代码,当然它被禁用了,但如果他们在 Javadocs 中提到这种东西就更好了。
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Binder> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
关于android - Binder 防止垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7976322/
我是 C 新手,还没有真正掌握 C 何时决定释放对象以及何时决定保留对象。 heap_t 是指向结构堆的指针。 heap_t create_heap(){ heap_t h_t = (heap
我有一个问题,我不知道如何解决。问题是: char * ary = new Char[]; ifstream fle; fle.open(1.txt, ios_base::binary); fle.s
假设我在 C# 中有字符串:“我看不到你……” 我想删除(替换为空等)这些“’”符号。 我该怎么做? 最佳答案 那个“垃圾”看起来很像有人将 UTF-8 数据解释为 ISO 8859-1 或 Wi
我无法在解析方法中更改蜘蛛设置。但这绝对是一种方式。 例如: class SomeSpider(BaseSpider): name = 'mySpider' allowed_domains
在开始之前,我们先回顾一下堆是个什么玩意,大家可能都知道,我们每天创建的Java对象几乎都存放在堆上面,所以说堆是一个巨大的对象池一点都不过分,在这个对象池里面管理者数据巨大的对象实例。 在对
我想知道为什么 printf() 在提供数组且没有格式化选项时成功打印字符数组,但在使用整数数组时编译器会抛出警告并打印垃圾值。 这是我的代码: #include int main() { c
我正在研究 Scrapy 库并尝试制作一个小爬虫。 这是爬虫的规则: rules = ( Rule(LinkExtractor(restrict_xpaths='//div[@class="w
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Printing a string to a temporary stream object in C++
这个问题在这里已经有了答案: Are WebGL objects garbage collected? (2 个答案) 关闭 3 年前。 在 WebGL 中,纹理的创建和销毁使用: WebGLTex
我继承了以下代码: (为保护无辜者更改了一些名称。) package foo.bar.baz; import javax.swing.JPanel; //Main panel in the GUI c
如果我没记错的话,在某些情况下,Java 中的 lambda 会生成为匿名类实例。例如,在这段代码中,lambda 需要从外部捕获一个变量: final int local = 123456; lis
我正在阅读托管代码中的内存泄漏,想知道是否可以在 C# 不安全代码中创建它? unsafe { while(true) new int; } 我不确定如果它作为不安全代码运行,是否会被 GC
假设我有以下用 HTML 编写的网页(仅正文部分): ... function fn() { // do stu
我想知道是否有简单的命令可以删除在 latex 编译过程中生成的所有不必要的文件,例如.aux、.log 等 最好将它链接到常规的 Latex 构建命令,这样在我点击“编译”后,垃圾文件就会被删除。
Java 在 Java7 中引入了带有字符串的 switch case。我想知道使用这样的开关盒是否会产生垃圾。 例如在我的程序中, String s = getString(); switch(s)
Cevelop将 char junk 作为“未初始化的变量”对象。在这种情况下,解决问题的正确方法是什么? friend std::ostream& operator>(std::istream&
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and t
我正在编写一个发送和接收纯文本的小型 boost asio tcp 服务器和客户端。通信或多或少是请求响应。在测试期间,我想我只是向服务器发送垃圾数据,向它发送 100.000 个请求。 客户端发
我正在使用 SAX 来读取/解析 XML 文档,并且它工作正常,除了这个特定的站点,在该站点中 eclipse 告诉我“文档元素之后的垃圾”并且我没有返回任何数据 http://www.zachblu
这是我的 Scrapy 爬虫代码。我正在尝试从网站中提取元数据值。没有元数据在一个页面上出现多次。 class MySpider(BaseSpider): name = "courses"
我是一名优秀的程序员,十分优秀!