Как я могу получить идентификатор моего процесса Java?
Я знаю, что есть несколько зависимых от платформы хаков, но я бы предпочел более общее решение.
Как я могу получить идентификатор моего процесса Java?
Я знаю, что есть несколько зависимых от платформы хаков, но я бы предпочел более общее решение.
Ответы:
Не существует независимого от платформы способа, который гарантированно работал бы во всех реализациях jvm.
ManagementFactory.getRuntimeMXBean().getName()
выглядит как лучшее (самое близкое) решение. Это коротко, и, вероятно, работает в каждой реализации в широком использовании.
В Linux + Windows он возвращает значение как 12345@hostname
( 12345
идентификатор процесса). Остерегайтесь, однако, в соответствии с документами , нет никаких гарантий относительно этого значения:
Возвращает имя, представляющее работающую виртуальную машину Java. Возвращенная строка имени может быть любой произвольной строкой, и реализация виртуальной машины Java может выбрать встраивание полезной информации для конкретной платформы в возвращенную строку имени. Каждая запущенная виртуальная машина может иметь свое имя.
В Java 9 может использоваться новый API процесса :
long pid = ProcessHandle.current().pid();
Вы могли бы использовать JNA . К сожалению, пока нет общего JNA API для получения текущего идентификатора процесса, но каждая платформа довольно проста:
Убедитесь, что у вас есть jna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Объявляет:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Затем:
int pid = CLibrary.INSTANCE.getpid();
В Java 9 новый API процесса может использоваться для получения текущего идентификатора процесса. Сначала вы берете дескриптор текущего процесса, затем запрашиваете PID:
long pid = ProcessHandle.current().pid();
getpid()
Решение также работает на OS X, с помощью вызова ЮНА в библиотеку «System».
error: cannot find symbol
для jdk9
Вот метод backdoor, который может не работать со всеми виртуальными машинами, но должен работать как на Linux, так и на Windows ( оригинальный пример здесь ):
java.lang.management.RuntimeMXBean runtime =
java.lang.management.ManagementFactory.getRuntimeMXBean();
java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
jvm.setAccessible(true);
sun.management.VMManagement mgmt =
(sun.management.VMManagement) jvm.get(runtime);
java.lang.reflect.Method pid_method =
mgmt.getClass().getDeclaredMethod("getProcessId");
pid_method.setAccessible(true);
int pid = (Integer) pid_method.invoke(mgmt);
getDeclaredMethod
объект, возвращенный jvm.get(runtime)
.
Попробуй Сигар . очень обширные API. Лицензия Apache 2.
private Sigar sigar;
public synchronized Sigar getSigar() {
if (sigar == null) {
sigar = new Sigar();
}
return sigar;
}
public synchronized void forceRelease() {
if (sigar != null) {
sigar.close();
sigar = null;
}
}
public long getPid() {
return getSigar().getPid();
}
Следующий метод пытается извлечь PID из java.lang.management.ManagementFactory
:
private static String getProcessId(final String fallback) {
// Note: may fail in some JVM implementations
// therefore fallback has to be provided
// something like '<pid>@<hostname>', at least in SUN / Oracle JVMs
final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
final int index = jvmName.indexOf('@');
if (index < 1) {
// part before '@' empty (index = 0) / '@' not found (index = -1)
return fallback;
}
try {
return Long.toString(Long.parseLong(jvmName.substring(0, index)));
} catch (NumberFormatException e) {
// ignore
}
return fallback;
}
Просто позвоните getProcessId("<PID>")
, например.
Для старых JVM, в Linux ...
private static String getPid() throws IOException {
byte[] bo = new byte[256];
InputStream is = new FileInputStream("/proc/self/stat");
is.read(bo);
for (int i = 0; i < bo.length; i++) {
if ((bo[i] < '0') || (bo[i] > '9')) {
return new String(bo, 0, i);
}
}
return "-1";
}
int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
. Почему лишние вращения?
getCanonicalFile()
методе, который преобразует «я» в PID?
Вы можете проверить мой проект: JavaSysMon на GitHub. Он предоставляет идентификатор процесса и кучу других вещей (использование процессора, использование памяти) кроссплатформенных (в настоящее время Windows, Mac OSX, Linux и Solaris)
Начиная с Java 9 существует метод Process.getPid (), который возвращает собственный идентификатор процесса:
public abstract class Process {
...
public long getPid();
}
Чтобы получить идентификатор текущего процесса Java, можно использовать ProcessHandle
интерфейс:
System.out.println(ProcessHandle.current().pid());
В Скала:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Это должно дать вам обходной путь в системах Unix до выпуска Java 9. (Я знаю, что вопрос был о Java, но поскольку у Scala нет аналогичного вопроса, я хотел оставить это для пользователей Scala, которые могут наткнуться на тот же вопрос.)
Для полноты в Spring Boot есть обертка для
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
решение. Если требуется целое число, то оно может быть суммировано до однострочного:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Если кто-то уже использует загрузку Spring, он / она может использовать org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
Метод toString () печатает pid или «???».
Предостережения, использующие ManagementFactory, уже обсуждались в других ответах.
Последнее я обнаружил, что есть свойство системы называется sun.java.launcher.pid
, которая доступна по крайней мере , на Linux. Мой план состоит в том, чтобы использовать это, и если не найдено, чтобы использовать JMX bean
.
Это зависит от того, откуда вы ищете информацию.
Если вы ищете информацию из консоли, вы можете использовать команду jps. Команда выводит данные, аналогичные команде Unix ps, и поставляется с JDK, так как я считаю, что 1.5
Если вы смотрите на процесс, RuntimeMXBean (как сказал Wouter Coekaerts), вероятно, ваш лучший выбор. Вывод функции getName () в Windows с использованием Sun JDK 1.6 u7 имеет вид [PROCESS_ID] @ [MACHINE_NAME]. Однако вы можете попытаться выполнить jps и проанализировать результат из этого:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
Если запустить без параметров, вывод должен быть идентификатор процесса, а затем имя.
Это код JConsole, и, возможно, JPS и VisualVM использует. Он использует классы из
sun.jvmstat.monitor.*
пакета, из tool.jar
.
package my.code.a003.process;
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
public class GetOwnPid {
public static void main(String[] args) {
new GetOwnPid().run();
}
public void run() {
System.out.println(getPid(this.getClass()));
}
public Integer getPid(Class<?> mainClass) {
MonitoredHost monitoredHost;
Set<Integer> activeVmPids;
try {
monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
activeVmPids = monitoredHost.activeVms();
MonitoredVm mvm = null;
for (Integer vmPid : activeVmPids) {
try {
mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
String mvmMainClass = MonitoredVmUtil.mainClass(mvm, true);
if (mainClass.getName().equals(mvmMainClass)) {
return vmPid;
}
} finally {
if (mvm != null) {
mvm.detach();
}
}
}
} catch (java.net.URISyntaxException e) {
throw new InternalError(e.getMessage());
} catch (MonitorException e) {
throw new InternalError(e.getMessage());
}
return null;
}
}
Есть несколько уловов:
tool.jar
библиотека, распространяемая вместе с Oracle JDK, но не JRE!tool.jar
от репозитория Maven; настроить его с Maven немного сложнееtool.jar
, Вероятно , содержит зависимый (родной?) Код платформы , так что не легко распространяемыйОБНОВЛЕНИЕ: я только что дважды проверил, что JPS использует этот способ, то есть библиотека Jvmstat (часть tool.jar). Так что нет необходимости вызывать JPS как внешний процесс, напрямую вызывать библиотеку Jvmstat, как показывает мой пример. Вы также можете получить список всех JVM, запущенных на localhost. Смотрите исходный код JPS :
Я добавляю это к другим решениям.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Основываясь на ответе Эшвина Джаяпракаша (+1) о лицензированном Apache 2.0 SIGAR
, я использую его для получения только PID текущего процесса:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Хотя он работает не на всех платформах, он работает на Linux, Windows, OS X и различных платформах Unix, как указано здесь .
Я знаю, что это старый поток, но я хотел сказать, что API для получения PID (а также другие манипуляции с процессом Java во время выполнения) добавляется в класс Process в JDK 9: http: // openjdk. java.net/jeps/102
Я нашел решение, которое может показаться немного странным, и я не пробовал его на других ОС, кроме Windows 10, но, думаю, стоит обратить на это внимание.
Если вы обнаружите, что работаете с J2V8 и nodejs, вы можете запустить простую функцию javascript, возвращающую вам pid процесса java.
Вот пример:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
Вот мое решение:
public static boolean isPIDInUse(int pid) {
try {
String s = null;
int java_pid;
RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
java_pid = Integer.parseInt(rt.getName().substring(0, rt.getName().indexOf("@")));
if (java_pid == pid) {
System.out.println("In Use\n");
return true;
}
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return false;
}
Это то, что я использовал, когда у меня было подобное требование. Это правильно определяет PID процесса Java. Позвольте вашему Java-коду порождать сервер по заранее определенному номеру порта, а затем выполнять команды ОС, чтобы выяснить PID, прослушивающий порт. Для Linux
netstat -tupln | grep portNumber