2

我已经看到了相当多的奇怪错误,但这一次,我完全被难住了。尝试调用同一类中的方法时出现 NullPointerException。

首先,一些代码。让我们从有问题的行开始。当然,该方法比这更长,但这是它的开始和所有相关的:

protected synchronized void checkTransfers() {
    if (isPaused())
        return;
}

isPaused是一个简单的getter方法:

protected boolean isPaused() {
    return paused.get();
}

为了完整起见:

protected AtomicBoolean paused = new AtomicBoolean(false);

现在的问题是,大约 50% 的这段代码运行时,它只是简单地抛出一个 NullPointerException 异常if (isPaused()),这对我来说毫无意义。该checkTransfers()方法与isPaused(). 我的同事尝试通过提到问题可能出在所涉及的多线程中来帮助我,例如,如果另一个线程获得了 CPU 时间并删除了它对对象的引用,但该对象永远不应该在我的代码中的任何地方丢失它的引用。另外:this一旦 NPE 触发,仍然正确定义。

堆栈跟踪如下:

main@830013674640" prio=5 可运行 java.lang.Thread.State:在 com.omines.android.communicationmanager.CommunicationManager.checkTransfers(CommunicationManager.java:125) 在 com.omines.android.communicationmanager.DownloadTask.onPostExecute(DownloadTask .java:105) 在 com.omines.android.communicationmanager.DownloadTask.onPostExecute(DownloadTask.java:20) 在 android.os.AsyncTask.finish(AsyncTask.java:602) 在 android.os.AsyncTask.access$600(AsyncTask .java:156) 在 android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java: 154) 在 android.app.ActivityThread.main(ActivityThread.java:4945) 在 java.lang.reflect.Method.invokeNative(Method.java:-1) 在 java.lang.reflect。Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)在 dalvik.system.NativeStart.main(NativeStart.java:-1)

第 125 行checkTransfers()是上面的 if 语句。

有谁知道什么会导致这样的行为?

4

1 回答 1

1

是的,它进行了一些邪恶的调试,但我似乎找到了问题所在。发布它以防以后可以帮助其他人。

首先,你需要多了解我的方法。这是完整的:

protected synchronized void checkTransfers() {
    if (isPaused())
        return;
    while (transferQueue.peek() != null && (transferQueue.peek().priority == PRIORITY_URGENT ||
            (transferSemaphore.availablePermits() > maxConcurrentTransfers)))
    {
        CommunicationTask ct = transferQueue.poll();
        if (ct != null)
        {
            if (ct instanceof DownloadTask)
                currentlyDownloading.add((DownloadTask)ct);
            ct.execute();
        }
    }
}

我发现它不会在方法开始时抛出异常。事实证明,在异常之前它会运行整个方法一次,然后调试器不会退出它,而是跳转到方法的第一行并抛出 NullPointerException。

手头有一些东西可以使用,我发现只要不是 DownloadTask 而是 UploadTask 被执行,就会发生这种情况。事实证明,我所有的 DownloadTasks 都知道他们的调用 Activity,以便他们可以显示进度对话框,但 UploadTask 总是被传递null而不是对调用者的引用。在旧版本的代码中,这很好,但在最近的一些更改之后,显然它成为了一个问题。

我仍然不确定为什么每当我的任务尝试访问对其调用活动的不存在引用时我不只是得到一个异常,但显然在看似无关的代码位中触发异常是正常行为。

感谢您花时间阅读我的问题并提供帮助。我希望至少我的回答对其他人有所帮助。

于 2013-08-19T16:30:53.323 回答