Comment obtenir l'identifiant de mon processus Java?
Je sais qu'il existe plusieurs hacks dépendants de la plate-forme, mais je préférerais une solution plus générique.
Comment obtenir l'identifiant de mon processus Java?
Je sais qu'il existe plusieurs hacks dépendants de la plate-forme, mais je préférerais une solution plus générique.
Réponses:
Il n'existe aucun moyen indépendant de la plateforme qui puisse être garanti de fonctionner dans toutes les implémentations jvm.
ManagementFactory.getRuntimeMXBean().getName()
ressemble à la meilleure solution (la plus proche). Il est court et fonctionne probablement dans toutes les implémentations largement utilisées.
Sur linux + windows, il retourne une valeur comme 12345@hostname
( 12345
étant l'identifiant du processus). Attention cependant selon les documents , il n'y a aucune garantie sur cette valeur:
Renvoie le nom représentant la machine virtuelle Java en cours d'exécution. La chaîne de nom renvoyée peut être n'importe quelle chaîne arbitraire et une implémentation de machine virtuelle Java peut choisir d'incorporer des informations utiles spécifiques à la plateforme dans la chaîne de nom renvoyée. Chaque machine virtuelle en cours d'exécution peut avoir un nom différent.
Dans Java 9, la nouvelle API de processus peut être utilisée:
long pid = ProcessHandle.current().pid();
Vous pouvez utiliser JNA . Malheureusement, il n'y a pas encore d'API JNA commune pour obtenir l'ID de processus actuel, mais chaque plate-forme est assez simple:
Assurez-vous d'avoir jna-platform.jar
alors:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Déclarer:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Ensuite:
int pid = CLibrary.INSTANCE.getpid();
Sous Java 9, la nouvelle API de processus peut être utilisée pour obtenir l'ID de processus actuel. Commencez par saisir un descripteur du processus en cours, puis interrogez le PID:
long pid = ProcessHandle.current().pid();
getpid()
solution fonctionne également pour OS X, avec un appel JNA à la bibliothèque "System".
error: cannot find symbol
pour jdk9
Voici une méthode de porte dérobée qui pourrait ne pas fonctionner avec toutes les machines virtuelles mais devrait fonctionner à la fois sur Linux et Windows ( exemple original ici ):
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
sur l'objet retourné par jvm.get(runtime)
.
Essayez Sigar . API très étendues. Licence 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();
}
La méthode suivante tente d'extraire le 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;
}
Appelez getProcessId("<PID>")
, par exemple.
Pour les anciennes JVM, sous 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());
. Pourquoi les girations supplémentaires?
getCanonicalFile()
méthode qui convertit le «moi» en PID?
Vous pouvez consulter mon projet: JavaSysMon sur GitHub. Il fournit un identifiant de processus et un tas d'autres choses (utilisation du processeur, utilisation de la mémoire) multiplateforme (actuellement Windows, Mac OSX, Linux et Solaris)
Depuis Java 9, il existe une méthode Process.getPid () qui renvoie l'ID natif d'un processus:
public abstract class Process {
...
public long getPid();
}
Pour obtenir l'ID de processus du processus Java actuel, on peut utiliser l' ProcessHandle
interface:
System.out.println(ProcessHandle.current().pid());
À Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Cela devrait vous fournir une solution de contournement sur les systèmes Unix jusqu'à la sortie de Java 9. (Je sais, la question concernait Java, mais comme il n'y a pas de question équivalente pour Scala, je voulais laisser cela aux utilisateurs de Scala qui pourraient tomber sur la même question.)
Pour être complet, il y a un wrapper dans Spring Boot pour le
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
Solution. Si un entier est requis, cela peut se résumer à la ligne unique:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Si quelqu'un utilise déjà Spring boot, il / elle peut utiliser org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
La méthode toString () imprime le pid ou '???'.
Les mises en garde à l'aide de ManagementFactory sont déjà discutées dans d'autres réponses.
Le dernier que j'ai trouvé est qu'il existe une propriété système appelée sun.java.launcher.pid
qui est disponible au moins sur Linux. Mon plan est de l'utiliser et s'il n'est pas trouvé d'utiliser le JMX bean
.
Cela dépend d'où vous cherchez les informations.
Si vous recherchez les informations de la console, vous pouvez utiliser la commande jps. La commande donne une sortie similaire à la commande Unix ps et est livrée avec le JDK car je crois que 1.5
Si vous cherchez à partir du processus, le RuntimeMXBean (comme l'a dit Wouter Coekaerts) est probablement votre meilleur choix. La sortie de getName () sous Windows à l'aide de Sun JDK 1.6 u7 se présente sous la forme [PROCESS_ID] @ [MACHINE_NAME]. Vous pouvez cependant essayer d'exécuter jps et d'analyser le résultat à partir de cela:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
S'il est exécuté sans options, la sortie doit être l'ID du processus suivi du nom.
Il s'agit du code JConsole et potentiellement utilisé par jps et VisualVM. Il utilise des classes de
sun.jvmstat.monitor.*
package, 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;
}
}
Il y a peu de captures:
tool.jar
est une bibliothèque distribuée avec Oracle JDK mais pas JRE!tool.jar
du repo Maven; le configurer avec Maven est un peu délicattool.jar
contient probablement du code dépendant de la plate-forme (natif?) Donc il n'est pas facilement distribuableMISE À JOUR: Je viens de vérifier que JPS utilise de cette façon, c'est-à-dire la bibliothèque Jvmstat (qui fait partie de tool.jar). Il n'est donc pas nécessaire d'appeler JPS en tant que processus externe, appelez directement la bibliothèque Jvmstat comme mon exemple le montre. Vous pouvez également obtenir la liste de toutes les JVM qui s'exécutent sur localhost de cette façon. Voir le code source JPS :
J'ajoute cela, à d'autres solutions.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Sur la base de la réponse d' Ashwin Jayaprakash (+1) à propos de la licence Apache 2.0 SIGAR
, voici comment je l'utilise pour obtenir uniquement le PID du processus actuel:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Même s'il ne fonctionne pas sur toutes les plates-formes, il fonctionne sur Linux, Windows, OS X et diverses plates-formes Unix comme indiqué ici .
Je sais que c'est un vieux fil, mais je voulais appeler cette API pour obtenir le PID (ainsi que d'autres manipulations du processus Java au moment de l'exécution) est ajoutée à la classe Process dans JDK 9: http: // openjdk. java.net/jeps/102
J'ai trouvé une solution qui peut être un peu un cas de bord et je ne l'ai pas essayée sur un autre système d'exploitation que Windows 10, mais je pense qu'il vaut la peine de le remarquer.
Si vous vous retrouvez à travailler avec J2V8 et nodejs, vous pouvez exécuter une simple fonction javascript vous renvoyant le pid du processus java.
Voici un exemple:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
Voici ma solution:
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;
}
C'est ce que j'ai utilisé lorsque j'avais des exigences similaires. Cela détermine correctement le PID du processus Java. Laissez votre code java générer un serveur sur un numéro de port prédéfini, puis exécutez les commandes du système d'exploitation pour découvrir l'écoute PID sur le port. Pour Linux
netstat -tupln | grep portNumber