jjzjj

android - Binder 防止垃圾回收

coder 2023-12-11 原文

我想我追踪到了内存泄漏,并想确认我认为 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/

有关android - Binder 防止垃圾回收的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  3. ruby - 防止SQL注入(inject)/好的Ruby方法 - 2

    Ruby中防止SQL注入(inject)的好方法是什么? 最佳答案 直接使用ruby?使用准备好的语句:require'mysql'db=Mysql.new('localhost','user','password','database')statement=db.prepare"SELECT*FROMtableWHEREfield=?"statement.execute'value'statement.fetchstatement.close 关于ruby-防止SQL注入(inject

  4. ruby-on-rails - 为什么 Devise/Omniauth 会向 URL 添加垃圾? - 2

    使用facebook登录后,我被重定向到/#_=_,其中显示主页。这种垃圾也出现在其他URL中,例如当注册失败并被重定向到/users/sign_in#_=_为什么会发生这种情况,我该如何解决? 最佳答案 如果你真的不想要它,一些简单的javascript就可以了:if(window.location.hash=="#_=_"){window.location.hash="";} 关于ruby-on-rails-为什么Devise/Omniauth会向URL添加垃圾?,我们在StackO

  5. ruby-on-rails - 如何防止错误 "code converter not found (UTF-8)"? - 2

    我在生产环境(CentOS5.6)中遇到此错误,但在开发环境(Ubuntu11.04)中运行良好。在这两种环境中,该应用程序都使用Ruby1.9.3和Rails3.0.9,并由passenger和nginx提供服务。我的Mechanizegem版本是2.3。未找到代码转换器(UTF-8)此代码的最后一行触发它:mech=Mechanize.newpage=mech.get("http://myurl.com/login.php?login_name=a&password=b")form=page.form_with(:name=>"loginForm")form.field_with(

  6. ruby-on-rails - ActionMailer HTML 编码 hell - 特殊字符替换为垃圾 - 2

    我有UTF-8字符串:Website•Facebook那是中间的一颗子弹又名•或0xE20x800xA2此值已正确存储在数据库中,并使用默认设置使用Rails3和ruby​​1.9.3正确显示在屏幕上。我正在尝试通过HTML电子邮件发送此邮件,但是当一切都说完之后,接收端看到的是垃圾:这背后的代码很简单,我有一个ActionMailer子类(默认使用UTF-8)设置以在布局中发送带有UTF-8内容编码的HTML电子邮件:email.html.erb布局文件:"all"%>内容使用与呈现网页相同的View,重要的一行是:我已经尝试了很多很多force_encoding的排列,e

  7. ruby - 符号的垃圾收集 Ruby 2.2.1 - 2

    所以从Ruby2.2+版本开始引入了符号垃圾回收。我在irb中编写了以下代码片段:before=Symbol.all_symbols.size#=>3331100_000.timesdo|i|"sym#{i}".to_symendSymbol.all_symbols.size#=>18835GC.startSymbol.all_symbols.size#=>3331因此,正如预期的那样,它收集了使用to_sym动态生成的所有符号。那么GC是如何知道收集哪些符号的呢?即使它们在程序中被引用,它会收集符号吗?符号垃圾回收是如何工作的?如果我创建的其中一个符号在程序中被引用,它还会收集它吗?

  8. ruby - ruby中类实例变量的垃圾回收 - 2

    如果我使用类似的方法defself.get_service_clientreturn@service_clientif!@service_client.nil?@service_client=#initializelogicend现在@service_client是一个类的实例变量。它在内存中有多长时间?只要类在内存中(即像静态变量一样),我可以指望它不会被重新初始化吗? 最佳答案 类也是Ruby中的实例,但是当您以通常的方式定义类时,它会被分配给一个常量,并且该常量会被其他常量引用,从而阻止其被收集。因此,该类将无限期地存储在内存

  9. ruby-on-rails - 防止为每个评论调用 upvote 模型 - 2

    我有三个模型:User、Comment和Upvote。User-to-Comment是一对多的关系,Comment-to-Upvote是一对多的关系,而User-to-Upvote是一对多的关系。我想做一些类似于在Stackoverflow上进行投票的事情。因此,当您投赞成票/反对票时,箭头将突出显示并保持突出显示状态,即使您在几天/几周后刷新页面或返回页面也是如此。目前我正在这样做:voted?方法在哪里:defself.voted?(user_id,comment_id)find_by(comment_id:comment_id,user_id:user_id).present?e

  10. ruby-on-rails - 使用 Unicorn + Rack 进行带外垃圾收集 - 2

    我正尝试在我的RubyonRails应用程序中运行带外垃圾收集(一旦请求完成响应)。我在config.ru中添加了以下内容:#ThisfileisusedbyRack-basedserverstostarttheapplication.require::File.expand_path('../config/environment',__FILE__)beginrequire'unicorn/oob_gc'rescueLoadError,NameErrorend#Out-of-bandGC,runsGCafterevery10threquestandaftertheresponse#h

随机推荐