【问题标题】:DeadObjectException in GMS::LocationClient (Android)GMS::LocationClient (Android) 中的 DeadObjectException
【发布时间】:2014-06-18 14:50:11
【问题描述】:

在 Android 上,我们有一个类,它封装了来自 GMS(Google 移动服务)的 LocationClient 对象。 (注意 LocationClient 实现了 com.google.android.gms.common.GooglePlayServicesClient)。

不幸的是,LocationClient 对象有抛出 DeadObjectExceptions 的习惯(例如,当我们调用 locationClient.getLastLocation() 时),我们通过多种日志记录机制检测到了这种情况。然而,奇怪的是,LocationClient 没有被记录为抛出 DeadObjectExceptions,而且我只能在它们发生 o_0 的时间的 1/40 时捕捉到所述 DeadObjectExceptions。我们没有对此问题的重现,我个人从未见过它,但是它发生在我们的大量用户中。

其他说明:

[a] “Caused by: java.lang.IllegalStateException: android.os.DeadObjectException”这行是关于什么的?这两种异常类型没有祖先-后代关系

[b] 我在 Android 论坛上发帖,但他们当然拒绝了我的帖子,认为是“错误的论坛”,而且没有 GMS 论坛,所以我完全不走运。

总而言之,问题是:GMS 触发了这个奇怪的无法捕获的异常,那么这是怎么回事,我该怎么办?

Here's a stack trace:
com.myapp.android.service.AsyncExecutionException
     at com.myapp.android.service.AsyncService$ExceptionThrower.run(MyApp:120)
     at android.os.Handler.handleCallback(Handler.java:615)
     at android.os.Handler.dispatchMessage(Handler.java:92)
     at android.os.Looper.loop(Looper.java:137)
     at android.app.ActivityThread.main(ActivityThread.java:4794)
     at java.lang.reflect.Method.invokeNative(Method.java)
     at java.lang.reflect.Method.invoke(Method.java:511)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
     at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.IllegalStateException: android.os.DeadObjectException
     at com.google.android.gms.internal.ey.getLastLocation()
     at com.google.android.gms.internal.ez.getLastLocation()
     at com.google.android.gms.location.LocationClient.getLastLocation()
     ***at com.myapp.GoogleLocationProvider.getLastLocation(MyApp:92)***
     at com.myapp.LocationProducer.getLocation(MyApp:183)
     at com.myapp.LocationProducer.getLocationHeader(MyApp:194)
     at com.myapp.API.onExecute(MyApp:344)
     ...
     at java.lang.Thread.run(Thread.java:856)
Caused by: android.os.DeadObjectException
     at android.os.BinderProxy.transact(Binder.java)
     at com.google.android.gms.internal.ex$a$a.a()
     at com.google.android.gms.internal.ey.getLastLocation()
     at com.google.android.gms.internal.ez.getLastLocation()
     ***at com.google.android.gms.location.LocationClient.getLastLocation()***
     at com.myapp.GoogleLocationProvider.getLastLocation(MyApp:92)
     at com.myapp.LocationProducer.getLocation(MyApp:183)
     at com.myapp.LocationProducer.getLocationHeader(MyApp:194)
     ...
     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
     at java.lang.Thread.run(Thread.java:856)

------------ 附录 ------------- 这是我们的实际代码。您会注意到我们总是事先检查 mLocationClient.isConnected() 是否存在,所以这不是问题。有可能我们变得非常不走运,并且 mLocationObject 在调用 isOnConnected() 和 getLastLocation() 之间死亡,但这对我来说似乎不太可能。我想我可以在通话之前、通话之间和通话后开始记录并找出答案。

LocationClient mLocationClient; // populated somewhere

public Location getLastLocation() {
    if (!mLocationClient.isConnected()) {
        return null;
    }
    Location location = null;
    try {
        location = mLocationClient.getLastLocation();
    } catch (Exception e) {
        if (!handleDeadObjectException(e)) {
            throw e;
        }
    }
    return location;
}

// logs, attempts to handle depending on user configuration
private boolean handleDeadObjectException(Exception e);

