5

我在诺基亚 S40 中收到 NullPointerException。

我想知道是什么导致了这个异常。

设备显示:

NullPointerException java/lang/NullPointerException

此错误仅发生在设备中,在模拟器中运行应用程序工作正常。

我使用microlog来调试我的应用程序。但是如果启用了日志,应用程序可以正常工作。

当我得到这个 NullPointerException 时,有没有办法获取堆栈跟踪?我不需要像行号这样的所有细节,只是哪个方法导致了这个异常。

更新:我在另一台诺基亚 S40 上安装了相同的应用程序,但没有出现相同的错误。

  • 诺基亚 2660 - 错误
  • 诺基亚 6131 - 没有错误

更新 2:不知何故,我找到了导致 NullPointerException 的原因。

    import javax.microedition.lcdui.Canvas;
    import javax.microedition.lcdui.Graphics;

    public class OuterClass extends Canvas {

    private Config config;

    public OuterClass() {
        this.config = new Config();
    }

    public void paint(Graphics graphics) {
        HelperClass helper = new HelperClass(this.config);
        helper.doStuff();
    }

    public void dispose() {
        this.config = null;
    }

    public class Config implements IConfig {
        public int getSomething() {
            // ...
        }
    }
}


 public class HelperClass {

        private IConfig config;

        public HelperClass(IConfig) {
            this.config = config;
        }

        public doStuff() {
            config.getSomething(); // Here is thrown NullPointerException
        }
    }

在某些情况下,会启动一个线程并在导致 NPE 的 helper.doStuff() 之前调用 OuterClass.dispose()。我认为当我启用日志时,它会使线程变慢,并且在我期望它被调用时调用了 helper.doStuff()。

4

4 回答 4

2

您不会找到任何方法在诺基亚 Series40 手机上保存 Thr​​owable 堆栈跟踪。

在 Series40 上调试 JavaME 应用程序的常用蛮力方法是修改代码以自己在内存中创建堆栈跟踪。

我在说的是:

  • 您可以识别的每个线程(包括系统回调线程)都需要自己的 Stack 对象,其中包含字符串。显然,这会在一定程度上增加应用程序的内存占用,但将其保留在内存中应该会限制对竞争条件的影响。

  • 当您的代码进入一个方法时,它会将方法签名添加到当前线程堆栈。当方法退出时(最好每个方法只有一个退出点),它会弹出堆栈的顶部。

  • 您可以在堆栈上添加其他调试信息,例如代码不同位置的变量值。

  • 您不一定需要将此添加到代码中的每个方法中。

  • 您可以添加try{}catch(Throwable){}到您识别的每个线程的入口点,并将堆栈转储到文件中或屏幕上(在表单中)。

显然,这不是您想要在现有大型代码库的很多地方手动添加的那种更改。但是,您可以将其作为未来组织编码标准的一部分,并编写源代码解析脚本以自动将其添加到现有代码中。

于 2009-08-14T11:42:09.993 回答
0

过去我在尝试将堆栈跟踪打印到标准输出以外的其他地方时遇到了一些麻烦。标准异常类不提供接收输出流的 printStackTrace 方法,因此它只打印到标准输出流。

至少在 Java SE 中,可以通过简单地说 System.out = 将 java 输出流重定向到其他地方。PrintStream 类接收一个 OutputStream,这意味着您可以创建自己的 ByteArrayOutputStream,初始化一个 PrintStream,将 System.out 设置为该流,然后调用 ex.printStackTrace()。我这里没有 J2ME 环境,但我相信,只要在您尝试将 System.out 设置为其他内容时它不会中断(没有说它在文档中是只读的),您应该能够做到它。

完成此操作后,我建议将其写入您专门为此而拥有的 RecordStore,然后将该 RecordStore 的记录上传到您的服务器,以便您获取它。

我知道这不是很容易,但它可能会奏效。我会首先测试 System.out 的东西。如果它有效,那么其他一切也应该有效。

我的回答是错误的。正如所指出的,System.out 和 System.err 字段被声明为 final。如果您无法获得堆栈跟踪,并且在您的模拟器上运行应用程序时无法获得错误,请尝试在您的代码(警报、日志等)上创建跟踪项目符号,以隔离代码片段问题正在发生。它必须是可以在模拟器和真实设备之间改变的东西 - 例如,与在 RecordStore 中检索/保存记录、打开连接等相关的东西......当你遇到问题时你会尝试做什么?

于 2009-08-14T04:31:13.430 回答
0

发生异常时,您可以使用 Microlog 发送电子邮件。

微日志

于 2010-05-01T21:21:32.077 回答
-2

您可以尝试在一些高级 try/catch 块中捕获异常,然后将跟踪通过电子邮件发送给自己。

于 2009-08-13T19:59:45.110 回答