предисловие
В написанной Java-программе иногда встречается, что JVM закрывается с помощью System.exit, а параметр состояния n включается при вызове метода выхода, т.е.System.exit(n)
. На самом деле это условное значение, если оно равно 0, это означает нормальное завершение работы, а если оно не равно 0, то это означает аварийное завершение работы. Здесь мы рассмотрим, как обрабатываются различные состояния из исходного кода JDK.
Система и среда выполнения
Сначала посмотрите на метод выхода класса System следующим образом: вы можете увидеть, что он косвенно вызывает метод выхода объекта Runtime.
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
Метод выхода Runtime выглядит следующим образом: сначала используйте SecurityManager, чтобы проверить, есть ли разрешение на закрытие JVM. Если выполнение разрешено, вызовите метод выхода Shutdown.
public void exit(int status) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkExit(status);
}
Shutdown.exit(status);
}
Shutdown
Входя в метод выхода класса Shutdown, уровень Java также имеет свое состояние состояния, которое может быть RUNNING, HOOKS и FINALIZERS.Вы можете видеть, что основная логика внутри:
- Независимо от состояния, Finalizer не выполняется, когда состояние не равно нулю.
- В состоянии RUNNING состояние изменяется на HOOKS, затем сначала выполняется метод sequence, а затем выполняется метод halt для остановки JVM.
- В состоянии FINALIZERS, когда статус не равен нулю, метод halt вызывается непосредственно для остановки JVM, а когда статус равен 0, необходимо выполнить все финализаторы, а затем вызывается метод halt для остановки JVM.
Метод sequence в основном управляет порядком выполнения хуков и финализаторов.Если состояние не HOOKS, он возвращается напрямую, затем выполняет все хуки, меняет состояние на FINALIZERS и, наконец, выполняет все финализаторы.static void exit(int status) { boolean runMoreFinalizers = false; synchronized (lock) { if (status != 0) runFinalizersOnExit = false; switch (state) { case RUNNING: state = HOOKS; break; case HOOKS: break; case FINALIZERS: if (status != 0) { halt(status); } else { runMoreFinalizers = runFinalizersOnExit; } break; } } if (runMoreFinalizers) { runAllFinalizers(); halt(status); } synchronized (Shutdown.class) { sequence(); halt(status); } }
private static void sequence() { synchronized (lock) { if (state != HOOKS) return; } runHooks(); boolean rfoe; synchronized (lock) { state = FINALIZERS; rfoe = runFinalizersOnExit; } if (rfoe) runAllFinalizers(); }
метод остановки
Выполнение JVM достигается с помощью метода остановки, затемSystem.exit(n)
Состояние n продолжает передаваться вниз, и, наконец, вызывается локальный метод halt0.
static void halt(int status) {
synchronized (haltLock) {
halt0(status);
}
}
static native void halt0(int status);
Соответствующие локальные методы следующие, в основном вызывающие функцию JVM_Halt,
JNIEXPORT void JNICALL
Java_java_lang_Shutdown_halt0(JNIEnv *env, jclass ignored, jint code)
{
JVM_Halt(code);
}
Продолжая вниз, функция JVM_Halt в основном включает функцию before_exit и функцию vm_exit. Функция before_exit в основном выполняет некоторую работу перед выходом. Она будет выполнена только один раз. В случае нескольких потоков может быть выполнена только блокировка, а другие потоки надо ждать. .
JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code))
before_exit(thread);
vm_exit(code);
JVM_END
А функция vm_exit выглядит следующим образом, код здесь по-прежнему Java-вызовSystem.exit(n)
Самое главное это функция vm_direct_exit, которая сначала отправляет уведомление о завершении работы в jvm, а затем вызывает функцию выхода для выхода, и значение состояния продолжает передаваться вниз.В это время значение состояния было передано в API операционной системы.
void vm_exit(int code) {
Thread* thread = ThreadLocalStorage::is_initialized() ?
ThreadLocalStorage::get_thread_slow() : NULL;
if (thread == NULL) {
vm_direct_exit(code);
}
if (VMThread::vm_thread() != NULL) {
VM_Exit op(code);
if (thread->is_Java_thread())
((JavaThread*)thread)->set_thread_state(_thread_in_vm);
VMThread::execute(&op); VM Thread.
vm_direct_exit(code);
} else {
vm_direct_exit(code);
}
ShouldNotReachHere();
}
void vm_direct_exit(int code) {
notify_vm_shutdown();
os::wait_for_keypress_at_exit();
::exit(code);
}
Суммировать
Код состояния Java System.exit(n) в конечном итоге передается API операционной системы, поэтому его значение связано со значением API операционной системы. этот процесс. Можно сказать, что большинство платформ могут напрямую вернуться, чтобы выйти из программы в основной функции, но некоторые платформы не могут этого сделать, поэтому вам нужно использовать exit() для выхода для совместимости.
Ниже приведенырекламироватьа такжеСвязанное Чтение
========Время рекламы========
Моя новая книга «Анализ дизайна ядра Tomcat» продана на Jingdong, нуждающиеся друзья могут обратиться кitem.JD.com/12185360.Контракт…Зарезервировать. Спасибо друзья.
Зачем писать «Анализ проектирования ядра Tomcat»
=========================
Связанное чтение:
Объект с точки зрения исходного кода JDK
Долго с точки зрения исходного кода JDK
Плавающие с точки зрения исходного кода JDK
Целое число с точки зрения исходного кода JDK
Достаточно ли изменчив, чтобы гарантировать синхронизацию данных?
Разговор об основных типах данных Java
Оптимизация одновременных блокировок с точки зрения исходного кода JDK
Блокировка и пробуждение потоков с точки зрения исходного кода JDK
С точки зрения исходного кода JDK тайм-аут параллельной конкуренции
Прерывание параллельных потоков Java с точки зрения исходного кода JDK
Справедливость параллелизма Java с точки зрения исходного кода JDK
Как обеспечить атомарность параллелизма Java с точки зрения исходного кода JDK
Байт с точки зрения исходного кода JDK
Логическое значение с точки зрения исходного кода JDK
Кратко с точки зрения исходного кода JDK
Подписывайтесь и награждайте: