Pergunta

Como obtenho o ID do meu processo Java?

Sei que existem vários hacks dependentes de plataforma, mas preferiria uma solução mais genérica.

Foi útil?

Solução

Não existe uma maneira independente de plataforma que possa garantir o funcionamento em todas as implementações de jvm.ManagementFactory.getRuntimeMXBean().getName() parece a melhor solução (mais próxima).É curto e provavelmente funciona em todas as implementações em amplo uso.

No linux+windows ele retorna um valor como 12345@hostname (12345 sendo o ID do processo).Cuidado com isso de acordo com os documentos, não há garantias sobre este valor:

Retorna o nome que representa a máquina virtual Java em execução.A sequência de nome retornada pode ser qualquer string arbitrária e uma implementação de máquina virtual Java pode optar por incorporar informações úteis específicas da plataforma na string de nome retornado.Cada máquina virtual em execução pode ter um nome diferente.

Em Java 9 o novo API de processo pode ser usado:

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

Outras dicas

Você poderia usar JNA.Infelizmente ainda não existe uma API JNA comum para obter o ID do processo atual, mas cada plataforma é bastante simples:

janelas

Assegure-se de ter jna-platform.jar então:

int pid = Kernel32.INSTANCE.GetCurrentProcessId();

Unix

Declarar:

private interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);   
    int getpid ();
}

Então:

int pid = CLibrary.INSTANCE.getpid();

Java 9

No Java 9, o novo API de processo pode ser usado para obter o ID do processo atual.Primeiro você pega um identificador para o processo atual e depois consulta o PID:

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

Aqui está um método backdoor que poder não funciona com todas as VMs, mas deve funcionar tanto no Linux quanto no Windows (exemplo original aqui):

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

Tentar Siga .APIs muito extensas.Licença 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();
    }

O método a seguir tenta extrair o 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;
}

Apenas ligue getProcessId("<PID>"), por exemplo.

Para JVM mais antiga, no 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";
}

Você pode conferir meu projeto: JavaSysMon no GitHub.Ele fornece identificação de processo e um monte de outras coisas (uso de CPU, uso de memória) em várias plataformas (atualmente Windows, Mac OSX, Linux e Solaris)

Desde Java 9 existe um método Process.getPid() que retorna o ID nativo de um processo:

public abstract class Process {

    ...

    public long getPid();
}

Para obter o ID do processo Java atual, pode-se usar o ProcessHandle interface:

System.out.println(ProcessHandle.current().pid());

Em Scala:

import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong

Isso deve fornecer uma solução alternativa em sistemas Unix até o lançamento do Java 9.(Eu sei, a pergunta era sobre Java, mas como não há pergunta equivalente para Scala, gostaria de deixar isso para usuários de Scala que possam se deparar com a mesma pergunta.)

Para completar, há um invólucro em Bota Primavera para o

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];

solução.Se um número inteiro for necessário, isso pode ser resumido em uma linha:

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

Se alguém já usa Spring boot, ele/ela pode usar org.springframework.boot.ApplicationPid

ApplicationPid pid = new ApplicationPid();
pid.toString();

O método toString() imprime o pid ou '???'.

Advertências sobre o uso do ManagementFactory já foram discutidas em outras respostas.

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

A última coisa que descobri é que existe um propriedade do sistema chamado sun.java.launcher.pid que está disponível pelo menos no Linux.Meu plano é usar isso e se não for encontrado usar o JMX bean.

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

Depende de onde você está procurando as informações.

Se você estiver procurando informações no console, poderá usar o comando jps.O comando fornece saída semelhante ao comando Unix ps e vem com o JDK desde que acredito 1.5

Se você está observando o processo, o RuntimeMXBean (como dito por Wouter Coekaerts) é provavelmente sua melhor escolha.A saída de getName() no Windows usando Sun JDK 1.6 u7 está no formato [PROCESS_ID]@[MACHINE_NAME].No entanto, você poderia tentar executar jps e analisar o resultado disso:

String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);

Se executado sem opções, a saída deverá ser o ID do processo seguido do nome.

Baseado em Ashwin Jayaprakash responder (+1) sobre o Apache 2.0 licenciado SIGAR, aqui está como eu uso para obter apenas o PID do processo atual:

import org.hyperic.sigar.Sigar;

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

Embora não funcione em todas as plataformas, funciona em Linux, Windows, OS X e várias plataformas Unix listadas aqui.

Este é o código que JConsole e, potencialmente, usa jps e VisualVM.Ele utiliza aulas desun.jvmstat.monitor.* pacote, 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;
    }
}

Existem algumas capturas:

  • O tool.jar é uma biblioteca distribuída com Oracle JDK, mas não com JRE!
  • Você não pode conseguir tool.jar do repositório Maven;configurá-lo com Maven é um pouco complicado
  • O tool.jar Provavelmente contém código dependente da plataforma (nativo?), Por isso não é facilmente distribuível
  • Ele é executado sob a suposição de que todos os aplicativos JVM em execução (locais) são "monitoráveis".Parece que, do Java 6, todos os aplicativos geralmente são (a menos que você configure ativamente o oposto)
  • Provavelmente funciona apenas para Java 6+
  • O Eclipse não publica a classe principal, então você não obterá o Eclipse PID facilmente bug no monitoredvmutil?

ATUALIZAR:Acabei de verificar se o JPS usa esse método, ou seja, a biblioteca Jvmstat (parte do tool.jar).Portanto, não há necessidade de chamar JPS como processo externo, chame a biblioteca Jvmstat diretamente, como mostra meu exemplo.Você também pode obter uma lista de todas as JVMs em execução no host local dessa maneira.Veja JPS Código fonte:

Podes tentar getpid() em JNR-Posix.

Ele possui um wrapper POSIX do Windows que chama getpid() da libc.

Eu sei que este é um tópico antigo, mas gostaria de salientar que a API para obter o PID (bem como outras manipulações do processo Java em tempo de execução) está sendo adicionada à classe Process no JDK 9: http://openjdk.java.net/jeps/102

Encontrei uma solução que pode ser um caso extremo e não a experimentei em outro sistema operacional além do Windows 10, mas acho que vale a pena notar.

Se você estiver trabalhando com J2V8 e nodejs, você pode executar uma função javascript simples retornando o pid do processo java.

Aqui está um exemplo:

public static void main(String[] args) {
    NodeJS nodeJS = NodeJS.createNodeJS();
    int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
    System.out.println(pid);
    nodeJS.release();
}

Adicionando a outras soluções.

com Java 10, para obter process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);

Aqui está minha solução:

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

Isso é o que usei quando tive requisitos semelhantes.Isso determina o PID do processo Java corretamente.Deixe seu código Java gerar um servidor em um número de porta predefinido e, em seguida, execute comandos do sistema operacional para descobrir o PID que está escutando na porta.Para Linux

netstat -tupln | grep portNumber
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top