Как программа Java может получить свой собственный идентификатор процесса?

Как получить идентификатор моего Java-процесса?

Я знаю, что есть несколько зависящих от платформы хаков, но я бы предпочел более общее решение.

Не существует независимого от платформы способа, который может быть гарантирован для работы во всех реализациях jvm. ManagementFactory.getRuntimeMXBean().getName() выглядит как лучшее (самое близкое) решение. Он короткий и, вероятно, работает в каждой реализации в широком использовании.

В linux + windows он возвращает значение, подобное [email protected] ( 12345 – идентификатор процесса). Остерегайтесь, хотя в соответствии с документами нет никаких гарантий относительно этого значения:

Возвращает имя, представляющее запущенную виртуальную машину Java. Возвращенная строка имени может быть любой произвольной строкой, а реализация виртуальной машины Java может вставлять полезную информацию, относящуюся к платформе, в возвращаемой строке имени. Каждая работающая виртуальная машина может иметь другое имя.

В Java 9 можно использовать новый API процесса :

 long pid = ProcessHandle.current().pid(); 

Вы можете использовать JNA . К сожалению, нет единого API-интерфейса JNA для получения текущего идентификатора процесса, но каждая платформа довольно проста:

Windows

Убедитесь, что у вас есть 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

В Java 9 новый API процесса может использоваться для получения текущего идентификатора процесса. Сначала вы берете дескриптор текущего процесса, затем запрашиваете PID:

 long pid = ProcessHandle.current().pid(); 

Вот бэкдор-метод, который может не работать со всеми виртуальными машинами, но должен работать как с 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); 

Попробуйте Сигара . очень обширные 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 '@', 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("") , например.

Вы можете проверить мой проект: 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 .

В Скала:

 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); 

Если запустить без параметров, то результатом должен быть идентификатор процесса, за которым следует имя.

Основываясь на ответе Ashwin Jayaprakash (+1) об лицензированном SIGAR Apache 2.0, вот как я использую его, чтобы получить только PID текущего процесса:

 import org.hyperic.sigar.Sigar; Sigar sigar = new Sigar(); long pid = sigar.getPid(); sigar.close(); 

Несмотря на то, что он не работает на всех платформах, он работает в Linux, Windows, OS X и различных платформах Unix, перечисленных здесь .

 java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0] 

Это код JConsole, и, возможно, использует jps и VisualVM. Он использует classы от sun.jvmstat.monitor.* tool.jar , from 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 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?) Код, поэтому он нелегко распределяется
  • Он исходит из предположения, что все (локальные) JVM-приложения «контролируются». Похоже, что с Java 6 все приложения обычно (если вы не настроите их на противоположную)
  • Вероятно, он работает только для Java 6+
  • Eclipse не публикует основной class, поэтому вы не получите Eclipse PID легко Ошибка в MonitoredVmUtil?

UPDATE: Я только дважды проверил, что JPS использует этот путь, то есть библиотеку Jvmstat (часть инструмента tool.jar). Поэтому нет необходимости вызывать JPS в качестве внешнего процесса, вызывать библиотеку Jvmstat непосредственно, как показывает мой пример. Вы также можете получить список всех JVM runnin на localhost таким образом. См. Исходный код JPS:

Вы можете попробовать getpid() в JNR-Posix .

У этого есть shell Windows POSIX, которая вызывает getpid () от libc.

Я знаю, что это старый stream, но я хотел бы назвать, что API для получения PID (а также других манипуляций с процессом Java во время выполнения) добавляется в class Process в JDK 9: http: // openjdk. java.net/jeps/102

Вот мое решение:

 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; } 

Добавление к другим решениям.

с Java 10, чтобы получить 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(); } 

Это то, что я использовал, когда у меня было подобное требование. Это правильно определяет PID процесса Java. Пусть ваш Java-код порождает сервер по предварительно определенному номеру порта, а затем выполняет команды ОС, чтобы узнать, что PID прослушивает порт. Для Linux

 netstat -tupln | grep portNumber 
  • Ошибка PID при запуске mysql.server?
  • Порт 80 используется SYSTEM (PID 4), что это?
  • Запустите процесс и верните его PID (как CHP.EXE) для пакетного файла
  • Как я могу перечислить все процессы, запущенные в Windows?
  • Как определить завершенный процесс Windows, если у меня все еще есть его PID?
  • Может кто-нибудь объяснить структуру Пида в Эрланге?
  • Как я могу получить PID родительского процесса моего приложения
  • получить имя процесса из идентификатора процесса (win32)
  • Linux - альтернативные места для хранения файла pid вместо / var / run
  • Как найти идентификатор процесса (pid) процесса, запущенного в java?
  • Если streamи разделяют один и тот же PID, как их можно идентифицировать?
  • Давайте будем гением компьютера.