Як отримати ідентифікатор мого процесу Java?
Я знаю, що існує кілька хакерських залежностей від платформи, але я вважаю за краще більш загальне рішення.
Як отримати ідентифікатор мого процесу Java?
Я знаю, що існує кілька хакерських залежностей від платформи, але я вважаю за краще більш загальне рішення.
Відповіді:
Не існує незалежного від платформи способу, який би гарантував роботу у всіх реалізаціях jvm.
ManagementFactory.getRuntimeMXBean().getName()
виглядає як найкраще (найближче) рішення. Це коротко і, ймовірно, працює в кожній реалізації в широкому використанні.
У Linux + Windows він повертає значення типу 12345@hostname
( 12345
ідентифікатор процесу). Але будьте обережні, згідно з документами , гарантій щодо цього значення немає:
Повертає ім'я, що представляє працюючу віртуальну машину Java. Повернута рядок імені може бути будь-якою довільною рядком, і реалізація віртуальної машини Java може вибрати вбудовувану корисну інформацію, що відповідає платформі, у рядок імені, що повертається. Кожна запущена віртуальна машина може мати іншу назву.
У Java 9 можна використовувати новий API процесу :
long pid = ProcessHandle.current().pid();
Ви могли використовувати JNA . На жаль, ще немає загального API JNA, щоб отримати поточний ідентифікатор процесу, але кожна платформа досить проста:
Переконайтеся, що у вас є 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
Ось метод "бекдор", який може працювати не з усіма віртуальними машинами, але повинен працювати як на 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());
У Scala:
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 boot, він / він може використовувати 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 repo; налаштувати його за допомогою Maven - трохи хитроtool.jar
, Ймовірно , містить залежний (рідна?) Код платформи , так що не легко розповсюджуванийОНОВЛЕННЯ: Я лише двічі перевірив, що JPS використовує цей спосіб, тобто бібліотеку Jvmstat (частина інструменту.jar). Тому не потрібно викликати JPS як зовнішній процес, зателефонуйте безпосередньо до бібліотеки Jvmstat, як показує мій приклад. Ви також можете отримати список усіх спільних бігу JVM на localhost таким чином. Див. Вихідний код JPS :
Я додаю це до інших рішень.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
На підставі Ashwin Jayaprakash в відповіді (+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, що повертає вам пид ява процесу.
Ось приклад:
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