Подтвердить что ты не робот

Состояние сброса переменных при исключении

Мне было интересно, есть ли способ сбросить состояние всех локальных переменных, когда есть исключение, чтобы лучше понять состояние среды, вызвавшее исключение. Ниже переменной 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, также не может изменять код. Я просмотрел их, но ничего не мог найти. Тем временем я продолжу искать там тоже;)

4b9b3361

Ответ 1

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

Ответ 2

Самое простое - запустить этот код в отладчике и пройти через него. Если вы не можете отлаживать код, вы можете использовать блок 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));
}

Ответ 3

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


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

Ответ 4

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

Ответ 5

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

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

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. Вычислите подозрительный код и систематически раскомментируйте код до возникновения исключения или наоборот.

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

Ответ 6

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

https://www.takipi.com/product

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