ฉันจะตรวจสอบการใช้งาน CPU หน่วยความจำและการใช้ดิสก์ใน Java ได้อย่างไร


180

ฉันต้องการตรวจสอบข้อมูลระบบต่อไปนี้ใน Java:

  • การใช้งาน CPU ปัจจุบัน ** (เปอร์เซ็นต์)
  • หน่วยความจำที่มี * (ฟรี / ทั้งหมด)
  • พื้นที่ว่างในดิสก์ (ฟรี / ทั้งหมด)

    * โปรดทราบว่าฉันหมายถึงหน่วยความจำโดยรวมที่มีให้สำหรับทั้งระบบไม่ใช่เฉพาะ JVM

ฉันกำลังมองหาโซลูชันข้ามแพลตฟอร์ม (Linux, Mac และ Windows) ที่ไม่พึ่งพารหัสของตัวเองที่เรียกใช้โปรแกรมภายนอกหรือใช้ JNI แม้ว่าสิ่งเหล่านี้เป็นตัวเลือกที่ทำงานได้ แต่ฉันไม่ต้องการบำรุงรักษาโค้ดเฉพาะระบบปฏิบัติการด้วยตนเองถ้ามีคนที่มีทางออกที่ดีกว่า

หากมีไลบรารี่ฟรีที่ทำสิ่งนี้ในลักษณะข้ามแพลตฟอร์มที่เชื่อถือได้นั่นจะยอดเยี่ยม (แม้ว่าจะทำการโทรภายนอกหรือใช้รหัสเนทีฟเอง)

ข้อเสนอแนะใด ๆ ที่ชื่นชมมาก

เพื่อชี้แจงฉันต้องการได้รับการใช้งาน CPU ปัจจุบันสำหรับทั้งระบบไม่ใช่เฉพาะกระบวนการ Java (es)

SIGAR API ให้ฟังก์ชั่นทั้งหมดที่ฉันกำลังมองหาในแพ็คเกจเดียวดังนั้นมันจึงเป็นคำตอบที่ดีที่สุดสำหรับคำถามของฉัน อย่างไรก็ตามเนื่องจากได้รับอนุญาตภายใต้ GPL ฉันไม่สามารถใช้เพื่อวัตถุประสงค์ดั้งเดิมของฉันได้ (แหล่งข้อมูลปิดผลิตภัณฑ์เชิงพาณิชย์) อาจเป็นไปได้ว่า Hyperic อาจให้สิทธิ์ SIGAR เพื่อการใช้งานเชิงพาณิชย์ แต่ฉันไม่ได้ตรวจสอบ สำหรับโครงการ GPL ของฉันฉันจะพิจารณา SIGAR ในอนาคต

สำหรับความต้องการในปัจจุบันของฉันฉันกำลังโน้มตัวต่อไปนี้:

  • สำหรับการใช้งาน CPU OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(โหลดเฉลี่ยต่อ cpu)
  • สำหรับหน่วยความจำOperatingSystemMXBean.getTotalPhysicalMemorySize()และOperatingSystemMXBean.getFreePhysicalMemorySize()
  • สำหรับพื้นที่ดิสก์File.getTotalSpace()และFile.getUsableSpace()

ข้อ จำกัด :

getSystemLoadAverage()และพื้นที่ดิสก์สอบถามวิธีการนี้ใช้ได้เฉพาะภายใต้ Java 6. นอกจากนี้บางฟังก์ชันการทำงาน JMX อาจไม่สามารถใช้ได้กับทุกแพลตฟอร์ม (คือมันได้รับรายงานว่าgetSystemLoadAverage()ผลตอบแทน -1 ใน Windows)

แม้ว่าจะได้รับสิทธิ์การใช้งานภายใต้ GPL แต่เดิมได้ถูกเปลี่ยนเป็นApache 2.0ซึ่งโดยทั่วไปสามารถใช้สำหรับผลิตภัณฑ์แบบปิดแหล่งที่มา


เพื่อชี้แจงซิการ์ api ทำให้คุณได้รับข้อมูลระบบ หากคุณต้องการข้อมูล jvm ให้ใช้ JMX
Matt Cummings

