Java завершает программу, не выходя из JVM

#java #jvm

#java #jvm

Вопрос:

Я хочу завершить java-процесс и освободить все ресурсы до того, как он завершит свою обычную работу, если выполняется определенное условие. Однако я не хочу выходить из JVM, поскольку у меня одновременно запущены другие Java-программы. return; Выполняет описанное выше, или есть лучший способ сделать это?

Спасибо.

Ответ №1:

На каждое запущенное Java-приложение приходится один процесс JVM. Если вы выходите из этого приложения, JVM процесса завершается. Однако это не влияет на другие процессы Java.

Комментарии:

1. Я запускаю их как службы под Debian Linux, и кажется, что если я System.exit(); закрою одну из них, остальные тоже завершат работу… Возможно, мне придется запускать их при загрузке как отдельные Java-программы.. попробую это сейчас. Спасибо за быстрый ответ. Как это return; повлияет на запущенную программу?

Ответ №2:

Вам необходимо понять механизм JVM и уточнить терминологию.

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

  • Потоки — это подразделения одновременно обрабатываемых потоков внутри процесса.

  • Процесс — это поток уровня операционной системы. ОС управляет процессами. Процесс завершается путем отправки сигнала завершения руководству операционной системы. Сигнал может быть отправлен самим процессом или другим процессом, который имеет соответствующие привилегии.

  • Внутри процесса вы можете создавать потоки уровня процесса. Потоки уровня процесса обычно поддерживаются управлением процессами операционной системы, но они инициируются процессом и завершаются процессом. Следовательно, потоки уровня процесса — это не то же самое, что процессы.

  • Приложение — это набор систем, программ и / или потоков, которые взаимодействуют в различных формах. Программа или процесс в приложении могут завершиться без завершения всего приложения.

В контексте терминологии JVM program может быть одним из следующих.

  • Программа запускается для каждого процесса JVM. Каждая программа использует один процесс JVM и вызывается путем указания пути к классу байт-кода java и указания основной точки входа, найденной в пути к классу. Когда вы завершаете программу Java, весь процесс jvm, который запускал эту программу, также завершается.

  • Программа выполняется для каждого потока уровня процесса. Например, приложение, запущенное на сервере tomcat или JEE, запускается как поток в процессе JEE. Процесс JEE сам по себе является программой, использующей один процесс JVM. Когда вы завершаете прикладную программу, процесс JEE не завершается.

Вы можете инициировать потоки уровня процесса в программе Java. Вы можете написать код, который завершает поток, но который не завершит процесс (если только это не последний и единственный запущенный поток в процессе). Сборка мусора JVM позаботится об освобождении ресурсов, и вам не нужно освобождать ресурсы самостоятельно после завершения потока уровня процесса.

Приведенный выше ответ упрощен для понимания. Пожалуйста, ознакомьтесь с дизайном ОС и потоковой обработкой, чтобы облегчить лучшее понимание процессов и механизма JVM.

Комментарии:

1. Да, кажется, мне нужно ознакомиться с архитектурой потоков / сервера и дизайном ОС в целом, — я не знал, что запуск Java-программы отдельно приведет к созданию отдельных JVM… Я бы предпочел запускать их в одной JVM, чтобы сэкономить немного оперативной памяти, но это работа на другой день. Думаю, я буду перемонтировать эти конкретные программы, когда у меня будет лучшее понимание того, как они должны работать и как я должен завершать поток (?), не завершая их все.

Ответ №3:

Если другие потоки, запущенные одновременно, не являются потоками демона, выход main не приведет к завершению работы виртуальной машины. Другие потоки продолжат выполняться.

Однако я полностью упустил суть.

Если вы запускаете каждую программу в отдельной JVM, вызов System.exit() в одной из них не повлияет на другие, это совершенно разные процессы.

Если вы запускаете их с помощью одного скрипта или чего-то еще, в зависимости от того, как он написан, что-то еще может привести к остановке других процессов. Без точной информации о том, как вы запускаете эти приложения, на самом деле невозможно сказать, что происходит.

Комментарии:

1. да, это правда, спасибо. Я не запускаю их как потоки, это отдельные программы, запускаемые как service @ boot .. кажется, что все они завершаются одновременно.. смотрите выше.

2. Они были запущены одной и той же службой (другой Java-программой) -> казалось, что все они были запущены в одной и той же JVM. Просто создал скрипт для запуска их отдельно при загрузке, и он работает, как ожидалось. Спасибо за помощь.

Ответ №4:

Ответ @ aix, вероятно, соответствует вашему вопросу. Каждый раз, когда вы выполняете java команду (или эквивалент), вы получаете другой экземпляр JVM. Вызов System.exit() в одном экземпляре JVM не приведет к завершению работы других экземпляров JVM. (Попробуйте и убедитесь!)

Возможно создать фреймворк, в котором вы запускаете несколько программ в рамках одной JVM. Действительно, это фактически то, что вы делаете, когда запускаете «bean shell». То же самое происходит, когда ваши «программы» являются сервисами (или веб-приложениями, или как вы их там называете), работающими в некоторой среде сервера приложений.

Плохая новость заключается в том, что если вы делаете подобные вещи, нет полностью надежного способа заставить отдельную «программу» исчезнуть. В частности, если программа не предназначена для совместной работы (например, если она не проверяет наличие прерываний), вам придется прибегнуть к УСТАРЕВШЕМУ Thread.stop() методу и друзьям. И эти методы могут иметь неприятные последствия для JVM и других запущенных в ней программ.

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

Комментарии:

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

2. Выполнение join() работает только в том случае, если «программа» сотрудничает; например, регулярно проверяет, не была ли она прервана.

Ответ №5:

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

Nailgun позволяет запускать то, что кажется несколькими независимыми исполнениями программы командной строки, но все они выполняются в одной и той же JVM. Поэтому не нужно переносить повторное время запуска JVM. Если это выполнение взаимодействует с глобальным состоянием, то JVM со временем будет загрязнена, и все начнет распадаться.

Drip будет использовать новую JVM для каждого выполнения, но всегда сохраняет предварительно созданную JVM с правильным путем к классам и опциями наготове. Это менее производительно, но может гарантировать корректность благодаря изоляции.