【问题讨论】:

  • 那么你有没有弄清楚,你是如何处理这个问题的??
  • 嗨,我遇到了同样的问题。你找到解决办法了吗
  • @MrMike 不。我离开了那家公司,并在另一家公司短暂地看到了这一点,但到 2015 年年中,这个问题显然对我们来说已经消失了。从那时起我就避免使用地理代码。
  • 感谢您的回复

标签: android location-client


【解决方案1】:

来自文档DeadObjectException

你调用的对象已经死掉了,因为它的宿主进程已经不存在了。

意思是,您正试图在一个不再可用的不同进程中访问一个对象。例如,如果您绑定到在不同进程中运行的服务(即 Google 移动服务),则您使用的 IBinder 是一个本地对象,它“代表”远程进程中的一个对象。当远程对象不再可用,并且您尝试使用本地 IBinder 对象时,您将得到 DeadObjectException

所以……

a] “Caused by: java.lang.IllegalStateException: android.os.DeadObjectException”这一行是关于什么的?这两种异常类型没有祖先-后代关系

这两个异常没有任何联系。 IllegalStateException 是实际异常,DeadObjectException 是根异常。

由于 gms.location.LocationClient.getLastLocation() 不想声明暴露内部实现的 throw 元素 - 使用活页夹等 - 它根本不需要。但是当 DeadObjectException 之类的异常发生时,它仍然想抛出,因此它使用运行时异常 IllegalStateException(不需要 throw 声明)。

[b] 我在 Android 论坛上发帖,但他们当然以“错误的论坛”为由拒绝了我的帖子,而且没有 GMS 论坛,所以我完全不走运。

:(

总而言之,问题是:GMS 触发了这个奇怪的无法捕获的异常,那么这是怎么回事,我该怎么办?

使用 GMS LocationClient 时,您需要在与客户端交互之前检查是否 LocationClient.isConnected()。请注意,有时 LocationClient.isConnected() 会返回 true,但在调用 LocationClient.getLastLocation() 之后仍可能抛出 java.lang.IllegalStateException: android.os。 DeadObjectException,其原因是线程问题和竞争条件,当您检查时客户端已连接,但在您实际操作之前连接丢失。

您应该做的是 a) 检查客户端是否已连接

if ( mLocationClient != null && mLocationClient.isConnected() ) {   
    mLocationClient.getLastLocation();
}

b) 捕获 IllegalStateException(而不是 DeadObjectException

if ( mLocationClient != null && mLocationClient.isConnected() ) {   
    try {
        mLocationClient.getLastLocation();
    } catch (IllegalStateException ex) {
        // This will catch the exception, handle as needed
    }
}

【讨论】:

  • 我将评论作为原始帖子的附加内容(在这里写的空间太大)。另请注意,handleDeadObjectException(Exception e) 处理所有类型的异常,并且始终有明确的逻辑来记录和小心处理 IllegalStateExceptions 和 DeadObjectExceptions,因此应该解决您的观点 (b)。我们开始认为我们需要在合理的剪辑中创建/销毁 LocationClient 对象——不要让它们存活太久,也不要在用户在活动之间颠簸时过快删除它们。切换到绑定服务可能会帮助我们做到这一点。
  • 首先,在任何情况下都应该能够捕获异常。因此,因此不应该存在任何实际崩溃的问题。其次,您是否创建多个位置客户端?也许您可以尝试只管理一个 LocationClient...
  • 对,我无法捕捉到异常,这完全是超现实的。不,我们将一个 LocationClient 创建为单例并使其永远保持活动状态,但我认为 GMS 以某种方式让它/内部的某些东西被回收,因此是 DOE。我们的想法正在转变为我们在任何给定时间仍然只创建一个位置客户端的情况,但我们确保偶尔断开它。
  • 对我来说这听起来不像是一个防弹解决方案 - 它可能会减少问题但不会解决它。定义一个位置客户端并找出异常的问题是我将从哪里开始。在没有看到实际代码的情况下,我很难确定问题所在。应该工作。
  • 顺便说一句,我们与一些 Google 代表进行了交谈,这可能是由 GooglePlayServices 内部的竞争条件引起的。
猜你喜欢
  • 2015-06-01
  • 2014-03-16
  • 1970-01-01
  • 2014-11-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2015-02-06
相关资源
最近更新 更多