Como obtenho o ID do meu processo Java?
Eu sei que existem vários hacks dependentes da plataforma, mas eu preferiria uma solução mais genérica.
Como obtenho o ID do meu processo Java?
Eu sei que existem vários hacks dependentes da plataforma, mas eu preferiria uma solução mais genérica.
Respostas:
Não existe uma maneira independente de plataforma que possa garantir que funcione em todas as implementações da jvm.
ManagementFactory.getRuntimeMXBean().getName()
parece a melhor solução (mais próxima). É curto e provavelmente funciona em todas as implementações de uso amplo.
No linux + windows, ele retorna um valor como 12345@hostname
( 12345
sendo o ID do processo). Cuidado, porém, de acordo com os documentos , não há garantias sobre esse valor:
Retorna o nome que representa a Java virtual machine em execução. A cadeia de nome retornada pode ser qualquer cadeia arbitrária e uma implementação da máquina virtual Java pode optar por incorporar informações úteis específicas da plataforma na cadeia de nome retornada. Cada máquina virtual em execução pode ter um nome diferente.
No Java 9, a nova API de processo pode ser usada:
long pid = ProcessHandle.current().pid();
Você poderia usar o JNA . Infelizmente, ainda não existe uma API JNA comum para obter o ID do processo atual, mas cada plataforma é bastante simples:
Certifique-se de ter jna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Declarar:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Então:
int pid = CLibrary.INSTANCE.getpid();
No Java 9, a nova API do processo pode ser usada para obter o ID do processo atual. Primeiro, você pega um identificador para o processo atual e, em seguida, consulta o PID:
long pid = ProcessHandle.current().pid();
getpid()
solução também funciona para o OS X, com uma chamada JNA para a biblioteca "System".
error: cannot find symbol
para jdk9
Aqui está um método backdoor que pode não funcionar com todas as VMs, mas deve funcionar no Linux e 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);
getDeclaredMethod
no objeto retornado por jvm.get(runtime)
.
Tente Sigar . 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;
}
Basta ligar 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";
}
int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
. Por que as girações extras?
getCanonicalFile()
método que converte "self" no PID?
Você pode conferir o meu projeto: JavaSysMon no GitHub. Ele fornece a identificação do processo e várias outras coisas (uso da CPU, uso da memória) entre plataformas (atualmente Windows, Mac OSX, Linux e Solaris)
Desde o 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 a 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 nos sistemas Unix até que o Java 9 seja lançado. (Eu sei, a pergunta era sobre Java, mas como não há uma pergunta equivalente para o Scala, eu gostaria de deixar isso para os usuários do Scala que possam encontrar a mesma pergunta.)
Para completar, existe um wrapper no Spring Boot 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 na linha única:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Se alguém já usa a inicialização Spring, ele pode usar org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
O método toString () imprime o pid ou '???'.
Advertências sobre o ManagementFactory já são discutidas em outras respostas.
O mais recente que descobri é que existe uma propriedade do sistema chamada sun.java.launcher.pid
que está disponível pelo menos no linux. Meu plano é usar isso e, se não for encontrado, use o JMX bean
.
Depende de onde você está procurando as informações.
Se você estiver procurando as informações do console, poderá usar o comando jps. O comando fornece uma saída semelhante ao comando ps do Unix e vem com o JDK, pois acredito que o 1.5
Se você está procurando pelo processo, o RuntimeMXBean (como dito por Wouter Coekaerts) é provavelmente a sua melhor escolha. A saída de getName () no Windows usando o Sun JDK 1.6 u7 está no formato [PROCESS_ID] @ [MACHINE_NAME]. No entanto, você pode 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 deve ser a identificação do processo seguida pelo nome.
Esse é o código que JConsole usa e potencialmente o jps e o VisualVM. Ele utiliza classes do
sun.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 poucas capturas:
tool.jar
é uma biblioteca distribuída com o Oracle JDK, mas não o JRE!tool.jar
do repositório Maven; configurá-lo com o Maven é um pouco complicadotool.jar
provavelmente contém código dependente de plataforma (nativo?) Por isso não é facilmente distribuívelATUALIZAÇÃO: Acabei de verificar se o JPS usa dessa maneira, ou seja, a biblioteca Jvmstat (parte do tool.jar). Portanto, não há necessidade de chamar o 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 o código fonte JPS :
Estou adicionando isso a outras soluções.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Com base na resposta de Ashwin Jayaprakash (+1) sobre o Apache 2.0 licenciado SIGAR
, eis como eu o uso para obter apenas o PID do processo atual:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Mesmo que não funcione em todas as plataformas, funciona no Linux, Windows, OS X e várias plataformas Unix, conforme listado aqui .
Eu sei que esse é um encadeamento antigo, mas eu queria chamar a atenção de que a API para obter o PID (assim como outras manipulações do processo Java no 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 pouco complicada e não tentei em outro sistema operacional que não o Windows 10, mas acho que vale a pena notar.
Se você estiver trabalhando com J2V8 e nodejs, poderá 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();
}
Aqui está a 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 eu usei quando tinha 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 execute comandos do SO para descobrir o PID que está ouvindo na porta. Para Linux
netstat -tupln | grep portNumber
bash -c 'echo $PPID'
ou o / proc respostas acima