Как узнать pid программы java
если я получу объект процесса в Java через Runtime.getRuntime().exec(. ) или ProcessBuilder.start() , Я могу подождать его через Process.waitFor() , что бы Thread.join() , или я мог бы убить его Process.destroy() , что похоже на устарел Thread.stop() .
но: как найти pid объекта процесса? Я не вижу способа сделать это в Официальная Документация. Могу ли я сделать это на Java? Если да, то как?
этот парень кричит Башу, чтобы получить PID. Я не уверен, есть ли решение java для этой проблемы.
подобно другим упомянутым инструментам, есть jps инструмент командной строки, который поставляется с Java runtime. Он выплевывает PIDs всех запущенных JVMs. Благо есть выход, нужно разобрать ограничивается только процессов JVM.
Лео, изучив эту проблему около недели, я думаю, что подход Jhurtado, вероятно, является" лучшим " подходом, которым мы можем управлять на Java прямо сейчас. "лучший" в кавычках, потому что он имеет очень неприятный побочный эффект в основном быть "догадкой" о том, что ваш ребенок PID.
Если ваше Java-приложение быстро порождает собственные процессы в системе с высокой нагрузкой, нет никакой гарантии, что PID, который вы забираете в своем расчете diff, является PID процесса, запущенного текущим Поток или что PID процесса, который вы выбираете, даже был порожден нашим приложением (возможно, хост-система уже запускала этот процесс в любом случае).
Это, как говорится, если вы не нерест десятки процессов или родной процесс вы нерест действительно уникален (некоторые пользовательские util вы грузите с приложением), то этот подход отлично работает в этом случае PID собственного процесса, который вы ищете является тот, который вы хотите.
в windows вы можете использовать'список задач' как отметил Jhurtado, чтобы получить полный список PIDs и фильтр для того, который вы хотите (использование переключателя фильтра /FI не сработало для меня в тестировании).
в любой системе * nix вы можете использовать "зы топор | команда grep "где имя-это имя процесса, например "nginx" или "httpd", которое вы хотите отфильтровать, чтобы получить свой список.
кроме того, если вам нужно убить бродячие процессы (например, на выходе VM) на *nix, вы можете, конечно, использовать"убить -9 " и на Windows, интересно, что вы можете использовать 'taskkill '.
к сожалению, вряд ли оптимальный.
я столкнулся с той же проблемой, что и вы. Я нашел довольно приличное решение, я рекомендую немного поспать, прежде чем он подумал, что процесс официально запущен.
где findLastString определяется как
в основном это получит список запущенных процессов, и найти самый последний запущенный с, в этом случае, именем javaw.exe (моя программа запускала отдельный процесс java). Вы можете заменить javaw.exe с именем процесс, который вы можете найти с помощью Диспетчера задач. Вам также нужно будет получить Apache common IO jar.
Я думаю, что в Java ваш лучший выстрел, чтобы получить tasklist до и после нереста вашего дочернего процесса. Сделайте diff и получите свой PID.
вы можете получить Tasklist, выдав Runtime.getRuntime.exec("tasklist");
Обратите внимание, что tasklist.exe не входит в Windows XP Home edition, но все же вы можете скачать его.
Now I need to know the process's pid that I've just started.
No idea how to do it in Java, but in case it's your script you may modify it, so it outputs it's pid and parse it from p.getInputStream().
NOT an "exact duplicate" to the one who voted to close. That question has to do with finding the pid of the Java process itself, not a new process that the Java process spawned.
18 Answers 18
Since Java 9 class Process has new method long pid() , so it is as simple as
There is no public API for this yet. see Sun Bug 4244896, Sun Bug 4250622
As a workaround:
returns an Object of type
The Process class is abstract, and what you get back is some subclass of Process which is designed for your operating system. For example on Macs, it returns java.lang.UnixProcess which has a private field called pid . Using Reflection you can easily get the value of this field. This is admittedly a hack, but it might help. What do you need the PID for anyway?
On Windows it returns java.lang.ProcessImpl which has no notion of PID. Your solution is not cross platform unfortunately.
I don't know about the OP but I need to be able to kill and possibly restart the process at some point.
This page has the HOWTO:
Returns an instance of "java.lang.Win32Process") OR "java.lang.ProcessImpl"
Both have a private field "handle".
This is an OS handle for the process. You will have to use this + Win32 API to query PID. That page has details on how to do that.
In Unix System (Linux & Mac)
@Miha_x64 Field I guess I said that thinking that getDeclaredField() returns always the same instance (it does not). So i can't hold that statement any more
Include jna (both "JNA" and "JNA Platform") in your library and use this function:
You can also download JNA from here and JNA Platform from here.
Could you please explain what the above code does? That way any future visitors will understand. Thanks
The answer of Shamit Verma notes why it needs to be done this way. Windows doesn't give you a PID but a handle, so you need to transform the handle to PID.
I think I have found out a solution, that looks quite bulletproof while working on most platforms. Here is the idea:
- Create a JVM-wide mutex that you acquire before spawning new process/killing a process
- Use platform-dependent code to acquire list of child processes + pids of your JVM process
- Spawn new process
- Acquire new list of child processes + pids and compare with the previous list. The one that is new is your guy.
Since you check only for child processes, you cannot be wronged by some other process in the same machine. JVM-wide mutex than allows you to be sure, that the new process is the correct one.
Reading child process list is simpler than getting PID from process objects, because it does not require WIN API calls on windows, and, more importantly, it has been done already in several libs.
Below is an implementation of the above idea using JavaSysMon library. It
In my testing all IMPL classes had the field "pid". This has worked for me:
Just make sure the returned value is not -1. If it is, then parse the output of ps .
I used a non-portable approach to retrieve the UNIX PID from the Process object that is very simple to follow.
STEP 1: Use some Reflection API calls to identify the Process implementation class on the target server JRE (remember that Process is an abstract class). If your UNIX implementation is like mine, you will see an implementation class that has a property named pid that contains the PID of the process. Here is the logging code that I used.
STEP 2: Based on the implementation class and field name that you obtained from the Reflection logging, write some code to pickpocket the Process implementation class and retrieve the PID from it using the Reflection API. The code below works for me on my flavour of UNIX. You may have to adjust the EXPECTED_IMPL_CLASS_NAME and EXPECTED_PID_FIELD_NAME constants to make it work for you.
If I get a process object in Java through Runtime.getRuntime().exec(. ) , or ProcessBuilder.start() , I can wait for it through Process.waitFor() , which is like Thread.join() , or I could kill it with Process.destroy() , which is like the deprecated Thread.stop() .
BUT: How do I find the pid of the Process Object? I don't see a method for doing that in The Official Documentation. Can I do this in Java? If so, how?
5 Answers 5
This guy calls out to bash to get the PID. I'm not sure if there is an java solution to the problem.
I think this will give the pid of the JVM process. not the process spawned by Java which I believe is what the question is asking.
I think you need to read a bit closer. It spawns a process thats only job is to echo its own PID to its stdout which itself is piping to the stdin file descriptor associated with the JVM.
Vectors are old-hat, and is synchronized - no real need to use that type of collection - try using an ArrayList instead. Just saying.
Just saying what? This is not germane to the problem. The question is about accessing a PID not java best practices.
Similar to the other tools mentioned, there is the jps command line tool that comes with the Java runtime. It spits out the PIDs of all running JVMs. The benefit is the output one needs to parse is confined to only the JVM processes.
Leo, after looking into this issue for about a week myself I think Jhurtado's approach is likely the "best" approach we can manage in Java right now. "best" is in quotes because it has the very nasty side effect of basically being a "guess" at what your child PID is.
If your Java app is spawning native processes quickly in a high-load system, there is NO guarantee that the PID you pickup in your diff calculation is the PID of the Process started by the current Thread or that the PID of the process you pick was even spawned by our app (maybe the host system was already running that process anyway).
That being said, if you are not spawning dozens of processes or the native Process you are spawning is really unique (some custom util you ship with your app) then this approach works fine in which case the PID of the native process you are looking for is the one you want.
On windows you can use 'tasklist' as Jhurtado pointed out to get the full list of PIDs and filter for the one you want (using the /FI filter switch didn't work for me in testing).
Additionally, if you need to kill stray processes (for example, on VM exit) on *nix you can of course use "kill -9 " and on Windows, interestingly enough, you can use 'taskkill '.
Я знаю, что есть несколько зависящих от платформы хаков, но я бы предпочел более общее решение.
не существует независимого от платформы способа, который может быть гарантирован для работы во всех реализациях jvm. ManagementFactory.getRuntimeMXBean().getName() выглядит как лучшее (ближайшее) решение. Он короткий, и наверное работает в каждой реализации в широком использовании.
в linux+windows он возвращает значение, подобное 12345@hostname ( 12345 быть идентификатор процесса). Остерегайтесь, хотя это согласно документам, нет никаких гарантий относительно этого значения:
возвращает имя представление виртуальной машины Java. Этот возвращаемая строка имени может быть любой произвольной строкой и виртуальная Java реализация машины может выбрать для встраивания платформы конкретной полезной сведения в строке возвращаемого имени. Каждая работающая виртуальная машина может быть другое имя.
В Java 9 новая API процесса можно использовать в:
вы могли бы использовать JNA. К сожалению, пока нет общего JNA API для получения текущего идентификатора процесса, но каждая платформа довольно проста:
Windows
убедитесь, что у вас есть jna-platform.jar затем:
в Unix
под Java 9 новый API процесса может использоваться для получения текущего идентификатора процесса. Сначала вы хватаете обработайте текущий процесс, затем запросите PID:
вот метод backdoor, который может не работает со всеми VMs, но должен работать как на linux, так и на windows (оригинальный пример здесь):
попробовать сигар . очень обширные API. Лицензией Apache 2.
следующий метод пытается извлечь PID из java.lang.management.ManagementFactory :
просто позвони getProcessId("") , например.
вы можете проверить мой проект: JavaSysMon на GitHub. Он предоставляет идентификатор процесса и кучу других вещей (использование процессора, использование памяти) кросс-платформенный (в настоящее время Windows, Mac OSX, Linux и Solaris)
для старых JVM, в linux.
С Java 9 существует процесс метода.getPid (), который возвращает собственный идентификатор процесса:
получить идентификатор процесса текущего процесса Java можно использовать ProcessHandle интерфейс:
для полноты есть обертка в Весна Загрузки на
решение. Если требуется целое число, то это можно суммировать до однострочного:
Если кто-то уже использует Spring boot, он/она может использовать org.springframework.сапог.ApplicationPid
метод toString () печатает pid или '. '.
предостережения с помощью ManagementFactory обсуждаются в других ответах уже.
последнее, что я нашел, это то, что есть системное свойство под названием sun.java.launcher.pid это доступно, по крайней мере, на linux. Я планирую использовать это, и если это не использовать JMX bean .
Это должно дать вам обходной путь в системах Unix, пока Java 9 не будет выпущен. (Я знаю, вопрос был о Java, но поскольку для Scala нет эквивалентного вопроса, я хотел оставить это для пользователей Scala, которые могут наткнуться на тот же вопрос.)
Это зависит от того, где вы ищете информацию.
Если вы ищете информацию из консоли вы можете использовать команду JPS. Команда дает вывод, подобный команде Unix ps, и поставляется с JDK, так как я считаю 1.5
Если вы ищете из процесса RuntimeMXBean (как сказал Ваутер Coekaerts), вероятно, ваш лучший выбор. Выход из getName() в Windows с помощью Sun JDK 1.6 u7 находится в форме [ИДЕНТИФИКАТОР_ПРОЦЕССА]@[ИМЯ_МАШИНЫ]. Однако вы можете попытаться выполнить jps и проанализировать результат из этого:
Если выполняется без параметров, вывод должен быть идентификатором процесса, за которым следует имя.
на основе Ашвина Джаяпракаша ответ (+1) о лицензированном Apache 2.0 SIGAR , вот как я использую его, чтобы получить только PID текущего процесса:
Мне нужно найти PID текущего запущенного процесса на платформе Linux (это может быть зависимое системное решение). Java не поддерживает получение идентификатора процесса, и JRuby в настоящее время имеет ошибку с методом Ruby, Process.пид-регулятор.
есть ли другой способ получить PID?
Если у вас procfs установлен, вы можете найти идентификатор процесса через символическую ссылку /proc/self, которая указывает на каталог, имя которого является pid (здесь также есть файлы с другой соответствующей информацией, включая PID, но каталог-это все, что вам нужно в этом случае).
таким образом, с Java, вы можете сделать:
в JRuby вы можете использовать одно и то же решение:
тестируется только в Linux с помощью Sun JVM. Может не работать с другими реализациями JMX.
вы можете использовать интерфейс JNI для вызова функции POSIX getpid(). Это довольно прямолинейно. Вы начинаете с класса для функций POSIX, которые вам нужны. Я называю это POSIX.java :
скомпилировать его с
после этого вы создаете заголовочный файл POSIX.h С
файл заголовка содержит прототип C для функции с обертыванием функции getpid. Теперь вам нужно реализовать функцию, которая довольно простой. Я сделал это в POSIX.c :
теперь вы можете скомпилировать его с помощью gcc:
вы должны указать место где установлена платформа Java. Вот и все. Теперь вы можете использовать его. Создайте простую программу getpid:
скомпилировать его с javac getpid.java и запустить его:
первый pid написан оболочкой, а второй написан программой Java после того, как приглашение оболочки вернулось. ∎
Spawn процесс оболочки, который будет читать pid своего родителя. Это должно быть наш пид. Вот рабочий код, без исключения и обработка ошибок.
Это решение кажется лучшим, если PID должен быть получен только для выдачи другой команды оболочки. Достаточно обернуть команду в обратные кавычки, чтобы передать ее в качестве аргумента другой команде, например:
Это может заменить последнюю строку в массиве, заданном exec звонок.
вы можете попробовать getpid() в JNR-Posix.
Он также имеет оболочку Windows POSIX, которая вызывает getpid () от libc. Нет необходимости в JNI.
Java 9 наконец предлагает официальный способ сделать это с ProcessHandle:
сначала получает ProcessHandle ссылка для текущего процесса.
для того, чтобы получить доступ к его pid .
нет необходимости импортировать как ProcessHandle является частью java.lang .
Читайте также: