2013-06-04 3 views
1

В этом примере коде NullPointerException выбрасывают на линии 4.невыполнима NPE бросают (Java)

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. } 

Это происходит только иногда, но это случалось несколько раз на живом сервере, так что это не какой-то «призрачный» баг - он определенно нуждается в исправлении.


Стек след:

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

Код для 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; 
} 

Я запутался:

  • Почему мы не получаем NPE в инструкции «if» в строке 3, если это generator, что равно нулю?
  • Почему трассировка стека начинается с строки 4, а не из строки внутри doGenerate(), если это откуда исходит исключение? (Внутренности doGenerate() являются длительными и сложными - возможно, что NPE начинается здесь, но почему нет трассировки стека?)

Update:

В качестве экспериментального теста, я намеренно бросил NPE внутри doGenerate() [в среде Dev], чтобы сравнить трассировку стека с тайной живой. У этого действительно есть ожидаемая дополнительная рамка стека.

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

Среда JVM является:

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) 
+8

Не могли бы вы добавить несколько элементов в стек? –

+2

Может возникнуть ошибка ** внутри ** метода 'doGenerate()'. – Dariusz

+0

отправьте метод stacktrace и doGenerate(). – Sikorski

ответ

6

Я дам вам некоторые теоретические варианты:

  1. это может быть мирским вещь, как неправильный номер строки сообщается. Например, из-за разных версий двоичного кода и исходного кода, на который вы смотрите;
  2. Исключение может происходить где-то в другом месте, но вы видите разорванную стеклу. Это может быть связано с некоторым вмешательством в коллапс с помощью stacktrace (для этого не требуется магия, просто Java), или фреймворк регистрации иногда может испортить его;
  3. вы попадаете в реальную ошибку в JRockit, возможно, ее JIT. Например, может быть около местных жителей, очищающих, что происходит не по порядку.

Мое предложение: вставьте оператор журнала в цикл, но над вызовом doGenerate. Вы также можете явно зарегистрировать результат generator != null. Это поможет вам устранить любые, но самые причудливые объяснения.

+0

'locals clearing' - новый термин для меня - вы имеете в виду' ThreadLocal' или что-то еще? – Stewart

+0

Предположительно, отрыв трассировки стека должен быть чем-то совершенно преднамеренным. Это невозможно сделать, просто поймав и перевернув исключение, не так ли? – Stewart

+1

Нет, он обнуляет локальную переменную, чтобы позволить ее референту быть GC'd. Это может быть законным образом после последнего использования переменной. –

0

Я столкнулся с подобной проблемой. Похоже, что JUnit (или JVM) урезал stacktrace неправильно.Обертывание всего тестового метода в try/catch и использование Exception.printStackTrace() показали реальный источник NPE вместо «невозможного» местоположения.