Java 프로그램은 어떻게 자체 프로세스 ID를 얻을 수 있나요?

StackOverflow https://stackoverflow.com/questions/35842

  •  09-06-2019
  •  | 
  •  

문제

내 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top