Programing

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

lottogame 2020. 3. 4. 08:06
반응형

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


Java 프로세스의 ID를 어떻게 얻습니까?

나는 플랫폼에 의존하는 여러 해킹이 있다는 것을 알고 있지만 더 일반적인 솔루션을 선호합니다.


모든 jvm 구현에서 작동하도록 보장 할 수있는 플랫폼 독립적 인 방법은 없습니다. ManagementFactory.getRuntimeMXBean().getName()최고의 (가장 가까운) 솔루션처럼 보입니다. 짧고 아마도 모든 구현에서 널리 사용됩니다.

linux + windows에서는 12345@hostname( 12345프로세스 ID) 와 같은 값을 반환합니다 . 있다고하더라도 조심 워드 프로세서에 따르면 ,이 값에 대한 보장이 없습니다 :

실행중인 Java 가상 머신을 나타내는 이름을 리턴합니다. 리턴 된 이름 문자열은 임의의 문자열 일 수 있으며 JVM (Java Virtual Machine) 구현은 플랫폼 별 유용한 정보를 리턴 된 이름 문자열에 임베드하도록 선택할 수 있습니다. 실행중인 각 가상 머신의 이름이 다를 수 있습니다.

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();

자바 9

Java 9에서는 새 프로세스 API 를 사용하여 현재 프로세스 ID를 얻을 수 있습니다. 먼저 현재 프로세스에 대한 핸들을 잡고 PID를 쿼리하십시오.

long pid = ProcessHandle.current().pid();

다음 은 모든 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);

시가를 보십시오 . 매우 광범위한 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의 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());

스칼라에서 :

import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong

이것은 Java 9가 출시 될 때까지 Unix 시스템에 대한 해결 방법을 제공해야합니다. (질문은 Java에 관한 것이지만 Scala에 대한 동등한 질문이 없으므로 동일한 질문에 걸려 넘어 질 수있는 Scala 사용자를 위해 이것을 남겨두고 싶었습니다.)


완전성을 위해 Spring Boot 에는 래퍼가 있습니다 .

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];

해결책. 정수가 필요한 경우 1- 라이너로 요약 할 수 있습니다.

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

누군가 이미 스프링 부트를 사용하고 있다면 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 다음에 이름이어야합니다.


라이센스가 부여 된 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 플랫폼에서 작동 합니다.


이것은 코드 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.jarMaven 저장소에서 얻을 수는 없습니다 . Maven으로 구성하는 것은 약간 까다 롭습니다.
  • tool.jar쉽게 배포되지 않도록 아마도 플랫폼에 의존 (기본?) 코드를 포함
  • 모든 (로컬) 실행중인 JVM 앱이 "모니터링 가능"하다는 가정하에 실행됩니다. Java 6부터 모든 앱이 일반적으로 보입니다 (대 향적으로 적극적으로 구성하지 않는 한)
  • 아마 Java 6 이상에서만 작동합니다.
  • Eclipse는 메인 클래스를 게시하지 않으므로 MonitoredVmUtil의 Eclipse PID를 쉽게 얻지 못합니까?

업데이트 : JPS 가이 방법을 사용하는지, 즉 Jvmstat 라이브러리 (tool.jar의 일부)를 두 번 확인했습니다. 따라서 외부 프로세스로 JPS를 호출 할 필요가 없습니다. 예제에 표시된대로 Jvmstat 라이브러리를 직접 호출하십시오. 이 방법으로 localhost에서 실행되는 모든 JVM 목록을 얻을 수 있습니다. JPS 소스 코드를 참조하십시오 .


JNR-Posixgetpid() 에서 시도해 볼 수 있습니다 .

libc에서 getpid ()를 호출하는 Windows POSIX 랩퍼가 있습니다.


나는 이것이 오래된 스레드라는 것을 알고 있지만 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();
}

다른 솔루션에 추가

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

참고 URL : https://stackoverflow.com/questions/35842/how-can-a-java-program-get-its-own-process-id



반응형