Java işlemimin kimliğini nasıl edinebilirim?
Platforma bağlı birkaç saldırı olduğunu biliyorum, ancak daha genel bir çözümü tercih ederim.
Java işlemimin kimliğini nasıl edinebilirim?
Platforma bağlı birkaç saldırı olduğunu biliyorum, ancak daha genel bir çözümü tercih ederim.
Yanıtlar:
Tüm jvm uygulamalarında çalışacağı garanti edilebilecek platformdan bağımsız bir yol yoktur.
ManagementFactory.getRuntimeMXBean().getName()
en iyi (en yakın) çözüm gibi görünüyor. Kısa ve muhtemelen her uygulamada geniş kullanımda çalışıyor.
Linux + pencerelerinde 12345@hostname
( 12345
işlem kimliği olmak üzere) gibi bir değer döndürür . O olsa dikkat docs göre , bu değeri hakkında hiçbir garanti vardır:
Çalışan Java sanal makinesini temsil eden adı döndürür. Döndürülen ad dizesi herhangi bir isteğe bağlı dize olabilir ve bir Java sanal makine uygulaması, döndürülen ad dizesine platforma özgü yararlı bilgileri katmayı seçebilir. Çalışan her sanal makinenin farklı bir adı olabilir.
Java 9'da yeni işlem API'si kullanılabilir:
long pid = ProcessHandle.current().pid();
JNA kullanabilirsiniz . Ne yazık ki, mevcut işlem kimliğini almak için henüz ortak bir JNA API'sı yok, ancak her platform oldukça basit:
O jna-platform.jar
zaman şunlara sahip olduğunuzdan emin olun :
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Bildirmek:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Sonra:
int pid = CLibrary.INSTANCE.getpid();
Java 9 altında, yeni işlem API'si geçerli işlem kimliğini almak için kullanılabilir. Önce geçerli işleme bir tanıtıcı alıp sonra PID'yi sorgulayın:
long pid = ProcessHandle.current().pid();
getpid()
Çözüm ayrıca "Sistem" kütüphaneye bir JNA çağrısı ile, OS X için çalışır.
error: cannot find symbol
jdk9 için alıyorum
İşte bir arka kapı yöntemidir olabilecek tüm sanal makineler ile çalışmaz ama (hem Linux ve pencereler üzerinde çalışması gerekir burada orijinal örnek ):
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
tarafından döndürülen Nesne üzerinde gerçekleştirin jvm.get(runtime)
.
Sigar'ı deneyin . çok kapsamlı API'lar. Apache 2 lisansı.
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();
}
Aşağıdaki yöntem PID'yi buradan ayıklamaya çalışır 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;
}
getProcessId("<PID>")
Mesela arayın .
Eski JVM için, Linux'ta ...
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());
. Neden ekstra dönmeler?
getCanonicalFile()
PID'ye "kendini" dönüştüren yöntemde bir çeşit sihir mi?
Projemi kontrol edebilirsiniz: GitHub'da JavaSysMon . İşlem kimliği ve bir dizi başka şey (CPU kullanımı, bellek kullanımı) çapraz platform (şu anda Windows, Mac OSX, Linux ve Solaris) sağlar
Java 9'dan beri, bir işlemin yerel kimliğini döndüren bir Process.getPid () yöntemi vardır:
public abstract class Process {
...
public long getPid();
}
Geçerli Java işleminin işlem kimliğini almak için ProcessHandle
arabirimi kullanabilirsiniz :
System.out.println(ProcessHandle.current().pid());
Scala'da:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Bu, Java 9 piyasaya sürülünceye kadar Unix sistemlerinde bir geçici çözüm sağlayacaktır. (Biliyorum, soru Java ile ilgiliydi, ancak Scala için eşdeğer bir soru olmadığından, bunu aynı soruya rastlayabilecek Scala kullanıcıları için bırakmak istedim.)
Bütünlüğü sağlamak için bir ambalaj olup Yay Boot için
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
çözüm. Bir tamsayı gerekiyorsa, bu tek astarlı olarak toplanabilir:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Birisi zaten Bahar önyükleme kullanıyorsa, org.springframework.boot.ApplicationPid kullanabilir.
ApplicationPid pid = new ApplicationPid();
pid.toString();
ToString () yöntemi, pid veya '???'
ManagementFactory kullanan uyarılar zaten diğer cevaplarda tartışılmıştır.
Bulduğum en son linux üzerinde kullanılabilir denilen bir sistem özelliğisun.java.launcher.pid
olmasıdır. Planım bunu kullanmak ve eğer bulamazsa kullanmaktır JMX bean
.
Bu bilgiyi nereden aradığınıza bağlıdır.
Konsoldan bilgi arıyorsanız jps komutunu kullanabilirsiniz. Komut, Unix ps komutuna benzer çıktılar verir ve inanıyorum çünkü JDK ile birlikte gelir
Eğer süreçten bakıyorsanız (Wouter Coekaerts tarafından söylendiği gibi) RuntimeMXBean muhtemelen en iyi seçimdir. Sun JDK 1.6 u7 kullanan Windows'ta getName () 'den çıktı [PROCESS_ID] @ [MACHINE_NAME] biçimindedir. Ancak jps yürütmeyi deneyebilir ve sonucu bundan ayrıştırabilirsiniz:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
Hiçbir seçenek olmadan çalıştırılırsa, çıktı işlem kimliği ve ardından ad olmalıdır.
Bu JConsole kodu ve potansiyel olarak jps ve VisualVM kullanır. sun.jvmstat.monitor.*
Paketten sınıftan yararlanır
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;
}
}
Birkaç yakalama var:
tool.jar
Oracle JDK ancak JRE ile dağıtılan bir kütüphane!tool.jar
Maven deposundan alamazsınız ; Maven ile yapılandırmak biraz zortool.jar
Kolayca dağıtılabilir değildir bu yüzden muhtemelen platformu bağımlı (native?) Kodu içerenGÜNCELLEME: Sadece JPS bu şekilde kullandığını, Jvmstat kütüphanesi (tool.jar parçası) olduğunu çift kontrol ettim. Bu yüzden JPS'yi harici işlem olarak çağırmanıza gerek yok, örneğimin gösterdiği gibi doğrudan Jvmstat kütüphanesini arayın. Bu şekilde localhost üzerinde çalıştırılan tüm JVM'lerin listesini de alabilirsiniz. JPS kaynak koduna bakın :
Bunu diğer çözümlere ekliyorum.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Ashwin Jayaprakash'ın lisanslı Apache 2.0 hakkındaki cevabına (+1) dayanarak, SIGAR
sadece mevcut sürecin PID'sini almak için bunu nasıl kullanırım:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Tüm platformlarda çalışmasa da, burada listelendiği gibi Linux, Windows, OS X ve çeşitli Unix platformlarında çalışır .
Bu eski bir iş parçacığı olduğunu biliyorum, ama PID (yanı sıra çalışma zamanında Java işleminin diğer manipülasyon) almak için API JDK 9: http: // openjdk Process sınıfına eklenmesini çağırmak istedim. java.net/jeps/102
Biraz uç durumda olabilecek bir çözüm buldum ve Windows 10'dan başka bir işletim sisteminde denemedim, ancak fark etmeye değer.
Kendinizi J2V8 ve nodejs ile çalışırken bulursanız, size java işleminin pidini döndüren basit bir javascript işlevi çalıştırabilirsiniz.
İşte bir örnek:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
İşte benim çözümüm:
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;
}
Benzer bir gereksinimim olduğunda kullandığım bu oldu. Bu, Java işleminin PID'sini doğru olarak belirler. Java kodunuzun önceden tanımlanmış bir bağlantı noktası numarasında bir sunucu oluşturmasına izin verin ve ardından bağlantı noktasında dinleme yapan PID'yi bulmak için OS komutlarını yürütün. Linux için
netstat -tupln | grep portNumber
bash -c 'echo $PPID'
veya / proc yanıtları da yapabilirsiniz