Java에서 컴퓨터의 CPU, 메모리 및 디스크 사용량을 어떻게 모니터링합니까?


180

Java로 다음 시스템 정보를 모니터링하고 싶습니다.

  • 현재 CPU 사용량 ** (퍼센트)
  • 사용 가능한 메모리 * (무료 / 전체)
  • 사용 가능한 디스크 공간 (사용 가능 / 전체)

    * JVM뿐만 아니라 전체 시스템에서 사용 가능한 전체 메모리를 의미합니다.

외부 프로그램을 호출하거나 JNI를 사용하는 자체 코드에 의존하지 않는 크로스 플랫폼 솔루션 (Linux, Mac 및 Windows)을 찾고 있습니다. 이것들은 실행 가능한 옵션이지만 누군가가 이미 더 나은 솔루션을 가지고 있다면 OS 특정 코드를 직접 유지하지 않는 것이 좋습니다.

신뢰할 수 있고 크로스 플랫폼 방식 으로이 작업을 수행하는 무료 라이브러리가 있다면 외부 호출을하거나 네이티브 코드 자체를 사용하는 경우에도 좋습니다.

어떤 제안이라도 대단히 감사합니다.

명확히하기 위해 Java 프로세스뿐만 아니라 전체 시스템의 현재 CPU 사용량을 얻고 싶습니다.

SIGAR API는 하나의 패키지로 찾고있는 모든 기능을 제공하므로 지금까지 내 질문에 가장 적합한 답변입니다. 그러나 GPL에 따라 라이센스가 부여되었으므로 원래 목적 (폐쇄 소스, 상용 제품)으로 사용할 수 없습니다. Hyperic이 상업적 용도로 SIGAR에 라이센스를 부여 할 수도 있지만, 살펴 보지는 않았습니다. 내 GPL 프로젝트의 경우 앞으로 SIGAR을 확실히 고려할 것입니다.

현재 필요에 따라 다음과 같이 기울고 있습니다.

  • CPU 사용량의 경우 OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()( CPU 당로드 평균)
  • 메모리의 경우, OperatingSystemMXBean.getTotalPhysicalMemorySize()OperatingSystemMXBean.getFreePhysicalMemorySize()
  • 디스크 공간 File.getTotalSpace()File.getUsableSpace()

한계 :

getSystemLoadAverage()방법을 질의 및 디스크 공간 또한 자바 6에 따라, 일부 JMX 기능 (즉이보고되고있어 모든 플랫폼에 사용할 수 없습니다에서만 사용할 수 있습니다getSystemLoadAverage() -1을 반환 Windows의 경우).

원래 GPL 라이센스 있지만,이 변경되었습니다아파치 2.0 일반적으로 닫힌 소스, 상용 제품에 사용할 수 있습니다.


명확히하기 위해 시가 API는 시스템 정보를 제공합니다. jvm 정보를 원하면 JMX를 사용하십시오.
매트 커밍스

GPL하에있는 SIGAR는 귀하가 GPL을 사용하는 것을 방해하지 않습니다. 단지 저자에게 연락하여 대체 라이센스를 요청해야한다는 의미입니다. 저자는 종종 작은 비용을 받고 상용 라이센스를 허용하는 것을 좋아합니다.
Alec Thomas

7
버전 1.6.4부터 SIGAR는 Apache 라이센스를 사용하고 있습니다.
Soundlink

각 개별 프로세서의로드를 얻는 방법을 알고 있습니까?
zcaudate

답변:


67

이 게시물에서 언급 한 내용에 따라 . SIGAR API 를 사용하는 것이 좋습니다 . 내 응용 프로그램 중 하나에서 SIGAR API를 사용하며 훌륭합니다. 안정적이고 잘 지원되며 유용한 예제가 가득하다는 것을 알 수 있습니다. GPL 2 Apache 2.0 라이센스 가있는 오픈 소스입니다 . 확인 해봐. 나는 그것이 당신의 필요를 충족시킬 느낌이 있습니다.

Java 및 Sigar API를 사용하면 메모리, CPU, 디스크,로드 평균, 네트워크 인터페이스 정보 및 메트릭, 프로세스 테이블 정보, 경로 정보 등을 얻을 수 있습니다.


14
Sigar를 사용할 때 x64 시스템에 문제가 있습니다 ... stackoverflow.com/questions/23405832/… 2010 년 이후 라이브러리가 업데이트되지 않는 것 같습니다
Alvaro

56

다음은 아마도 CPU와 RAM을 얻는 것입니다. 자세한 내용은 ManagementFactory 를 참조하십시오.

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

private static void printUsage() {
  OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
  for (Method method : operatingSystemMXBean.getClass().getDeclaredMethods()) {
    method.setAccessible(true);
    if (method.getName().startsWith("get")
        && Modifier.isPublic(method.getModifiers())) {
            Object value;
        try {
            value = method.invoke(operatingSystemMXBean);
        } catch (Exception e) {
            value = e;
        } // try
        System.out.println(method.getName() + " = " + value);
    } // if
  } // for
}

3
위 코드에 대한 샘플 출력. 이 코드는 Java 1.5에서 작동합니다. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r

AFAIK getProcessCpuTime = 390625000은 해당 스레드가 실행 된 시간입니다. 그것은 프로세서 사용을 결정하는데 실제로 유용하지 않습니다
MikeNereson

2
실제로 신뢰할 수 있는지 확실하지 않습니다. 실제 메모리가 4GB 인 Windows XP에서는 2GB 만보고합니다 (Java 6 및 Java 7에서 테스트). 총 스왑 크기도 잘못되었습니다.
Emmanuel Bourg

4
@EmmanuelBourg는이 주제를 보는 사람들을 위해 문서화하기 위해 이와 관련된 버그가 있습니다.
Sérgio Michels

2
이 메소드는 Java 9까지 훌륭하게 작동했으며 이제 Java가 사용중인 새로운 액세스 확인 프레임 워크로 인해 java.lang.reflect.InaccessibleObjectException이 발생합니다.
Thor Lancaster

40

JDK 1.7에서는을 통해 시스템 CPU 및 메모리 사용량을 얻을 수 있습니다 com.sun.management.OperatingSystemMXBean. 와 (과) 다릅니다 java.lang.management.OperatingSystemMXBean.

long    getCommittedVirtualMemorySize()
Returns the amount of virtual memory that is guaranteed to be available to the running process in bytes, or -1 if this operation is not supported.

long    getFreePhysicalMemorySize()
Returns the amount of free physical memory in bytes.

long    getFreeSwapSpaceSize()
Returns the amount of free swap space in bytes.

double  getProcessCpuLoad()
Returns the "recent cpu usage" for the Java Virtual Machine process.

long    getProcessCpuTime()
Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.

double  getSystemCpuLoad()
Returns the "recent cpu usage" for the whole system.

long    getTotalPhysicalMemorySize()
Returns the total amount of physical memory in bytes.

long    getTotalSwapSpaceSize()
Returns the total amount of swap space in bytes.

5
이 히트와 그리워 보인다. FreeBSD 10 및 OpenJDK 8에서 CPU로드에 대해 -1 얻기
cen

이 질문을 확인하십시오 stackoverflow.com/q/19781087/1206998 . 효과를 내려면 몇 초가 걸립니다. (참고 : 시도하지 않았습니다)
Juh_

25

이것은 외부 API없이 완벽하게 작동합니다. 기본 Java 숨겨진 기능 :)

import com.sun.management.OperatingSystemMXBean;
...
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
                OperatingSystemMXBean.class);
// What % CPU load this current JVM is taking, from 0.0-1.0
System.out.println(osBean.getProcessCpuLoad());

// What % load the overall system is at, from 0.0-1.0
System.out.println(osBean.getSystemCpuLoad());

솔직히 이것이 최선의 대답이라고 생각하고 Linux에서 작동하므로 행복합니다.
ArsenArsen

1
두 번째 호출이 0.0을 나타내는 이유는 무엇입니까? OpenJDK v8에서.
vorburger

잊지 마십시오 : "import java.lang.management.ManagementFactory;"
Bernd

1
getProcessCpuLoad 및 getSystemCpuLoad는 -1을 반환합니다. 메신저 JDK 1.8를 사용하여
부락 Akyıldız

스레드 수를 얻는 방법이 없습니까? 왜 궁금해?
djangofan

16

이 매우 자세한 기사를 살펴보십시오 : http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

사용 된 CPU의 백분율을 얻으려면 간단한 수학 만 있으면됩니다.

MBeanServerConnection mbsc = ManagementFactory.getPlatformMBeanServer();

OperatingSystemMXBean osMBean = ManagementFactory.newPlatformMXBeanProxy(
mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);

long nanoBefore = System.nanoTime();
long cpuBefore = osMBean.getProcessCpuTime();

// Call an expensive task, or sleep if you are monitoring a remote process

long cpuAfter = osMBean.getProcessCpuTime();
long nanoAfter = System.nanoTime();

long percent;
if (nanoAfter > nanoBefore)
 percent = ((cpuAfter-cpuBefore)*100L)/
   (nanoAfter-nanoBefore);
else percent = 0;

System.out.println("Cpu usage: "+percent+"%");

참고 :를 가져 com.sun.management.OperatingSystemMXBean오지 말고 가져와야합니다 java.lang.management.OperatingSystemMXBean.


이것은 정말 좋은 대답입니다. 다른 모든 기술은 정말 이상하고 신뢰할 수없는 결과를 제공하지만 후행 평균이있는이 기술은 저에게 매력처럼 작용했습니다.
Fractaly

CPU 시간이 경과 시간보다 높으면 (100 % 이상 획득) 멀티 스레딩 때문입니까, 아니면 어떻게 이해합니까?
Lukas Hanacek

8

디스크 공간의 경우 Java 6이있는 경우 File 에서 getTotalSpacegetFreeSpace 메소드를 사용할 수 있습니다 . Java 6을 사용하지 않는 경우 Apache Commons IO 를 사용 하여 방법을 얻을 수 있다고 생각합니다 .

CPU 사용 또는 메모리 사용을 얻는 크로스 플랫폼 방법을 모르겠습니다.


6

이것의 많은 부분은 이미 JMX를 통해 사용 가능합니다. Java 5에는 JMX가 내장되어 있으며 JDK와 함께 JMX 콘솔 뷰어가 포함되어 있습니다.

JMX를 사용하여 수동으로 모니터하거나이 정보가 런타임에 필요한 경우 Java에서 JMX 명령을 호출 할 수 있습니다.



4
/* YOU CAN TRY THIS TOO */

import java.io.File;
 import java.lang.management.ManagementFactory;
// import java.lang.management.OperatingSystemMXBean;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.management.RuntimeMXBean;
 import java.io.*;
 import java.net.*;
 import java.util.*;
 import java.io.LineNumberReader;
 import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.util.Random;



 public class Pragati
 {

     public static void printUsage(Runtime runtime)
     {
     long total, free, used;
     int mb = 1024*1024;

     total = runtime.totalMemory();
     free = runtime.freeMemory();
     used = total - free;
     System.out.println("\nTotal Memory: " + total / mb + "MB");
     System.out.println(" Memory Used: " + used / mb + "MB");
     System.out.println(" Memory Free: " + free / mb + "MB");
     System.out.println("Percent Used: " + ((double)used/(double)total)*100 + "%");
     System.out.println("Percent Free: " + ((double)free/(double)total)*100 + "%");
    }
    public static void log(Object message)
         {
            System.out.println(message);
         }

        public static int calcCPU(long cpuStartTime, long elapsedStartTime, int cpuCount)
        {
             long end = System.nanoTime();
             long totalAvailCPUTime = cpuCount * (end-elapsedStartTime);
             long totalUsedCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()-cpuStartTime;
             //log("Total CPU Time:" + totalUsedCPUTime + " ns.");
             //log("Total Avail CPU Time:" + totalAvailCPUTime + " ns.");
             float per = ((float)totalUsedCPUTime*100)/(float)totalAvailCPUTime;
             log( per);
             return (int)per;
        }

        static boolean isPrime(int n)
        {
     // 2 is the smallest prime
            if (n <= 2)
            {
                return n == 2;
            }
     // even numbers other than 2 are not prime
            if (n % 2 == 0)
            {
                return false;
            }
     // check odd divisors from 3
     // to the square root of n
         for (int i = 3, end = (int)Math.sqrt(n); i <= end; i += 2)
         {
            if (n % i == 0)
         {
         return false;
        }
        }
 return true;
}
    public static void main(String [] args)
    {
            int mb = 1024*1024;
            int gb = 1024*1024*1024;
             /* PHYSICAL MEMORY USAGE */
             System.out.println("\n**** Sizes in Mega Bytes ****\n");
            com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
            //RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            //operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
            com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)
            java.lang.management.ManagementFactory.getOperatingSystemMXBean();
            long physicalMemorySize = os.getTotalPhysicalMemorySize();
            System.out.println("PHYSICAL MEMORY DETAILS \n");
            System.out.println("total physical memory : " + physicalMemorySize / mb + "MB ");
            long physicalfreeMemorySize = os.getFreePhysicalMemorySize();
            System.out.println("total free physical memory : " + physicalfreeMemorySize / mb + "MB");
            /* DISC SPACE DETAILS */
            File diskPartition = new File("C:");
            File diskPartition1 = new File("D:");
            File diskPartition2 = new File("E:");
            long totalCapacity = diskPartition.getTotalSpace() / gb;
            long totalCapacity1 = diskPartition1.getTotalSpace() / gb;
            double freePartitionSpace = diskPartition.getFreeSpace() / gb;
            double freePartitionSpace1 = diskPartition1.getFreeSpace() / gb;
            double freePartitionSpace2 = diskPartition2.getFreeSpace() / gb;
            double usablePatitionSpace = diskPartition.getUsableSpace() / gb;
            System.out.println("\n**** Sizes in Giga Bytes ****\n");
            System.out.println("DISC SPACE DETAILS \n");
            //System.out.println("Total C partition size : " + totalCapacity + "GB");
            //System.out.println("Usable Space : " + usablePatitionSpace + "GB");
            System.out.println("Free Space in drive C: : " + freePartitionSpace + "GB");
            System.out.println("Free Space in drive D:  : " + freePartitionSpace1 + "GB");
            System.out.println("Free Space in drive E: " + freePartitionSpace2 + "GB");
            if(freePartitionSpace <= totalCapacity%10 || freePartitionSpace1 <= totalCapacity1%10)
            {
                System.out.println(" !!!alert!!!!");
            }
            else
                System.out.println("no alert");

            Runtime runtime;
            byte[] bytes;
            System.out.println("\n \n**MEMORY DETAILS  ** \n");
            // Print initial memory usage.
            runtime = Runtime.getRuntime();
            printUsage(runtime);

            // Allocate a 1 Megabyte and print memory usage
            bytes = new byte[1024*1024];
            printUsage(runtime);

            bytes = null;
            // Invoke garbage collector to reclaim the allocated memory.
            runtime.gc();

            // Wait 5 seconds to give garbage collector a chance to run
            try {
            Thread.sleep(5000);
            } catch(InterruptedException e) {
            e.printStackTrace();
            return;
            }

            // Total memory will probably be the same as the second printUsage call,
            // but the free memory should be about 1 Megabyte larger if garbage
            // collection kicked in.
            printUsage(runtime);
            for(int i = 0; i < 30; i++)
                     {
                         long start = System.nanoTime();
                        // log(start);
                        //number of available processors;
                         int cpuCount = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
                         Random random = new Random(start);
                         int seed = Math.abs(random.nextInt());
                         log("\n \n CPU USAGE DETAILS \n\n");
                         log("Starting Test with " + cpuCount + " CPUs and random number:" + seed);
                         int primes = 10000;
                         //
                         long startCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();
                         start = System.nanoTime();
                         while(primes != 0)
                         {
                            if(isPrime(seed))
                            {
                                primes--;
                            }
                            seed++;

                        }
                         float cpuPercent = calcCPU(startCPUTime, start, cpuCount);
                         log("CPU USAGE : " + cpuPercent + " % ");


                         try
                         {
                             Thread.sleep(1000);
                         }
                         catch (InterruptedException e) {}
        }

            try
            {
                Thread.sleep(500);
            }`enter code here`
            catch (Exception ignored) { }
        }
    }

