Сброс состояния переменных на Исключение - PullRequest
13 голосов
/ 20 января 2012

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

Пример:

public static void main(String[] args) {
    HashMap<Integer, String> employees = new HashMap<Integer, String>();
    employees.put(1, "James");

    Integer[] idsToDump = new Integer[] { 1, 2, 3 };
    for (Integer employeeId : idsToDump) {
        String name = employees.get(employeeId).toLowerCase();
        System.out.println(name + " is employee number: " + employeeId);
    }

}

Выход:

james is employee number: 1
Exception in thread "main" java.lang.NullPointerException

Вопрос: Есть ли какой-то аргумент JVM, который я могу передать для получения информации о текущем состоянии локальных переменных? то есть мы получаем

java.lang.NullPointerException

и (это часть, которую я ищу)

values: employeeId=2

Я хочу иметь возможность делать это на клиентском сайте, поэтому никакой доступ к Eclipse или инструментам отладки, ищущим только аргументы JVM, также не может вносить изменения в код. Я просмотрел их, но ничего не смог найти. А пока я тоже буду там искать;)

Ответы [ 6 ]

2 голосов
/ 02 мая 2015

Я наткнулся на коммерческий продукт, который делает это, просто используя параметр запуска -agentlib JVM agent.Я еще не использовал его, но собираюсь попробовать, так как он выглядит очень многообещающе.

https://www.takipi.com/product

У кого-нибудь есть опыт использования этого продукта?

2 голосов
/ 20 января 2012

Самое простое, что нужно сделать - запустить этот код в отладчике и пройти через него. Если вы не можете отладить код, вы можете использовать блок try / catch и установить employeeId вне этого, например:

int debugEmployeeId = -1;
try {
    Integer[] idsToDump = new Integer[] { 1, 2, 3 };
    for (Integer employeeId : idsToDump) {
        debugEmployeeId = employeeId;
        ...
} catch (Exception e) {
    throw new Exception("Missing employeeId = " + Integer.toString(debugEmployeeId));
}
1 голос
/ 20 января 2012

Хотя вы упомянули, что вы не можете вносить какие-либо изменения кода, здесь есть подсказка для случая, когда изменения кода все еще возможны: удобным инструментом для получения дополнительной информации об исключении является метод "printStackTrace" изброшенный объект исключения.Вы можете использовать что-то вроде этого.


try {
...
}
catch ( Exception e ) {
  System.out.println( "Exception occured! Reason: " + e.printStackTrace() );
}

1 голос
/ 20 января 2012

Учитывая все ваши ограничения, я не могу рекомендовать что-либо еще, кроме JDB. Запустите этого плохого парня и начните шаг за шагом проходить через код клиента. Я знаю, что вы сказали нет инструментов отладки, но если они не являются средой только JRE, вы должны уже установить jdb.

0 голосов
/ 20 января 2012

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

1.Учитесь читать трассировку стека при возникновении исключения. Это дает вам много информации о том, что может быть причиной исключения. Если конкретная строка, на которую указывает трассировка стека, кажется, не имеет ничего неправильного, отследите код и посмотрите, был ли это предыдущий объект, который вызывает исключение. Например (используя пример кода и методы):

Book book = null;
Bookshelf bookshelf = new Bookshelf();
bookshelf.add(book);
bookshelf.getBooks();

Нечто подобное заставит трассировку стека NPE указывать на bookshelf, но на самом деле это book вызывает NPE.

2. Распечатайте переменные, которые, как вы подозреваете, вызывают NPE.

for (Integer employeeId : idsToDump) {
  System.out.println(employeeId);
  String name = employees.get(employeeId).toLowerCase();
  System.out.println(name + " is employee number: " + employeeId);
}

Ваш вывод будет:

1
2

И тогда вы узнаете, что 2 вызывает NPE.

3.Закомментируйте подозрительный код и систематически раскомментируйте код, пока не произойдет исключение, или наоборот.

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

0 голосов
/ 20 января 2012

Лучшим вариантом, afaik, является старый ручной способ: использовать какую-либо запись в лог (будь то Log4J или просто stdout) и явно записывать интересующие вас переменные с помощью блока catch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...