OS 수준의 시스템 정보 얻기


232

나는 현재 많은 다른 플랫폼에서 실행될 수 있지만 주로 Solaris, Linux 및 Windows의 변형에서 실행될 수있는 Java 응용 프로그램을 만들고 있습니다.

누구든지 현재 사용 된 디스크 공간, CPU 사용률 및 기본 OS에서 사용 된 메모리와 같은 정보를 성공적으로 추출 할 수 있습니까? Java 앱 자체가 소비하는 것은 어떻습니까?

JNI를 사용하지 않고이 정보를 얻고 싶습니다.


3
사용 가능한 메모리와 관련하여 stackoverflow.com/a/18366283/231397을 참조하십시오 ( Runtime.getRuntime().freeMemory()허용 된 답변에서 제안 된대로 사용 가능한 메모리 양이 제공되지 않음
Christian Fries

답변:


206

Runtime 클래스에서 제한된 메모리 정보를 얻을 수 있습니다. 그것은 실제로 당신이 찾고있는 것이 아니지만, 나는 완전성을 위해 그것을 제공 할 것이라고 생각했습니다. 다음은 작은 예입니다. 편집 : java.io.File 클래스에서 디스크 사용 정보를 얻을 수도 있습니다. 디스크 공간 사용량에는 Java 1.6 이상이 필요합니다.

public class Main {
  public static void main(String[] args) {
    /* Total number of processors or cores available to the JVM */
    System.out.println("Available processors (cores): " + 
        Runtime.getRuntime().availableProcessors());

    /* Total amount of free memory available to the JVM */
    System.out.println("Free memory (bytes): " + 
        Runtime.getRuntime().freeMemory());

    /* This will return Long.MAX_VALUE if there is no preset limit */
    long maxMemory = Runtime.getRuntime().maxMemory();
    /* Maximum amount of memory the JVM will attempt to use */
    System.out.println("Maximum memory (bytes): " + 
        (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

    /* Total memory currently available to the JVM */
    System.out.println("Total memory available to JVM (bytes): " + 
        Runtime.getRuntime().totalMemory());

    /* Get a list of all filesystem roots on this system */
    File[] roots = File.listRoots();

    /* For each filesystem root, print some info */
    for (File root : roots) {
      System.out.println("File system root: " + root.getAbsolutePath());
      System.out.println("Total space (bytes): " + root.getTotalSpace());
      System.out.println("Free space (bytes): " + root.getFreeSpace());
      System.out.println("Usable space (bytes): " + root.getUsableSpace());
    }
  }
}

7
"JVM에서 현재 사용중인 총 메모리"는 약간 혼란 스럽다고 생각합니다. javadoc에서는 그 함수가 반환 말한다 "바이트 단위로 측정 현재와 미래의 객체에 대해 현재 사용 가능한 총 메모리의 양을." 메모리가 남아 있고 사용하지 않는 것 같습니다.
Dirk

@ Dirk : 귀하의 의견을 반영하기 위해 문구를 업데이트했습니다. 감사!
윌리엄 브렌델

@LeonardoGaldioli : 나는이 클래스와 메소드의 성능 특성을 모르지만 속도에 최적화되지 않았다면 놀라지 않을 것입니다. 다른 답변은 JMX를 사용하여 특정 정보를 수집하는 방법을 설명합니다.
윌리엄 브렌델

15
이것은 질문에 올바르게 대답하지 않습니다. 모든 데이터 리퍼는 OS가 아닌 JVM에 의존합니다.
Alvaro

이 주제는 매우 구식이라는 것을 알고 있습니다. 그러나 CPU 코어가 실제로 필요한 경우이 솔루션을 사용하지 마십시오. 각 코어마다 2 개의 스레드가있는 듀얼 코어 CPU가 있습니다. JVM은 하드웨어 코어가 아니라 소프트웨어 코어 / 스레드를 반환합니다.
F_Schmidt

95

java.lang.management의 패키지는 당신에게 런타임보다 훨씬 더 많은 정보를 준다 - 예를 들어 당신에게 힙 메모리를 줄 것이다 ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) (비 힙 메모리에서 분리 ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

(자신의 JNI 코드를 작성하지 않고) 프로세스 CPU 사용량을 얻을 수도 있지만를로 캐스팅해야 java.lang.management.OperatingSystemMXBean합니다 com.sun.management.OperatingSystemMXBean. 이것은 Windows 및 Linux에서 작동하며 다른 곳에서는 테스트하지 않았습니다.

예를 들어 ... 더 정확한 판독 값을 얻으려면 get getCpuUsage () 메소드를 더 자주 호출하십시오.

public class PerformanceMonitor { 
    private int  availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
    private long lastSystemTime      = 0;
    private long lastProcessCpuTime  = 0;

    public synchronized double getCpuUsage()
    {
        if ( lastSystemTime == 0 )
        {
            baselineCounters();
            return;
        }

        long systemTime     = System.nanoTime();
        long processCpuTime = 0;

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }

        double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );

        lastSystemTime     = systemTime;
        lastProcessCpuTime = processCpuTime;

        return cpuUsage / availableProcessors;
    }

    private void baselineCounters()
    {
        lastSystemTime = System.nanoTime();

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }
    }
}

