#java #linux #pid #isalive #processhandle
Вопрос:
У меня есть два метода Java 11, которые проверяют, запущен ли процесс для данного PID:
public static final boolean isProcessRunning( final long pid ) {
Optional< ProcessHandle > optionalProcess = ProcessHandle.of( pid );
return optionalProcess.isPresent() amp;amp; optionalProcess.get().isAlive();
}
public static boolean isProcessRunning2( final long pid ) {
return ProcessHandle.allProcesses()
.filter( p -> p.pid() == pid )
.anyMatch( p -> p.isAlive() );
}
При проверке нескольких PID на клиентах Linux я иногда получаю разные результаты для определенных PID, где первая реализация всегда возвращается true
, а вторая всегда false
.
Проверка некоторых «ложных срабатываний» с помощью команды оболочки ps -ef | grep <pid>
показывает, что первая реализация кажется неправильной, ОС также не знает об этих процессах. Предположительно, вторая реализация всегда верна, но кажется очень неэффективной.
Что не так с первой реализацией и как я могу это исправить?
Ответ №1:
Взглянув на реализацию ProcessHandleImpl.isAlive()
(версия Java 11), кажется, что этот метод может вернуться true
, если собственный метод isAlive0(pid)
возвращает 0, что он и делает, «если время начала не может быть определено». Тот же собственный метод также используется для определения того, следует ли возвращать пустое необязательное значение (возвращает -1) или нет (возвращает 0 или фактическое время начала). ProcessHandle.allProcesses()
с другой стороны, получает все дочерние значения pid 0, а затем вызывает getProcessPids0(...)
(другой собственный метод), чтобы вернуть pid и время начала.
Таким образом, похоже, что это разница в машинном коде используемой вами JVM — или в вашей операционной системе (зависит от того, что делает машинный код).
Чтобы «исправить» свой первый фрагмент, вы можете исключить время начала «0» с помощью info().startInstant().isPresent()
:
public static final boolean isProcessRunning( final long pid, final boolean excludeUnsure ) {
Optional< ProcessHandle > optionalProcess = ProcessHandle.of( pid );
if( excludeUnsure ) {
return optionalProcess.map(ph -> ph.info())
.flatMap(info -> info.startInstant())
.isPresent();
} else {
return optionalProcess.map(ph -> ph.isAlive()).orElse(Boolean.FALSE);
}
}