#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 с правильным путем к классам и опциями наготове. Это менее производительно, но может гарантировать корректность благодаря изоляции.