4

다음 코드는 Linux (아마도 Unix) 전용이지만 실제 프로젝트에서 작동합니다.

    private double getAverageValueByLinux() throws InterruptedException {
    try {

        long delay = 50;
        List<Double> listValues = new ArrayList<Double>();
        for (int i = 0; i < 100; i++) {
            long cput1 = getCpuT();
            Thread.sleep(delay);
            long cput2 = getCpuT();
            double cpuproc = (1000d * (cput2 - cput1)) / (double) delay;
            listValues.add(cpuproc);
        }
        listValues.remove(0);
        listValues.remove(listValues.size() - 1);
        double sum = 0.0;
        for (Double double1 : listValues) {
            sum += double1;
        }
        return sum / listValues.size();
    } catch (Exception e) {
        e.printStackTrace();
        return 0;
    }

}

private long getCpuT throws FileNotFoundException, IOException {
    BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
    String line = reader.readLine();
    Pattern pattern = Pattern.compile("\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)")
    Matcher m = pattern.matcher(line);

    long cpuUser = 0;
    long cpuSystem = 0;
    if (m.find()) {
        cpuUser = Long.parseLong(m.group(1));
        cpuSystem = Long.parseLong(m.group(3));
    }
    return cpuUser + cpuSystem;
}

1
이것은 내가 찾고 있었던,하지만 코드는 / proc 디렉토리 / 합계에서 CPU 정보를 찾기위한 정규식 패턴이없는 것을 실제로
DONAL 토빈을

패턴은 무엇입니까?
HCarrasko

3

다음과 같이 배치 파일 "Pc.bat"를 다음과 같이 입력하십시오. type perf -sc 1 "\ mukit \ processor (_Total) \ %% Processor Time"

MProcess 클래스를 사용할 수 있습니다.

/ *
 * Md. 무킷 하산
 * CSE-JU, 35
 ** / import java . io . *;

공개 클래스 MProcessor {

public MProcessor() { String s; try { Process ps = Runtime.getRuntime().exec("Pc.bat"); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); while((s = br.readLine()) != null) { System.out.println(s); } } catch( Exception ex ) { System.out.println(ex.toString()); } }

}

그런 다음 일부 문자열 조작 후 CPU를 사용하게됩니다. 다른 작업에도 동일한 프로세스를 사용할 수 있습니다.

-무킷 하산


1
나를 위해 (Win XP) 적절한 명령 줄은 다음과 같습니다. typeperf "\processor(_total)\% processor time"배치 파일에 넣으면 % 대신 % %를 사용하십시오. technet.microsoft.com/en-us/library/bb490960.aspx를 사용했습니다 .
tutejszy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.