Как получить идентификатор моего Java-процесса?
Я знаю, что есть несколько зависящих от платформы хаков, но я бы предпочел более общее решение.
Как получить идентификатор моего Java-процесса?
Я знаю, что есть несколько зависящих от платформы хаков, но я бы предпочел более общее решение.
Существует не зависящий от платформы способ, который может быть гарантирован для работы во всех реализациях jvm.
ManagementFactory.getRuntimeMXBean().getName()
выглядит как лучшее (самое близкое) решение. Он короткий и, вероятно, работает в каждой реализации в широком использовании.
В linux + windows возвращается значение типа [email protected]
(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();
Вот бэкдор-метод, который может не работать со всеми виртуальными машинами, но должен работать как с linux, так и с окнами (оригинальный пример здесь):
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);
Попробуйте Sigar. очень обширные 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>")
, например.
Вы можете проверить мой проект: JavaSysMon на GitHub. Он предоставляет идентификатор процесса и кучу других вещей (использование процессора, использование памяти) кросс-платформенную (в настоящее время Windows, Mac OSX, Linux и Solaris)
Для более старых 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";
}
Так как Java 9 существует метод Process.getPid(), который возвращает собственный идентификатор процесса:
public abstract class Process {
...
public long getPid();
}
Чтобы получить идентификатор процесса текущего процесса Java, можно использовать интерфейс ProcessHandle
:
System.out.println(ProcessHandle.current().pid());
Для полноты есть оболочка Spring Boot для
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
решение. Если требуется целое число, то это можно суммировать с одним слоем:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Если кто-то использует Spring boot уже, он/он может использовать org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
Метод toString() печатает pid или '???'.
Предостережения с использованием ManagementFactory уже обсуждаются в других ответах.
public static long getPID() {
String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
if (processName != null && processName.length() > 0) {
try {
return Long.parseLong(processName.split("@")[0]);
}
catch (Exception e) {
return 0;
}
}
return 0;
}
Последнее, что я обнаружил, это системное свойство sun.java.launcher.pid
, доступное по крайней мере на linux. Мой план состоит в том, чтобы использовать это, и если он не найден, используйте JMX bean
.
В Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Это должно дать вам обходное решение для Unix-систем, пока не будет выпущена Java 9. (Я знаю, вопрос был о Java, но поскольку нет эквивалентного вопроса для Scala, я хотел оставить это для Scala пользователей, которые могли бы споткнуться в один и тот же вопрос.)
Это зависит от того, откуда вы ищете информацию.
Если вы ищете информацию с консоли, вы можете использовать команду 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);
Если запустить без параметров, то результатом должен быть идентификатор процесса, за которым следует имя.
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
Это код 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 repo; настроить его с помощью Maven немного сложноtool.jar
, вероятно, содержит зависимый от платформы (native?) код, так что это нелегко
распространяемыйUPDATE: я просто дважды проверил, что JPS использует этот путь, то есть библиотеку Jvmstat (часть tool.jar). Поэтому нет необходимости вызывать JPS в качестве внешнего процесса, вызывать библиотеку Jvmstat непосредственно, как показывает мой пример. Вы также можете получить список всех JVM runnin на localhost таким образом. См. JPS исходный код:
На основе Ashwin Jayaprakash answer (+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, перечисленных здесь.
Вы можете попробовать getpid()
в JNR-Posix.
У этого есть оболочка Windows POSIX, которая вызывает getpid() от libc.
Я знаю, что это старый поток, но я хотел назвать, что API для получения PID (а также других манипуляций с процессом Java во время выполнения) добавляется в класс Process в JDK 9: http://openjdk.java.net/jeps/102
Добавление к другим решениям.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Я нашел решение, которое может показаться немного странным, и я не пробовал его на других ОС, кроме 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