Jak uzyskać identyfikator mojego procesu Java?
Wiem, że istnieje kilka hacków zależnych od platformy, ale wolałbym bardziej ogólne rozwiązanie.
Jak uzyskać identyfikator mojego procesu Java?
Wiem, że istnieje kilka hacków zależnych od platformy, ale wolałbym bardziej ogólne rozwiązanie.
Odpowiedzi:
Nie istnieje sposób niezależny od platformy, który gwarantowałby działanie we wszystkich implementacjach Jvm.
ManagementFactory.getRuntimeMXBean().getName()
wygląda jak najlepsze (najbliższe) rozwiązanie. Jest krótki i prawdopodobnie działa w każdej implementacji w szerokim użyciu.
W systemie Linux + Windows zwraca wartość typu 12345@hostname
( 12345
będącą identyfikatorem procesu). Uważaj jednak, że zgodnie z dokumentami nie ma żadnych gwarancji dotyczących tej wartości:
Zwraca nazwę reprezentującą działającą maszynę wirtualną Java. Zwrócony ciąg nazwy może być dowolnym dowolnym ciągiem, a implementacja wirtualnej maszyny Java może osadzić przydatne informacje specyficzne dla platformy w zwróconym ciągu nazwy. Każda działająca maszyna wirtualna może mieć inną nazwę.
W Javie 9 można użyć nowego interfejsu API procesu :
long pid = ProcessHandle.current().pid();
Możesz użyć JNA . Niestety nie ma jeszcze wspólnego interfejsu API JNA, aby uzyskać bieżący identyfikator procesu, ale każda platforma jest dość prosta:
Upewnij się, że masz jna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Ogłosić:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Następnie:
int pid = CLibrary.INSTANCE.getpid();
W Javie 9 nowy interfejs API procesu może być używany do uzyskania bieżącego identyfikatora procesu. Najpierw łapiesz uchwyt do bieżącego procesu, a następnie odpytujesz PID:
long pid = ProcessHandle.current().pid();
getpid()
Rozwiązanie działa również dla OS X, z uprzednim JNA do biblioteki „System”.
error: cannot find symbol
dla jdk9
Oto metoda backdoora, która może nie działać ze wszystkimi maszynami wirtualnymi, ale powinna działać zarówno na systemie Linux, jak i Windows ( oryginalny przykład tutaj ):
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
obiekt zwrócony przez jvm.get(runtime)
.
Wypróbuj Sigar . bardzo rozbudowane interfejsy API. Licencja 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();
}
Poniższa metoda próbuje wyodrębnić PID z 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;
}
Na getProcessId("<PID>")
przykład zadzwoń .
Dla starszych JVM, w systemie 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());
. Dlaczego dodatkowe wahania?
getCanonicalFile()
metodzie, która przekształca „jaźń” w PID?
Możesz sprawdzić mój projekt: JavaSysMon na GitHub. Zapewnia identyfikator procesu i kilka innych rzeczy (użycie procesora, użycie pamięci) na różnych platformach (obecnie Windows, Mac OSX, Linux i Solaris)
Od wersji Java 9 istnieje metoda Process.getPid (), która zwraca natywny identyfikator procesu:
public abstract class Process {
...
public long getPid();
}
Aby uzyskać identyfikator bieżącego procesu Java, można użyć ProcessHandle
interfejsu:
System.out.println(ProcessHandle.current().pid());
W Scali:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
To powinno dać ci obejście na systemach Unix do czasu wydania Java 9. (Wiem, że pytanie dotyczyło Javy, ale ponieważ nie ma równoważnego pytania dla Scali, chciałem zostawić to użytkownikom Scali, którzy mogą natknąć się na to samo pytanie).
Dla kompletności jest opakowanie w Spring Boot dla
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
rozwiązanie. Jeśli wymagana jest liczba całkowita, można to zsumować do jednej linijki:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Jeśli ktoś już używa Spring Boot, może użyć org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
Metoda toString () wypisuje pid lub „???”.
Ostrzeżenia dotyczące korzystania z ManagementFactory zostały już omówione w innych odpowiedziach.
Ostatnie stwierdziłem, że istnieje właściwość systemowa o nazwie, sun.java.launcher.pid
która jest dostępna przynajmniej w systemie Linux. Mój plan jest taki, a jeśli nie można go użyć JMX bean
.
To zależy od tego, skąd szukasz informacji.
Jeśli szukasz informacji z konsoli, możesz użyć polecenia jps. Polecenie daje dane wyjściowe podobne do polecenia ps w systemie Unix i jest dostarczane z JDK, ponieważ uważam, że 1.5
Jeśli szukasz z procesu, RuntimeMXBean (jak powiedział Wouter Coekaerts) jest prawdopodobnie najlepszym wyborem. Dane wyjściowe getName () w systemie Windows używającym Sun JDK 1.6 u7 mają postać [PROCESS_ID] @ [MACHINE_NAME]. Możesz jednak spróbować wykonać jps i przeanalizować wynik:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
Jeśli uruchamiany jest bez opcji, wynikiem powinien być identyfikator procesu, a po nim nazwa.
Jest to kod JConsole i potencjalnie używa jps i VisualVM. Wykorzystuje klasy z
sun.jvmstat.monitor.*
pakietu, z 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;
}
}
Istnieje kilka połowów:
tool.jar
Jest biblioteką rozprowadzany z Oracle JDK ale nie JRE!tool.jar
z repozytorium Maven; skonfigurowanie go za pomocą Maven jest nieco trudnetool.jar
Prawdopodobnie zawiera platform zależnej (native?) Kodu, więc nie jest łatwo dystrybuowanaAKTUALIZACJA: Właśnie dwukrotnie sprawdziłem, czy JPS używa tej metody, to znaczy biblioteki Jvmstat (część tool.jar). Nie ma więc potrzeby wywoływania JPS jako zewnętrznego procesu, wywoływania biblioteki Jvmstat bezpośrednio, jak pokazuje mój przykład. W ten sposób można również uzyskać listę wszystkich JVM uruchomionych na localhost. Zobacz kod źródłowy JPS :
Dodam to do innych rozwiązań.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Na podstawie ashwin Jayaprakash za odpowiedź (+1) o 2,0 licencją Apache SIGAR
, tutaj jest, jak go używać, aby uzyskać tylko PID bieżącego procesu:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Mimo że nie działa na wszystkich platformach, działa na systemach Linux, Windows, OS X i różnych platformach Unix wymienionych tutaj .
Wiem, że to stary wątek, ale chciałem przywołać ten interfejs API do pobierania PID (a także innych manipulacji procesem Java w czasie wykonywania) jest dodawany do klasy Process w JDK 9: http: // openjdk. java.net/jeps/102
Znalazłem rozwiązanie, które może być trochę przypadkowe i nie wypróbowałem go na innym systemie operacyjnym niż Windows 10, ale myślę, że warto to zauważyć.
Jeśli znajdziesz pracę z J2V8 i nodejs, możesz uruchomić prostą funkcję javascript zwracającą ci pid procesu java.
Oto przykład:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
Oto moje rozwiązanie:
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;
}
Tego właśnie użyłem, gdy miałem podobne wymagania. To poprawnie określa PID procesu Java. Pozwól, aby kod Java odrodził serwer na wstępnie zdefiniowanym numerze portu, a następnie uruchom komendę systemu operacyjnego, aby dowiedzieć się, czy PID nasłuchuje na porcie. Dla systemu Linux
netstat -tupln | grep portNumber
bash -c 'echo $PPID'
lub powyższe odpowiedzi