10
컴파일하려면 캐스트 OperatingSystemMXBean를로 바꾸고 com.sun.management.OperatingSystemMXBean모든 인스턴스를 getOperatingSystemMXBean()로 시작하십시오 ManagementFactory.. 모든 클래스를 적절히 가져와야합니다.
tmarthal 2019

2
모든 것에 CPU 사용량이 0으로 표시됩니다. CPU 사용 수식을 cpuUsage = processCpuTime / systemTime으로 변경했습니다. 나는 이해할 수없는 CPU 사용량에 대한 가치를 얻고 있습니다.
Raj

않는 1.0 에서 결과를 getCpuUsage시스템에서 사용하는 모든 것을 의미 availableProcessors을 100 %?
user454322

2
@Raj가 말한 것처럼 항상 0을 얻습니다 ... 그 코드를 사용하는 방법의 예를 들어 줄 수 있습니까?
dm76

1
시도((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
Anthony O.

43

가장 좋은 방법은 HypericSIGAR API 를 구현하는 입니다. 그것은 대부분의 주요 운영 체제에서 작동하며 (현대적으로 거의 다름) 작업하기가 매우 쉽습니다. 개발자는 포럼 및 메일 링리스트에 매우 반응이 좋습니다. 또한 GPL2 Apache 라이센스가있는 것이 좋습니다. Java에서도 많은 예제를 제공합니다!

SIGAR == 시스템 정보, 수집 및보고 도구.


2
@Yohan-게으르지 마십시오! 링크 된 웹 페이지 를 읽으면 찾을 수 있습니다 . (그리고 그것은 "플랫폼 독립적"의 의미에 달려 있습니다.)
Stephen C

2
@StephenC : Sigar는 .dll 파일을 사용하므로 플랫폼에 따라 다릅니다. 더 높은 수준의 API는 Java에있을 수 있습니다. 다른 이야기입니다
Lemon Juice

1
@Artificial_Intelligence는 그렇습니다. 그러나 가장 인기있는 플랫폼을위한 라이브러리 (c로 작성)를 제공합니다. jvm 자체보다 더 많은 플랫폼에 의존하지 않습니다. 더 높은 수준의 Java API는 모든 플랫폼에서 일관성이 있어야합니다.
Jeshurun

8
Sigar는 2010 년 이후로 업데이트되지 않으며 64 비트 시스템에 버그가있는 것 같습니다 : stackoverflow.com/questions/23405832/…
Alvaro

1
그리고 SIGAR는 JVM 충돌도 발생하지만 간헐적이지만 프로덕션에서는이 위험을 감수하지 않을 것이라고 확신합니다.
AKS

25

JNA를 사용하여 (설치할 기본 라이브러리가 없음) Java 프로젝트가 있으며 현재 개발 중입니다. 현재 Linux, OSX, Windows, Solaris 및 FreeBSD를 지원하며 RAM, CPU, 배터리 및 파일 시스템 정보를 제공합니다.


네이티브 라이브러리가 잘못된 것일 수 있습니다. 이 프로젝트 아무것도 작성하지 않았더라도 설치하지 않아도 기본 라이브러리를 사용합니다.
Stephen C

1
네가 옳아. JNA는 기본 구성 요소가있는 libffi를 사용합니다. 그러나 모든 목적을 위해 네이티브 라이브러리가없는 것 같습니다 (확실히 설치할 라이브러리가 없음).
dB.

@StephenC 비록 당신이 말하는 것이 정확하지만 네이티브 메소드를 호출하는 rt.jar와 동일하기 때문에 오해의 소지가 있습니다. 사람들이 네이티브 메소드에 관심을 갖는 유일한 이유는 컴파일 및 / 또는 설치해야하기 때문에 종종 사소한 작업이 아닙니다. libffi는 광범위하게 채택, 이식 및 설치되므로 어려움을 완화합니다. 따라서 기술적으로는 정확하지만 실제로는 중요하지 않습니다.
rbp

@rbp- 경험 많은 Java 개발자가 네이티브 라이브러리를 피하는 것을 선호하는 또 다른 이유가 있습니다 . 스레드 안전 문제 또는 메모리 관리 문제를 포함하여 버그가있는 기본 라이브러리는 호스트 JVM을 불안정하게 만들 수 있습니다. 이것은 " 문제 가되지 않습니다" 문제 는 아닙니다 . ....
Stephen C

@StephenC는 weblogic 응용 프로그램 서버를 작성하면 충분히 경험할 수 있습니까?
rbp

13

창문의 경우 나는이 길을 갔다.

    com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    long physicalMemorySize = os.getTotalPhysicalMemorySize();
    long freePhysicalMemory = os.getFreePhysicalMemorySize();
    long freeSwapSize = os.getFreeSwapSpaceSize();
    long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();

자세한 내용 이있는 링크 는 다음과 같습니다 .


11

System.getenv()관련 환경 변수 이름을 매개 변수로 전달하여을 사용하여 일부 시스템 수준 정보를 얻을 수 있습니다 . 예를 들어, Windows의 경우 :

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

다른 운영 체제의 경우 관련 환경 변수의 유무 및 이름이 다릅니다.


1
변수 이름은 시스템마다 다르기 때문에 플랫폼에 따라 다릅니다. 환경 변수에 대한 오라클 기사가 그 사실을 알려줍니다. 또한 시스템 독립적 인 방법을 찾는 방법을 찾고 있습니다.
레몬 주스

Linux (Ubuntu 17.10)에서는 환경의 프로세서에 관한 흥미로운 정보가 많지 않습니다.
pveentjer

8

maven을 통해 OSHI 종속성을 추가하십시오.

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

배터리 용량을 백분율로 표시하십시오.

SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
    System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}

OSHI는 다른 의견에 설명 된 대부분의 정보를 가지고 있습니다. 가능한 경우 JNA를 사용하여 OS 기본 호출을 통해 가져옵니다.
Daniel Widdis

6

java.lang.management 패키지 에서 사용 가능한 API를 살펴보십시오 . 예를 들면 다음과 같습니다.

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

거기에는 다른 유용한 것들도 많이 있습니다.


2
너무 비싸기 때문에 Windows에서는 OperatingSystemMXBean.getSystemLoadAverage ()가 구현되지 않습니다.
MikeNereson

1
ThreadMXBean.getCurrentThreadCpuTime ()은 해당 스레드가 실행 된 시간 만 리턴합니다. CPU 사용량이 아닙니다.
MikeNereson

5

일반적으로 낮은 수준의 OS 정보를 얻기 위해 Runtime.exec ()로 원하는 정보를 제공하거나 Linux에서 / proc / *와 같은 파일을 읽는 OS 관련 명령을 호출 할 수 있습니다.


5

CPU 사용은 간단하지 않습니다. com.sun.management.OperatingSystemMXBean.getProcessCpuTime을 통한 java.lang.management는 가까이 왔습니다 (위의 Patrick의 우수한 코드 스 니펫 참조). 다른 프로세스에서 소비 한 CPU 시간 또는 프로세스와 관련된 시스템 활동을 수행하는 데 소요 된 CPU 시간에 대해서는 알려주지 않습니다.

예를 들어 나는 네트워크 집약적 인 Java 프로세스를 가지고 있습니다. 유일하게 실행되고 CPU는 99 %이지만 그중 55 %만이 "프로세서 CPU"로보 고됩니다.

MX bean의 유일한 CPU 관련 항목 임에도 불구하고 쓸데없는 옆에 있으므로 "로드 평균"을 시작하지 마십시오. 가끔 지혜로만 태양이 "getTotalCpuTime"과 같은 것을 노출 시킨다면 ...

심각한 CPU 모니터링을 위해 Matt가 언급 한 SIGAR가 최선의 방법으로 보입니다.


4

Windows, 당신은 실행할 수있는 systeminfo명령을 다음과 같은 코드를 예를 들어 출력을 검색합니다

private static class WindowsSystemInformation
{
    static String get() throws IOException
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("systeminfo");
        BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder stringBuilder = new StringBuilder();
        String line;

        while ((line = systemInformationReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }

        return stringBuilder.toString().trim();
    }
}

3

Jrockit VM을 사용하는 경우 VM CPU 사용을 얻는 다른 방법이 있습니다. 런타임 Bean은 또한 프로세서 당 CPU로드를 제공 할 수 있습니다. Tomcat 성능을 관찰하기 위해 Red Hat Linux에서만 이것을 사용했습니다. 이것이 작동하려면 catalina.sh에서 JMX remote를 활성화해야합니다.

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);     
MBeanServerConnection conn = jmxc.getMBeanServerConnection();       
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");

