Почему Java не говорит Вам, какой указатель является нулевым?

Сегодня утром на WWDC в лаборатории Swift подтвердили инженеру Apple, что на данный момент нет #pragma или его эквивалента, они считают это ошибкой, и она скоро появится, поэтому я предполагаю бета 2, Я надеюсь.

В любом случае, это уже в пути.


Xcode теперь поддерживает ориентиры // MARK :, // TODO: и // FIXME для аннотирования вашего кода и перечисления их в панели переходов

27
задан kpozin 22 July 2009 в 21:05
поделиться

6 ответов

Это потому, что разыменование всегда происходит, когда имя недоступно. Значение загружается в стек операндов, а затем передается одному из кодов операций JRE, который разыменовывает его. Однако у стека операндов нет имени, которое можно было бы связать с нулевым значением. Все, что у него есть, это «ноль». С помощью некоторого умного кода отслеживания времени выполнения можно получить имя, но это добавит накладных расходов с ограниченным значением.

Из-за этого нет опции JRE, которая включала бы дополнительную информацию для исключений с нулевым указателем.

В этом примере ссылка сохраняется в локальном слоте 1, который отображается на имя локальной переменной. Но разыменование происходит в инструкции invokevirtual, которая видит в стеке только «нулевое» значение, а затем выдает исключение:

15 aload_1
16 invokevirtual #5 

В равной степени допустима загрузка массива с последующим разыменованием, но в этом случае нет имени для сопоставления с нулевым значением, только индекс другого значения.

76 aload    5
78 iconst_0
79 aaload
80 invokevirtual #5

Вы не можете выделить имена статически для каждой инструкции - в этом примере создается много байт-кода, но вы можете видеть, что инструкция разыменования получит либо objA, либо objB, и вам нужно будет отслеживать это динамически, чтобы сообщить правильный, поскольку обе переменные передаются в одно и то же инструкция по разыменованию:

(myflag ? objA : objB).toString()
49
ответ дан 28 November 2019 в 04:46
поделиться

После JIT кода это просто математика нативного указателя, и если какой-либо указатель в нативном коде имеет значение NULL, генерируется исключение. Обратное преобразование этой сборки обратно к исходной переменной имело бы разрушительное влияние на производительность, и, учитывая, что JIT оптимизирует сгенерированный код до различных уровней, часто даже невозможно.

12
ответ дан 28 November 2019 в 04:46
поделиться

Если вы разбиваете строку на несколько строк вместо выполнения нескольких вызовов методов в одной строке,

0
ответ дан 28 November 2019 в 04:46
поделиться

Если

Номер строки недостаточно конкретен потому что оскорбительная линия часто может содержат множество переменных, которые могут вызвали ошибку.

тогда я предлагаю:

  1. Разбить эту строку на более чем одну строку и присвоить возможные NullPointerException -генерирующие значения временным переменным.
  2. Используйте отладчик и шаг для каждого вызова метода, пока вы не найдете тот, который вызывает проблему.
0
ответ дан 28 November 2019 в 04:46
поделиться

К сожалению, именно так работает Java.

Если это «ваш» код, просто добавьте фрагменты вроде

if (foo == null) {
  throw new NullPointerException("foo == null");
}

сразу после назначения foo. Если foo является параметром, проверьте сразу же в начале тела метода и вместо этого выбросите IllegalArgumentException.

Это должно помочь вам прояснить ситуацию.

0
ответ дан 28 November 2019 в 04:46
поделиться

Вы можете добавить точку останова для исключения нулевого указателя в Eclipse при отладке, чтобы узнать точную причину исключения.

0
ответ дан 28 November 2019 в 04:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: