¿Cómo obtengo la identificación de mi proceso Java?
Sé que hay varios hacks que dependen de la plataforma, pero preferiría una solución más genérica.
¿Cómo obtengo la identificación de mi proceso Java?
Sé que hay varios hacks que dependen de la plataforma, pero preferiría una solución más genérica.
Respuestas:
No existe una forma independiente de la plataforma que pueda garantizarse que funcione en todas las implementaciones de jvm.
ManagementFactory.getRuntimeMXBean().getName()
Parece la mejor solución (más cercana). Es breve, y probablemente funciona en todas las implementaciones en uso amplio.
En linux + windows devuelve un valor como 12345@hostname
( 12345
siendo el id del proceso). Sin embargo, tenga en cuenta que según los documentos , no hay garantías sobre este valor:
Devuelve el nombre que representa la máquina virtual Java en ejecución. La cadena de nombre devuelta puede ser cualquier cadena arbitraria y una implementación de máquina virtual Java puede elegir incrustar información útil específica de la plataforma en la cadena de nombre devuelta. Cada máquina virtual en ejecución podría tener un nombre diferente.
En Java 9 , se puede utilizar la nueva API de proceso :
long pid = ProcessHandle.current().pid();
Podrías usar JNA . Desafortunadamente, todavía no hay una API JNA común para obtener la ID de proceso actual, pero cada plataforma es bastante simple:
Asegúrate de tener jna-platform.jar
entonces:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Declarar:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Entonces:
int pid = CLibrary.INSTANCE.getpid();
En Java 9, la nueva API de proceso se puede utilizar para obtener la ID del proceso actual. Primero, toma un identificador del proceso actual, luego consulta el PID:
long pid = ProcessHandle.current().pid();
getpid()
solución también funciona para OS X, con una llamada JNA a la biblioteca "Sistema".
error: cannot find symbol
para jdk9
Aquí hay un método de puerta trasera que podría no funcionar con todas las máquinas virtuales, pero debería funcionar tanto en Linux como en Windows ( ejemplo original aquí ):
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
en el Objeto devuelto por jvm.get(runtime)
.
Prueba con Sigar . API muy extensas. Apache 2 licencia.
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();
}
El siguiente método intenta extraer el PID de 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;
}
Solo llame getProcessId("<PID>")
, por ejemplo.
Para JVM anteriores, en 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());
. ¿Por qué los giros extra?
getCanonicalFile()
método que convierte "self" al PID?
Puedes ver mi proyecto: JavaSysMon en GitHub. Proporciona id de proceso y un montón de otras cosas (uso de CPU, uso de memoria) multiplataforma (actualmente Windows, Mac OSX, Linux y Solaris)
Desde Java 9 hay un método Process.getPid () que devuelve la ID nativa de un proceso:
public abstract class Process {
...
public long getPid();
}
Para obtener la ID del proceso del proceso Java actual, se puede usar la ProcessHandle
interfaz:
System.out.println(ProcessHandle.current().pid());
En Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Esto debería darle una solución alternativa en los sistemas Unix hasta que se lance Java 9. (Lo sé, la pregunta era sobre Java, pero como no hay una pregunta equivalente para Scala, quería dejar esto para los usuarios de Scala que podrían tropezar con la misma pregunta).
Para completar, hay un contenedor en Spring Boot para
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
solución. Si se requiere un número entero, esto se puede resumir en una línea:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Si alguien ya usa Spring boot, él / ella puede usar org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
El método toString () imprime el pid o '???'.
Las advertencias que usan ManagementFactory ya se analizan en otras respuestas.
Lo último que he encontrado es que hay una propiedad del sistema llamada sun.java.launcher.pid
que está disponible al menos en Linux. Mi plan es usar eso y, si no se encuentra, usar el JMX bean
.
Depende de dónde esté buscando la información.
Si está buscando la información de la consola, puede usar el comando jps. El comando da una salida similar al comando Unix ps y viene con el JDK ya que creo que 1.5
Si está buscando en el proceso, RuntimeMXBean (como dijo Wouter Coekaerts) es probablemente su mejor opción. El resultado de getName () en Windows con Sun JDK 1.6 u7 tiene el formato [PROCESS_ID] @ [MACHINE_NAME]. Sin embargo, podría intentar ejecutar jps y analizar el resultado a partir de eso:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
Si se ejecuta sin opciones, la salida debería ser la identificación del proceso seguida del nombre.
Este es el código JConsole, y potencialmente utiliza jps y VisualVM. Utiliza clases de
sun.jvmstat.monitor.*
paquete, de 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;
}
}
Hay pocas capturas:
tool.jar
Es una biblioteca distribuida con Oracle JDK pero no con JRE!tool.jar
del repositorio de Maven; configurarlo con Maven es un poco complicadotool.jar
probablemente contiene código dependiente de la plataforma (nativo?) Por lo que no es fácilmente distribuiblesACTUALIZACIÓN: Acabo de comprobar que JPS usa de esta manera, es decir, la biblioteca Jvmstat (parte de tool.jar). Por lo tanto, no es necesario llamar a JPS como proceso externo, llame a la biblioteca Jvmstat directamente como lo muestra mi ejemplo. También puede obtener la lista de todas las JVM que se ejecutan en localhost de esta manera. Ver código fuente JPS :
Estoy agregando esto, a otras soluciones.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Basado en la respuesta de Ashwin Jayaprakash (+1) sobre la licencia Apache 2.0 SIGAR
, así es como lo uso para obtener solo el PID del proceso actual:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Aunque no funciona en todas las plataformas, funciona en Linux, Windows, OS X y varias plataformas Unix como se enumeran aquí .
Sé que este es un hilo antiguo, pero quería llamar a esa API para obtener el PID (así como otra manipulación del proceso Java en tiempo de ejecución) que se agrega a la clase Process en JDK 9: http: // openjdk. java.net/jeps/102
Encontré una solución que puede ser un poco marginal y no la probé en otro sistema operativo que no sea Windows 10, pero creo que vale la pena notarlo.
Si se encuentra trabajando con J2V8 y nodejs, puede ejecutar una función javascript simple que le devolverá el pid del proceso java.
Aquí hay un ejemplo:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
Aquí está mi solución:
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;
}
Esto es lo que usé cuando tenía un requisito similar. Esto determina el PID del proceso Java correctamente. Deje que su código Java genere un servidor en un número de puerto predefinido y luego ejecute comandos del sistema operativo para descubrir el PID que escucha en el puerto. Para Linux
netstat -tupln | grep portNumber
bash -c 'echo $PPID'
o las respuestas