为什么在同步锁上会出现NullPointerException?

7

我有一个“简单”的同步锁块,如下所示:

private final Object screenLock = new Object();

public void Update(double deltaTime)
{
    synchronized (screenLock)
    {
        screenManager.Update(deltaTime);
    }
}

public void Draw()
{
    synchronized (screenLock)
    {
        screenManager.Draw();
    }
}

deltaTime 不是 nullscreenManager 也不是 null,所以我有点迷茫。

我知道我不应该在这么高的层级上放置锁,但无论我把锁放在哪里问题都存在。我有两个线程在运行 UpdateDraw,两个线程都有 screenLock

什么会导致锁上的 NullPointerException

跟踪:

java.lang.NullPointerException at com.dnx.manavo.ScreenManager.Update(ScreenManager.java:107) at com.dnx.manavo.ApplicationActivity.Update(ApplicationActivity.java:98) at com.dnx.manavo.GameThread.run(GameThread.java:43)


1
NullPointerException的完整堆栈跟踪是什么?您能提供一个完整的工作示例来演示NPE吗? - Jeffrey
1
@AdamBatkin deltaTime 是一个基本类型,它不能是 null - Jeffrey
1
好的,没问题。是啊,我没有仔细阅读示例代码。我的意思是,你怎么知道 screenManager 不是空的?这会导致 NPE。 - Adam Batkin
2
我可能在这里走错了方向(没什么新鲜的;)), 但是 NullPointerException 是来自于 ScreenManager.Update 而不是 ApplicationActivity.Update 方法。从你的代码示例来看,这意味着你已经通过了 synchronized 块进入了 screenManager.Update 方法? - MadProgrammer
1
@MadProgrammer -- 坏举动!!一个人不应该真的阅读异常回溯。在SO上提问要好得多。 - Hot Licks
显示剩余6条评论
2个回答

6
感谢@Adam Batkin和@MadProgrammer的帮助,我找到了在screenManager的某些部分中导致NullPointerException的问题。
我进行了一些研究,有时候NullPointerException会在同步块的开头被抛出,但实际上它是在块内抛出的。
其他原因:
  • screenLock为空
  • 同步块内的代码引发异常

你的研究是无用的。在这种情况下,堆栈跟踪清楚地显示异常是在ScreenManager.Update()而不是ApplicationActivity.Update()中引发的。仔细阅读堆栈跟踪总是值得的......以避免在调试过程中得出错误的结论。 - Stephen C
它不是在 com.dnx.manavo.GameThread.run(GameThread.java:43),而是在 ScreenManagercurrent screen 中。我确实检查了这两个地方,但无法找到抛出异常的原因,因为一个线程在实例化“current screen”之后更改了值。这是一个奇怪的情况。 - Nate-Wilkins

0

synchronized (screenLock) 上出现 NPE 的唯一可能解释是 screenlocknull

检查你正在查看的源代码是否与你实际运行的代码匹配。

另一个可能性是异常在其他地方抛出。堆栈跟踪应该告诉你异常是在哪里抛出的(除了愚蠢的情况...)。

如果这些都没有帮助,请创建一个演示问题的 SSCE 并将其添加到问题中。


@dnxviral -- 简短的、自包含的示例。 - Hot Licks

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