Bagaimana saya mendapatkan id dari proses Java saya?
Saya tahu ada beberapa peretasan yang bergantung pada platform, tetapi saya lebih suka solusi yang lebih umum.
Bagaimana saya mendapatkan id dari proses Java saya?
Saya tahu ada beberapa peretasan yang bergantung pada platform, tetapi saya lebih suka solusi yang lebih umum.
Jawaban:
Tidak ada cara platform-independen yang dapat dijamin untuk bekerja di semua implementasi jvm.
ManagementFactory.getRuntimeMXBean().getName()
sepertinya solusi terbaik (terdekat). Ini pendek, dan mungkin bekerja di setiap implementasi yang digunakan secara luas.
Di linux + windows, ia mengembalikan nilai seperti 12345@hostname
( 12345
menjadi id proses). Namun berhati-hatilah bahwa menurut dokumen , tidak ada jaminan tentang nilai ini:
Mengembalikan nama yang mewakili mesin virtual Java yang sedang berjalan. String nama yang dikembalikan dapat berupa sembarang string dan implementasi mesin virtual Java dapat memilih untuk menanamkan informasi berguna platform-spesifik dalam string nama yang dikembalikan. Setiap mesin virtual yang berjalan dapat memiliki nama yang berbeda.
Di Java 9 , API proses baru dapat digunakan:
long pid = ProcessHandle.current().pid();
Anda bisa menggunakan JNA . Sayangnya tidak ada API JNA umum untuk mendapatkan ID proses saat ini, tetapi setiap platform cukup sederhana:
Pastikan Anda sudah jna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Menyatakan:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Kemudian:
int pid = CLibrary.INSTANCE.getpid();
Di bawah Java 9 API proses baru dapat digunakan untuk mendapatkan ID proses saat ini. Pertama, Anda mengambil pegangan untuk proses saat ini, lalu meminta PID:
long pid = ProcessHandle.current().pid();
getpid()
solusi juga bekerja untuk OS X, dengan panggilan JNA ke perpustakaan "Sistem".
error: cannot find symbol
untuk jdk9
Berikut adalah metode backdoor yang mungkin tidak berfungsi dengan semua VM tetapi harus bekerja pada linux dan windows ( contoh asli di sini ):
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
pada Objek yang dikembalikan oleh jvm.get(runtime)
.
Coba Sigar . API yang sangat luas. Lisensi 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();
}
Metode berikut mencoba untuk mengekstrak PID dari 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;
}
Panggil saja getProcessId("<PID>")
, misalnya.
Untuk JVM yang lebih lama, di 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());
. Mengapa girasi ekstra?
getCanonicalFile()
metode yang mengubah "diri" menjadi PID?
Anda dapat melihat proyek saya: JavaSysMon di GitHub. Ini memberikan id proses dan banyak hal lainnya (penggunaan CPU, penggunaan memori) lintas-platform (saat ini Windows, Mac OSX, Linux dan Solaris)
Karena Java 9 ada metode Process.getPid () yang mengembalikan ID asli suatu proses:
public abstract class Process {
...
public long getPid();
}
Untuk mendapatkan ID proses dari proses Java saat ini, seseorang dapat menggunakan ProcessHandle
antarmuka:
System.out.println(ProcessHandle.current().pid());
Dalam Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Ini akan memberi Anda solusi pada sistem Unix sampai Java 9 akan dirilis. (Saya tahu, pertanyaannya adalah tentang Java, tetapi karena tidak ada pertanyaan yang setara untuk Scala, saya ingin meninggalkan ini untuk pengguna Scala yang mungkin tersandung ke pertanyaan yang sama.)
Untuk kelengkapan ada pembungkus di Spring Boot untuk
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
larutan. Jika bilangan bulat diperlukan, maka ini dapat disimpulkan hingga satu-baris:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Jika seseorang sudah menggunakan boot Spring, ia mungkin menggunakan org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
Metode toString () mencetak pid atau '???'.
Peringatan menggunakan ManagementFactory sudah dibahas dalam jawaban lain.
Yang terbaru yang saya temukan adalah bahwa ada sistem properti yang disebut sun.java.launcher.pid
yang tersedia setidaknya di linux. Rencana saya adalah menggunakan itu dan jika tidak ditemukan menggunakan JMX bean
.
Tergantung di mana Anda mencari informasi.
Jika Anda mencari informasi dari konsol Anda dapat menggunakan perintah jps. Perintah memberikan output mirip dengan perintah ps Unix dan datang dengan JDK sejak saya percaya 1,5
Jika Anda melihat dari proses, RuntimeMXBean (seperti yang dikatakan oleh Wouter Coekaerts) mungkin merupakan pilihan terbaik Anda. Output dari getName () pada Windows menggunakan Sun JDK 1.6 u7 adalah dalam bentuk [PROCESS_ID] @ [MACHINE_NAME]. Namun Anda bisa mencoba mengeksekusi jps dan mem-parsing hasil dari itu:
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
Jika dijalankan tanpa opsi, output harus menjadi id proses diikuti dengan nama.
Ini adalah kode JConsole, dan berpotensi menggunakan jps dan VisualVM. Ini menggunakan kelas dari
sun.jvmstat.monitor.*
paket, dari 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;
}
}
Ada beberapa tangkapan:
tool.jar
adalah perpustakaan yang didistribusikan dengan Oracle JDK tetapi tidak JRE!tool.jar
dari repo Maven; mengkonfigurasinya dengan Maven agak sulittool.jar
mungkin mengandung tergantung platform (asli?) Kode sehingga tidak mudah didistribusikanUPDATE: Saya baru saja memeriksa ulang bahwa JPS menggunakan cara ini, yaitu perpustakaan Jvmstat (bagian dari tool.jar). Jadi tidak perlu memanggil JPS sebagai proses eksternal, panggil perpustakaan Jvmstat secara langsung seperti contoh saya. Anda juga dapat memperoleh daftar semua runnin JVM di localhost dengan cara ini. Lihat kode sumber JPS :
Saya menambahkan ini, ke solusi lain.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Berdasarkan jawaban Ashwin Jayaprakash (+1) tentang lisensi Apache 2.0 SIGAR
, berikut adalah cara saya menggunakannya untuk hanya mendapatkan PID dari proses saat ini:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Meskipun tidak bekerja di semua platform, ia bekerja di Linux, Windows, OS X dan berbagai platform Unix seperti yang tercantum di sini .
Saya tahu ini adalah utas lama, tetapi saya ingin memanggil bahwa API untuk mendapatkan PID (serta manipulasi lain dari proses Java saat runtime) sedang ditambahkan ke kelas Proses di JDK 9: http: // openjdk. java.net/jeps/102
Saya menemukan solusi yang mungkin sedikit kasus tepi dan saya tidak mencobanya pada OS lain selain Windows 10, tapi saya pikir itu layak diperhatikan.
Jika Anda menemukan diri Anda bekerja dengan J2V8 dan nodejs, Anda dapat menjalankan fungsi javascript sederhana dan mengembalikan Anda pid dari proses java.
Berikut ini sebuah contoh:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
Inilah solusi saya:
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;
}
Inilah yang saya gunakan ketika saya memiliki persyaratan yang sama. Ini menentukan PID proses Java dengan benar. Biarkan kode java Anda menelurkan server pada nomor port yang telah ditentukan sebelumnya dan kemudian jalankan perintah OS untuk mengetahui mendengarkan PID pada port tersebut. Untuk Linux
netstat -tupln | grep portNumber
bash -c 'echo $PPID'
atau / proc jawaban di atas