Java 프로그램은 어떻게 자체 프로세스 ID를 얻을 수 있나요?
문제
내 Java 프로세스의 ID를 어떻게 얻나요?
플랫폼에 따른 해킹이 여러 가지 있다는 것을 알고 있지만 좀 더 일반적인 솔루션을 선호합니다.
해결책
모든 jvm 구현에서 작동을 보장할 수 있는 플랫폼 독립적인 방법은 없습니다.ManagementFactory.getRuntimeMXBean().getName()
가장 좋은 (가장 가까운) 솔루션처럼 보입니다.짧고, 아마 널리 사용되는 모든 구현에서 작동합니다.
Linux+windows에서는 다음과 같은 값을 반환합니다. 12345@hostname
(12345
프로세스 ID임).그래도 조심하세요 문서에 따르면, 이 값에 대한 보장은 없습니다.
실행 중인 JVM(Java Virtual Machine)을 나타내는 이름을 반환합니다.반환 된 이름 문자열은 임의의 문자열 일 수 있으며 Java Virtual Machine 구현은 리턴 된 이름 문자열에 플랫폼 별 유용한 정보를 포함하도록 선택할 수 있습니다.실행중인 가상 머신은 다른 이름을 가질 수 있습니다.
자바 9에서 새로운 프로세스 API 사용할 수 있습니다:
long pid = ProcessHandle.current().pid();
다른 팁
당신은 사용할 수 있습니다 JNA.안타깝게도 현재 프로세스 ID를 가져오는 일반적인 JNA API는 아직 없지만 각 플랫폼은 매우 간단합니다.
윈도우
당신이 가지고 있는지 확인하십시오 jna-platform.jar
그 다음에:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
유닉스
선언하다:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
그 다음에:
int pid = CLibrary.INSTANCE.getpid();
자바 9
Java 9에서는 새로운 프로세스 API 현재 프로세스 ID를 얻는 데 사용할 수 있습니다.먼저 현재 프로세스에 대한 핸들을 잡은 다음 PID를 쿼리합니다.
long pid = ProcessHandle.current().pid();
다음은 백도어 방법입니다. ~할 것 같다 모든 VM에서 작동하지는 않지만 Linux와 Windows 모두에서 작동해야 합니다(원래 예는 여기):
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);
노력하다 시가르 .매우 광범위한 API.아파치 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();
}
다음 방법은 PID를 추출하려고 시도합니다. 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>")
, 예를 들어.
이전 JVM의 경우 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";
}
내 프로젝트를 확인할 수 있습니다. 자바시스몬 GitHub에서.프로세스 ID 및 기타 여러 항목(CPU 사용량, 메모리 사용량)을 크로스 플랫폼(현재 Windows, Mac OSX, Linux 및 Solaris)으로 제공합니다.
Java 9부터 프로세스의 기본 ID를 반환하는 Process.getPid() 메서드가 있습니다.
public abstract class Process {
...
public long getPid();
}
현재 Java 프로세스의 프로세스 ID를 얻으려면 다음을 사용할 수 있습니다. ProcessHandle
상호 작용:
System.out.println(ProcessHandle.current().pid());
스칼라에서는:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
이는 Java 9가 출시될 때까지 Unix 시스템에 대한 해결 방법을 제공합니다.(질문은 Java에 관한 것이라는 것을 알고 있지만 Scala에 해당하는 질문이 없기 때문에 같은 질문에 빠질 수 있는 Scala 사용자를 위해 이 질문을 남기고 싶었습니다.)
완전성을 위해 래퍼가 있습니다. 스프링 부트 위해
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
해결책.정수가 필요한 경우 이를 한 줄로 요약할 수 있습니다.
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
누군가 이미 Spring 부트를 사용하고 있다면, 그 사람은 다음을 사용할 수도 있습니다. org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
toString() 메소드는 pid 또는 '???'를 인쇄합니다.
ManagementFactory를 사용하는 주의 사항은 이미 다른 답변에서 논의되었습니다.
public static long getPID() {
String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
if (processName != null && processName.length() > 0) {
try {
return Long.parseLong(processName.split("@")[0]);
}
catch (Exception e) {
return 0;
}
}
return 0;
}
내가 찾은 최신 정보는 다음과 같습니다. 시스템 속성 ~라고 불리는 sun.java.launcher.pid
적어도 리눅스에서는 사용할 수 있습니다.내 계획은 그것을 사용하는 것입니다. 그리고 그것이 사용되지 않으면 JMX bean
.
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
정보를 어디에서 찾고 있는지에 따라 다릅니다.
콘솔에서 정보를 찾으려면 jps 명령을 사용할 수 있습니다.이 명령은 Unix ps 명령과 유사한 출력을 제공하며 1.5를 믿기 때문에 JDK와 함께 제공됩니다.
프로세스를 살펴보면 RuntimeMXBean(Wouter Coekaerts가 말한 대로)이 아마도 최선의 선택일 것입니다.Sun JDK 1.6 u7을 사용하는 Windows에서 getName()의 출력은 [PROCESS_ID]@[MACHINE_NAME] 형식입니다.그러나 jps를 실행하고 그 결과를 구문 분석할 수 있습니다.
String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
옵션 없이 실행하는 경우 출력은 프로세스 ID 뒤에 이름이 와야 합니다.
Ashwin Jayaprakash의 작품을 기반으로 함 답변 Apache 2.0 라이센스에 대한 (+1) SIGAR
, 현재 프로세스의 PID만 가져오기 위해 이를 사용하는 방법은 다음과 같습니다.
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
모든 플랫폼에서 작동하지는 않지만 다음에서는 작동합니다. 여기에 나열된 Linux, Windows, OS X 및 다양한 Unix 플랫폼.
이는 JConsole 코드이며 잠재적으로 jps 및 VisualVM이 사용합니다.다음의 클래스를 활용합니다.sun.jvmstat.monitor.*
패키지, 에서 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;
}
}
몇 가지 문제가 있습니다:
- 그만큼
tool.jar
Oracle JDK와 함께 배포되지만 JRE는 배포되지 않는 라이브러리입니다! - 당신은 얻을 수 없습니다
tool.jar
Maven 저장소에서;Maven으로 구성하는 것은 약간 까다롭습니다. - 그만큼
tool.jar
아마도 플랫폼 종속 (기본?) 코드가 포함되어 있으므로 쉽게 배포 할 수 없습니다. - 실행 중인 모든 (로컬) JVM 앱이 "모니터링 가능"하다는 가정하에 실행됩니다.Java 6에서 나온 것 같습니다. 모든 앱은 일반적으로 (반대를 적극적으로 구성하지 않는 한)
- 아마도 Java 6 이상에서만 작동합니다.
- Eclipse는 메인 클래스를 게시하지 않으므로 MonitoredVMutil에서 Eclipse Pid가 쉽게 버그를 얻지 못합니까?
업데이트:JPS가 이런 방식, 즉 Jvmstat 라이브러리(tool.jar의 일부)를 사용하는지 다시 확인했습니다.따라서 JPS를 외부 프로세스로 호출할 필요가 없습니다. 제 예제에서 볼 수 있듯이 Jvmstat 라이브러리를 직접 호출하세요.이 방법으로 localhost에서 실행되는 모든 JVM 목록을 얻을 수도 있습니다.JPS 참조 소스 코드:
당신은 시도 할 수 있습니다 getpid()
~에 JNR-Posix.
libc에서 getpid()를 호출하는 Windows POSIX 래퍼가 있습니다.
이것이 오래된 스레드라는 것을 알고 있지만 PID(런타임 시 Java 프로세스의 기타 조작 포함)를 가져오기 위한 API가 JDK 9의 Process 클래스에 추가되고 있음을 알리고 싶었습니다. http://openjdk.java.net/jeps/102
다소 극단적인 경우일 수 있는 솔루션을 찾았고 Windows 10이 아닌 다른 OS에서는 시도해 보지 않았지만 주목할 가치가 있다고 생각합니다.
당신이 함께 일하는 것을 발견한다면 J2V8 nodejs를 사용하면 Java 프로세스의 pid를 반환하는 간단한 javascript 함수를 실행할 수 있습니다.
예는 다음과 같습니다.
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
다른 솔루션에 추가.
Java 10을 사용하면 process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
내 해결책은 다음과 같습니다.
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;
}
비슷한 요구 사항이 있을 때 사용한 것입니다.이는 Java 프로세스의 PID를 올바르게 결정합니다.Java 코드가 미리 정의된 포트 번호에 서버를 생성한 다음 OS 명령을 실행하여 포트에서 수신 대기하는 PID를 찾으세요.리눅스의 경우
netstat -tupln | grep portNumber