Java 프로세스의 ID를 어떻게 얻습니까?
나는 플랫폼에 의존하는 여러 해킹이 있다는 것을 알고 있지만 더 일반적인 솔루션을 선호합니다.
Java 프로세스의 ID를 어떻게 얻습니까?
나는 플랫폼에 의존하는 여러 해킹이 있다는 것을 알고 있지만 더 일반적인 솔루션을 선호합니다.
답변:
모든 jvm 구현에서 작동하도록 보장 할 수있는 플랫폼 독립적 인 방법은 없습니다.
ManagementFactory.getRuntimeMXBean().getName()
최고의 (가장 가까운) 솔루션처럼 보입니다. 짧고 아마도 모든 구현에서 널리 사용됩니다.
linux + windows에서는 12345@hostname
( 12345
프로세스 ID) 와 같은 값을 반환합니다 . 있다고하더라도 조심 워드 프로세서에 따르면 ,이 값에 대한 보장이 없습니다 :
실행중인 Java 가상 머신을 나타내는 이름을 리턴합니다. 리턴 된 이름 문자열은 임의의 문자열 일 수 있으며 Java 가상 머신 구현은 플랫폼 별 유용한 정보를 리턴 된 이름 문자열에 임베드하도록 선택할 수 있습니다. 실행중인 각 가상 머신의 이름이 다를 수 있습니다.
Java 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();
Java 9에서는 새 프로세스 API 를 사용하여 현재 프로세스 ID를 얻을 수 있습니다. 먼저 현재 프로세스에 대한 핸들을 잡고 PID를 쿼리하십시오.
long pid = ProcessHandle.current().pid();
getpid()
솔루션은 또한 "System"라이브러리에 대한 JNA 호출과 함께 OS X에서도 작동합니다.
error: cannot find symbol
jdk9 위해
다음 은 모든 VM에서 작동하지 않을 수 있지만 Linux 및 Windows 모두에서 작동해야하는 백도어 방법입니다 ( 원본 예제 here ).
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
의해 반환 된 Object를 수행하십시오 jvm.get(runtime)
.
시가를 보십시오 . 매우 광범위한 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";
}
int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
됩니다. 왜 여분의 gyrations?
getCanonicalFile()
"self"를 PID로 변환 하는 방법의 일종의 마술 ?
내 프로젝트를 확인할 수 있습니다 : GitHub의 JavaSysMon . 프로세스 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());
완전성을 위해 Spring Boot 에는 래퍼가 있습니다 .
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
해결책. 정수가 필요한 경우 1- 라이너로 요약 할 수 있습니다.
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
누군가 이미 Spring Boot를 사용하고 있다면 org.springframework.boot.ApplicationPid를 사용할 수 있습니다.
ApplicationPid pid = new ApplicationPid();
pid.toString();
toString () 메소드는 pid 또는 '???'를 인쇄합니다.
ManagementFactory를 사용하는주의 사항은 이미 다른 답변에서 논의되었습니다.
내가 찾은 최신이 있다는 것입니다 시스템 프로퍼티 라는 sun.java.launcher.pid
리눅스에 적어도 사용할 수 있습니다. 내 계획은 그것을 사용하는 것이며 그것을 사용하지 않는 경우 JMX bean
.
정보를 찾는 위치에 따라 다릅니다.
콘솔에서 정보를 찾고 있다면 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 다음에 이름이어야합니다.
이것은 코드 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
오라클 JDK가 아닌 JRE와 함께 배포 라이브러리입니다!tool.jar
Maven 저장소에서 얻을 수는 없습니다 . Maven으로 구성하는 것은 약간 까다 롭습니다.tool.jar
쉽게 배포되지 않도록 아마도 플랫폼에 의존 (기본?) 코드를 포함업데이트 : JPS 가이 방법을 사용하는지, 즉 Jvmstat 라이브러리 (tool.jar의 일부)를 두 번 확인했습니다. 따라서 외부 프로세스로 JPS를 호출 할 필요가 없습니다. 예제에 표시된대로 Jvmstat 라이브러리를 직접 호출하십시오. 이 방법으로 localhost에서 실행되는 모든 JVM 목록을 얻을 수 있습니다. JPS 소스 코드를 참조하십시오 .
이것을 다른 솔루션에 추가하고 있습니다.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
라이센스가 부여 된 Apache 2.0에 대한 Ashwin Jayaprakash의 답변 (+1)을 기반으로 SIGAR
현재 프로세스의 PID 만 가져 오는 데 사용하는 방법은 다음과 같습니다.
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
모든 플랫폼에서 작동하지는 않지만 여기에 나열된 Linux, Windows, OS X 및 다양한 Unix 플랫폼에서 작동 합니다.
나는 이것이 오래된 스레드라는 것을 알고 있지만 PID를 얻는 API (런타임에서 Java 프로세스를 다른 조작하는 것)가 JDK 9의 Process 클래스에 추가되고 싶다고 생각했다. http : // openjdk. java.net/jeps/102
약간의 경우가 될 수있는 솔루션을 발견했으며 Windows 10 이외의 다른 OS에서는 시도하지 않았지만 주목할 가치가 있다고 생각합니다.
J2V8 및 nodejs로 작업하는 것을 발견 하면 간단한 자바 스크립트 함수를 실행하여 Java 프로세스의 pid를 반환 할 수 있습니다.
예를 들면 다음과 같습니다.
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
내 해결책은 다음과 같습니다.
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