SIGAR ที่อยู่ภายใต้ GPL ไม่ได้ขัดขวางคุณจากการใช้งานมันหมายความว่าคุณต้องติดต่อผู้เขียนและขอใบอนุญาตทางเลือกอื่น ผู้เขียนมักจะยินดีที่จะยอมรับค่าธรรมเนียมเล็กน้อยและอนุญาตให้มีใบอนุญาตเชิงพาณิชย์
อเล็กซ์โทมัส

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
ไม่แน่ใจว่ามันเชื่อถือได้จริง บน Windows XP ที่มีหน่วยความจำกายภาพ 4GB จะรายงานเพียง 2GB (ทดสอบกับ Java 6 และ Java 7) ขนาดการแลกเปลี่ยนโดยรวมก็ไม่ถูกต้องเช่นกัน
Emmanuel Bourg

4
@EmmanuelBourg เพียงเพื่อจัดทำเอกสารสำหรับคนที่เห็นหัวข้อนี้มีข้อบกพร่องที่เกี่ยวข้องกับเรื่องนี้
Sérgio Michels

2
วิธีนี้ใช้งานได้ดีจนถึง Java 9 ในตอนนี้มันจะพ่น java.lang.reflect.InaccessibleObjectException เนื่องจากเฟรมเวิร์กการตรวจสอบการเข้าถึงใหม่ที่ Java กำลังใช้อยู่
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
ดูเหมือนว่าเรื่องนี้จะถูกตีและพลาด การเดินทาง -1 สำหรับการโหลดของ CPU บน FreeBSD 10 และ OpenJDK 8.
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
เบาะแสใด ๆ ว่าทำไมการร้องขอครั้งที่ 2 แสดง 0.0? บน OpenJDK v8
vorburger

อย่าลืม: "import java.lang.management.ManagementFactory;"
Bernd

1
getProcessCpuLoad และ getSystemCpuLoad คืนค่า -1 ให้ฉัน ฉันใช้ jdk 1.8
Burak 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.OperatingSystemMXBeanjava.lang.management.OperatingSystemMXBean


นี่เป็นคำตอบที่ดีจริงๆ เทคนิคอื่น ๆ ทั้งหมดให้ผลลัพธ์ที่แปลกและไม่น่าเชื่อถือจริง ๆ แต่เทคนิคนี้มีค่าเฉลี่ยต่อท้ายบางอย่างทำงานได้เหมือนเสน่ห์สำหรับฉัน
Fractaly

เมื่อเวลา cpu สูงกว่าเวลาที่ผ่านไป (ฉันได้รับมากกว่า 100%) มันเป็นเพราะมัลติเธรดหรือการทำความเข้าใจ
Lukas Hanacek

8

สำหรับพื้นที่ดิสก์ถ้าคุณมี Java 6 คุณสามารถใช้เมธอด getTotalSpaceและgetFreeSpaceบนไฟล์ หากคุณไม่ได้ใช้ Java 6 ฉันเชื่อว่าคุณสามารถใช้Apache Commons IOเพื่อไปยังที่นั่น

ฉันไม่รู้วิธีข้ามแพลตฟอร์มเพื่อรับการใช้งาน CPU หรือการใช้หน่วยความจำฉันกลัว


6

สิ่งนี้มีอยู่มากมายผ่านทาง JMX ด้วย Java 5, JMX นั้นมีอยู่แล้วภายในและจะรวมตัวแสดงคอนโซล JMX กับ JDK

คุณสามารถใช้ JMX เพื่อตรวจสอบด้วยตนเองหรือเรียกใช้คำสั่ง JMX จาก Java หากคุณต้องการข้อมูลนี้ในเวลาทำงานของคุณเอง


6

คำตอบที่ได้รับการยอมรับในปี 2008 แนะนำให้ SIGAR อย่างไรก็ตามเป็นความคิดเห็นจาก 2014 (@Alvaro) พูดว่า:

ระวังเมื่อใช้ Sigar มีปัญหากับเครื่อง x64 ... Sigar 1.6.4 ล้มเหลว: EXCEPTION_ACCESS_VIOLATIONและดูเหมือนว่าไลบรารีจะไม่ได้รับการอัปเดตตั้งแต่ปี 2010

คำแนะนำของฉันคือการใช้ https://github.com/oshi/oshi

หรือคำตอบดังกล่าวข้างต้น


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
นี่คือสิ่งที่ฉันกำลังมองหา แต่รหัสไม่มีรูปแบบ REGEX สำหรับการค้นหาข้อมูลซีพียูจาก / proc / stat
Donal Tobin

รูปแบบคืออะไร?
HCarrasko

3

สร้างไฟล์แบตช์ "Pc.bat" เป็น typeperf -sc 1 "\ mukit \ processor (_Total) \ %% เวลาตัวประมวลผล"

คุณสามารถใช้คลาส MProcess

/ *
 * Md Mukit Hasan
 * CSE-JU 35
 ** / นำเข้าจาวา 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.