Impossible NPE being thrown (java)

孤人 提交于 2019-12-14 02:21:37

问题


In this example code a NullPointerException is being thrown on line 4.

1. private <O,T> void generate(Suggestion suggestion, GeneratorFactory<O, T> generatorFactory) {
2.     final Generator<O, T> generator = generatorFactory.getGenerator(suggestion);
3.     while (generator.hasNext()) {
4.         generator.doGenerate();
5.     }
6.     // post-generate stuff here
7. }

It only happens occasionally, but it has happened a few times on a live server, so it's not some kind of "ghost" bug - it definitely needs fixing.


Stack trace:

java.lang.NullPointerException
    at package.SuggestionServiceImpl.generate(SuggestionServiceImpl.java:4)

Code for GeneratoryFactory:

@Override
public synchronized Generator<O, T> getGenerator(final Suggestion suggestion) {
    Generator<O, T> generator = generators.get(suggestion.getId());
    if (generator == null) {
        generator = construct(suggestion); // calls `new Generator()`
        generators.put(suggestion.getId(), generator);
    }
    return generator;
}

I'm confused by:

  • How come we don't get a NPE in the 'if' statement on line 3, if it's generator that's null?
  • How come the stack trace starts at line 4, and not from a line inside doGenerate() if that's where the exception is coming from? (The internals of doGenerate() are lengthy and complex - it is possible that an NPE starts here, but why no stack trace?)

Update:

As an experimental test, I deliberately threw a NPE inside doGenerate() [in dev environment] to compare the stack trace with the mystery live one. It does indeed have the anticipated extra stack frame.

java.lang.NullPointerException: DELIBERATE TEST EXCEPTION
    at package.Generator.doGenerate(Generator.java:71)
    at package.SuggestionServiceImpl.generate(SuggestionServiceImpl.java:4)

The runtime JVM is:

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Oracle JRockit(R) (build R28.1.4-7-144370-1.6.0_26-20110617-2130-linux-x86_64, compiled mode)

回答1:


I'll give you some theoretical options:

  1. it may be a mundane thing like a wrong line number reported. For example, due to different versions of binary code and the source code you are looking at;
  2. the exception may be happening somewhere else, but you see a severed stacktrace. This could be due to some intervenening code messing with the stacktrace (no magic neededed for this, just plain Java), or the logging framework may be messing it up occasionally;
  3. you are hitting an actual bug in JRockit, possibly its JIT. For example, there may be some locals clearing in effect which happens out of order.

My suggestion: insert a log statement within the loop, but above the doGenerate call. You may also explicitly log the result of generator != null. This will help you eliminate any but the most bizarre explanation.




回答2:


I have encountered similar issue. It looks like JUnit (or JVM) truncated stacktrace in wrong way. Wrapping whole test method in try/catch and using Exception.printStackTrace() showed the real source of NPE instead of "impossible" location.



来源:https://stackoverflow.com/questions/16913295/impossible-npe-being-thrown-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!