3

아직 개발 중이지만 이미 jHardware를 사용할 수 있습니다

Java를 사용하여 시스템 데이터를 스크랩하는 간단한 라이브러리입니다. Linux와 Windows 모두에서 작동합니다.

ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());        
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]

좋지만 내 요구와 충돌하는 구아바 및 JNA 버전을 사용합니다 (예 : GLASSFISH-21367 참조 ).
lu_ko

안녕하세요, JNA는 0.8 버전의 jHardware에서 도입되었습니다. 온도 및 센서 데이터에만 사용됩니다. 해당 정보가 필요하지 않은 경우 0.7 버전을 사용할 수 있습니다. 구아바도 마찬가지입니다. 이 경우 0.6.3 버전을 사용해야합니다.
profesor_falken

2

OS 레벨 정보를 얻는 데 사용할 수있는 간단한 방법 중 하나이며 Mac에서 잘 테스트되었습니다.

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

여기 에서 운영 체제의 많은 관련 메트릭을 찾을 수 있습니다


1

Java / com 통합으로이 작업을 수행 할 수 있습니다. WMI 기능에 액세스하면 모든 정보를 얻을 수 있습니다.


0

Java 코드 내 에서 시스템로드 평균 1 분, 5 분 및 15 분 을 얻으려면 다음을 cat /proc/loadavg사용 하여 명령 을 실행 하고 해석하여이를 수행 할 수 있습니다.

    Runtime runtime = Runtime.getRuntime();

    BufferedReader br = new BufferedReader(
        new InputStreamReader(runtime.exec("cat /proc/loadavg").getInputStream()));

    String avgLine = br.readLine();
    System.out.println(avgLine);
    List<String> avgLineList = Arrays.asList(avgLine.split("\\s+"));
    System.out.println(avgLineList);
    System.out.println("Average load 1 minute : " + avgLineList.get(0));
    System.out.println("Average load 5 minutes : " + avgLineList.get(1));
    System.out.println("Average load 15 minutes : " + avgLineList.get(2));

그리고 명령을 실행 하고 다음과 같이 해석 하여 실제 시스템 메모리 를 가져옵니다 free -m.

Runtime runtime = Runtime.getRuntime();

BufferedReader br = new BufferedReader(
    new InputStreamReader(runtime.exec("free -m").getInputStream()));

String line;
String memLine = "";
int index = 0;
while ((line = br.readLine()) != null) {
  if (index == 1) {
    memLine = line;
  }
  index++;
}
//                  total        used        free      shared  buff/cache   available
//    Mem:          15933        3153        9683         310        3097       12148
//    Swap:          3814           0        3814

List<String> memInfoList = Arrays.asList(memLine.split("\\s+"));
int totalSystemMemory = Integer.parseInt(memInfoList.get(1));
int totalSystemUsedMemory = Integer.parseInt(memInfoList.get(2));
int totalSystemFreeMemory = Integer.parseInt(memInfoList.get(3));

System.out.println("Total system memory in mb: " + totalSystemMemory);
System.out.println("Total system used memory in mb: " + totalSystemUsedMemory);
System.out.println("Total system free memory in mb: "   + totalSystemFreeMemory);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.