(Неизвестный источник) в трассировке стека исключений - PullRequest
49 голосов
/ 28 июня 2010

Фон

Этот вопрос относится к Почему String.valueOf (null) генерирует исключение NullPointerException?

Рассмотрим следующий фрагмент:

public class StringValueOfNull {
    public static void main(String[] args) {
        String.valueOf(null);

        // programmer intention is to invoke valueOf(Object), but instead
        // code invokes valueOf(char[]) and throws NullPointerException
    }
}

Как объяснено в ответе на связанный вопрос, перегрузка метода Java разрешает приведенный выше вызов в String.valueOf(char[]), что справедливо приводит к NullPointerException во время выполнения.

Скомпилировано в Eclipse и javac 1.6.0_17, это трассировка стека:

Exception in thread "main" java.lang.NullPointerException
        at java.lang.String.<init>(Unknown Source)
        at java.lang.String.valueOf(Unknown Source)
        at StringValueOfNull.main(StringValueOfNull.java:3)

Обратите внимание, что в трассировке стека выше отсутствует KEY информация: НЕ имеет полную сигнатуру valueOf метода!Он просто говорит String.valueOf(Unknown Source)!

В большинстве ситуаций, с которыми я сталкивался, трассировки стека исключений всегда имеют полную сигнатуру методов, которые на самом деле находятся в трассировке стека, что, конечно, очень полезно в немедленной идентификации проблемы и основной причине, по которой трассировка стека (которую, разумеется, довольно дорого построить) предоставляется в первую очередь.

И, тем не менее, в этом случае трассировка стека вообще не помогает .Он с треском провалился, помогая программисту идентифицировать проблему.

Таким образом, я вижу 3 способа, которыми программист может идентифицировать проблему с помощью приведенного выше фрагмента:

  • Программист осознает, чтоего / ее собственное, что метод перегружен, и по правилу разрешения в этом случае вызывается «неправильная» перегрузка
  • Программист использует хорошую IDE, которая позволяет ему / ей быстро видеть, какой метод выбран
    • Например, в Eclipse при наведении указателя мыши на вышеупомянутое выражение программист быстро сообщает, что String valueOf(char[] data) действительно выбрано
  • Программист проверяет байт-код (тьфу!)

Последний вариант, вероятно, наименее доступен, но, конечно же, это Ultimate Answer (программист может неправильно понять правило перегрузки, IDE может содержать ошибки, но байт-коды всегда (?) Говорят правду о том, чтоделается).


Вопросы

  • Почему трассировка стека так неинформативна в этом случае в отношениисигнатуры методов, которые на самом деле находятся в трассировке стека?
    • Это из-за компилятора?Время выполнения?Что-то еще?
  • В каких других (редких?) Сценариях трассировка стека может не захватить важную информацию, подобную этой?

Ответы [ 6 ]

99 голосов
/ 29 декабря 2011

Обратите внимание, что если вы используете Ant build и если для атрибута debug установлено значение false в команде javac, это может произойти.

ex: если вам нужно правильное расположение в наборе трассировки debug = true в сборке Ant,

    <javac verbose="false" srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.java">
        <classpath refid="compile.classpath" />
    </javac>
29 голосов
/ 28 июня 2010

Обычно это связано с отсутствием отладочной информации.Вы, вероятно, используете JRE (не JDK), который не включает отладочную информацию для классов rt.jar.Попробуйте использовать полный JDK, вы получите правильные места в трассировке стека:

Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at StringValueOfNull.main(StringValueOfNull.java:3)
6 голосов
/ 20 февраля 2014

У меня была такая же проблема, я использую spring и apache ant для непрерывной интеграции.

Ошибка, которая была у меня в файле build.xml.

Журнал смены пола с более точным содержанием был:

build.xml с ошибкой:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes">
        <classpath refid="compile.classpath" />
    </javac>

build.xml без ошибок:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes"  debug="true">
        <classpath refid="compile.classpath" />
    </javac>

Внутри структуры мне не хватало смелости debug = "true"

3 голосов
/ 28 июня 2010

Я запустил код в Eclipse и получил следующий вывод:

public class Aloof {
    public static void main(String[] args) {
        String.valueOf(null);
    }
}

Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at mysql.Aloof.main(Aloof.java:19)

Если вы включите полный исходный код (из JDK), вы можете отладить строку 177 в String.java

1 голос
/ 13 мая 2014

В Eclipse: «Настройки»> «Java»> «Установленные JRE». Проверенная запись должна иметь путь внутри JDK, например, C: \ Program Files (x86) \ Java \ jdk1.7.0_55 \ jre.

1 голос
/ 28 июня 2010

Это происходит, когда в источнике нет отладочной (строковой) информации или виртуальной машине предписано выбрасывать эту информацию во время загрузки класса.Поскольку у вас есть несколько номеров строк, это не настройка виртуальной машины, а в классе String отсутствует отладочная информация.

...