Я использовал непереносимый подход для получения UNIX PID из объекта Process
, которому очень просто следовать.
ШАГ 1. Используйте несколько вызовов API Reflection, чтобы определить Process
класс реализации на JRE целевого сервера (помните, что Process
является абстрактным классом). Если ваша реализация UNIX похожа на мою, вы увидите класс реализации, у которого есть свойство с именем pid
, которое содержит PID процесса. Вот код регистрации, который я использовал.
//--------------------------------------------------------------------
// Jim Tough - 2014-11-04
// This temporary Reflection code is used to log the name of the
// class that implements the abstract Process class on the target
// JRE, all of its 'Fields' (properties and methods) and the value
// of each field.
//
// I only care about how this behaves on our UNIX servers, so I'll
// deploy a snapshot release of this code to a QA server, run it once,
// then check the logs.
//
// TODO Remove this logging code before building final release!
final Class<?> clazz = process.getClass();
logger.info("Concrete implementation of " + Process.class.getName() +
" is: " + clazz.getName());
// Array of all fields in this class, regardless of access level
final Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
field.setAccessible(true); // allows access to non-public fields
Class<?> fieldClass = field.getType();
StringBuilder sb = new StringBuilder(field.getName());
sb.append(" | type: ");
sb.append(fieldClass.getName());
sb.append(" | value: [");
Object fieldValue = null;
try {
fieldValue = field.get(process);
sb.append(fieldValue);
sb.append("]");
} catch (Exception e) {
logger.error("Unable to get value for [" +
field.getName() + "]", e);
}
logger.info(sb.toString());
}
//--------------------------------------------------------------------
ШАГ 2: В зависимости от класса реализации и имени поля, полученного вами из журнала Reflection, напишите код, чтобы украсть класс реализации Process
и получить от него PID с помощью API Reflection. Приведенный ниже код работает для меня с моей разновидностью UNIX. Возможно, вам придется настроить константы EXPECTED_IMPL_CLASS_NAME
и EXPECTED_PID_FIELD_NAME
, чтобы он работал на вас.
/**
* Get the process id (PID) associated with a {@code Process}
* @param process {@code Process}, or null
* @return Integer containing the PID of the process; null if the
* PID could not be retrieved or if a null parameter was supplied
*/
Integer retrievePID(final Process process) {
if (process == null) {
return null;
}
//--------------------------------------------------------------------
// Jim Tough - 2014-11-04
// NON PORTABLE CODE WARNING!
// The code in this block works on the company UNIX servers, but may
// not work on *any* UNIX server. Definitely will not work on any
// Windows Server instances.
final String EXPECTED_IMPL_CLASS_NAME = "java.lang.UNIXProcess";
final String EXPECTED_PID_FIELD_NAME = "pid";
final Class<? extends Process> processImplClass = process.getClass();
if (processImplClass.getName().equals(EXPECTED_IMPL_CLASS_NAME)) {
try {
Field f = processImplClass.getDeclaredField(
EXPECTED_PID_FIELD_NAME);
f.setAccessible(true); // allows access to non-public fields
int pid = f.getInt(process);
return pid;
} catch (Exception e) {
logger.warn("Unable to get PID", e);
}
} else {
logger.warn(Process.class.getName() + " implementation was not " +
EXPECTED_IMPL_CLASS_NAME + " - cannot retrieve PID" +
" | actual type was: " + processImplClass.getName());
}
//--------------------------------------------------------------------
return null; // If PID was not retrievable, just return null
}
person
Jim Tough
schedule
04.11.2014
Process
, который он запустил - person Novaterata   schedule 28.11.2017