Як JVM обробляє виняток, викинутий основним методом?


10

Я розумію винятки, кидаючи їх, обробляючи їх і розповсюджуючи їх методом, розташованим нижче в стеку викликів (тобто throws).

Що я не розумію, це:

public static void main(String[] args) throws Exception {
    ...
}

Тепер я припускаю, що у випадку, коли mainвикидається Exception, JVM обробляє його (правильно?) Якщо це так, то моє питання:

Як JVM обробляє винятки, кинуті main? Що це робить?

Відповіді:


19

Ви можете подумати, що public static void mainметод на Java або mainфункція на C - це реальна точка входу вашої програми, але це не так. Усі мови високого рівня (включаючи C) мають мовне виконання, яке ініціалізує програму, а потім передає потік управління до точки входу. У випадку з Java, ініціалізація буде включати:

  • встановлення СВМ
  • завантаження необхідних класів
  • запуск статичних блоків ініціалізатора. Це може виконати визначений користувачем код, перш ніж mainбуде викликано. Ці блоки не повинні викидати винятки.

Існує найрізноманітніший спосіб реалізувати обробку винятків, але для цілей цього питання всі вони можуть розглядатися як чорна скринька. Важливо, однак, що мовна програма повинна завжди забезпечувати самий зовнішній обробник винятків, який фіксує всі винятки, які не вловлюються кодом користувача. Цей обробник винятків зазвичай роздруковує слід стека, вимикає програму впорядковано та виходить із кодом помилки. Правильне вимкнення програми включає знищення об’єктного графіка, виклик фіналізаторів та звільнення ресурсів, таких як пам'ять, ручки файлів або мережеві з'єднання.

Для ілюстрації можна зобразити час виконання, загортаючи весь код у гігантський пробний вигляд, який виглядає так

try {
    loadClasses();
    runInitializers();
    main(argv);
    System.exit(0);
} catch (Throwable e) {
    e.printStackTrace();
    System.exit(-1);
}

за винятком того, що мова не потрібна фактично виконувати такий код. Та ж семантика може бути реалізована в коді для throw(або еквівалента), який шукає перший застосовний обробник винятків.


9

Весь код Java працює в контексті потоку . Зв'язаний JavaDoc пояснює критерії обробки помилок та критерії виходу, але ось суть цього:

  • JVM відкручується і готує середовище виконання.
  • JVM створює потік, який запустить main()метод, використовуючи будь-які параметри командного рядка.
  • JVM встановлює за замовчуванням обробку виключень за замовчуванням, яка друкує виняток до стандартної помилки та припиняється.
  • JVM виконує нитку.

У випадку невиконання виключення, програма фактично гине за третім вище пунктом. Ця поведінка додатково визначена в специфікації мови Java, розділ 11.3


додаткова інформація

Інші згадували статичні блоки та способи їх виконання main(). Однак для правильного розуміння цього потрібно трохи більше пояснень.

Під час завантаження класу завантажувач класів повинен ініціалізувати всі static finalстани та запустити всі staticблоки, перш ніж клас може бути використаний, включити екземпляри екземплярів класу (вбік: створити клас Java, де константа класу ініціалізується в статичний блок після створення екземпляр класу, і конструктор посилається на константу. Бум!). Однак це все відбувається в логіці завантажувача класів, перш ніж будь-який код може посилатися на клас . Крім того, клас завантажується в будь-який потік, на який посилається клас.

Що це означає, якщо клас, що містить main()посилання іншого класу (наприклад, константа класу), тоді цей клас повинен бути завантажений перед main()виконанням, щоб включити його статичні блоки. В іншому випадку статичні блоки виконуються, як зазначено вище. Якщо клас не може завантажити, то клас, що містить main(), також не вдасться завантажити і програма припиниться.

Ще один FYI: статичні блоки можуть кинути. Errorsкидаються як є. Exceptionsзаборонені (помилка часу компіляції). RuntimeExceptionsзагортаються у ExceptionInInitializerError . Вони обробляються за оброблювачем виняткових ситуацій, яке, як правило, або знищує потік, або додаток (основний потік), якщо ви ретельно не загортаєте посилання класу (і завантажуєте) у try- catch.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.