Làm cách nào để theo dõi việc sử dụng CPU, bộ nhớ và ổ đĩa của máy tính trong Java?


180

Tôi muốn theo dõi thông tin hệ thống sau đây trong Java:

  • Sử dụng CPU hiện tại ** (phần trăm)
  • Bộ nhớ khả dụng * (miễn phí / tổng số)
  • Dung lượng đĩa trống (miễn phí / tổng cộng)

    * Lưu ý rằng tôi có nghĩa là bộ nhớ tổng thể có sẵn cho toàn bộ hệ thống, không chỉ JVM.

Tôi đang tìm kiếm một giải pháp đa nền tảng (Linux, Mac và Windows) không dựa vào mã của riêng tôi để gọi các chương trình bên ngoài hoặc sử dụng JNI. Mặc dù đây là những tùy chọn khả thi, tôi không muốn tự mình duy trì mã dành riêng cho hệ điều hành nếu ai đó đã có giải pháp tốt hơn.

Nếu có một thư viện miễn phí ngoài đó thực hiện điều này theo cách đa nền tảng, đáng tin cậy, thì đó sẽ là điều tuyệt vời (ngay cả khi nó thực hiện các cuộc gọi bên ngoài hoặc sử dụng chính mã nguồn gốc).

Bất kỳ đề xuất đều được đánh giá cao.

Để làm rõ, tôi muốn có được mức sử dụng CPU hiện tại cho toàn bộ hệ thống, không chỉ các quy trình Java.

API SIGAR cung cấp tất cả các chức năng tôi đang tìm kiếm trong một gói, vì vậy đây là câu trả lời tốt nhất cho câu hỏi của tôi cho đến nay. Tuy nhiên, do được cấp phép theo GPL, tôi không thể sử dụng nó cho mục đích ban đầu của mình (một nguồn đóng, sản phẩm thương mại). Có thể Hyperic có thể cấp phép cho SIGAR cho mục đích thương mại, nhưng tôi chưa xem xét nó. Đối với các dự án GPL của tôi, tôi chắc chắn sẽ xem xét SIGAR trong tương lai.

Đối với nhu cầu hiện tại của tôi, tôi đang nghiêng về những điều sau đây:

  • Đối với việc sử dụng CPU, OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(tải trung bình trên mỗi cpu)
  • Dành cho bộ nhớ OperatingSystemMXBean.getTotalPhysicalMemorySize()OperatingSystemMXBean.getFreePhysicalMemorySize()
  • Đối với không gian đĩa File.getTotalSpace()File.getUsableSpace()

Hạn chế:

Các getSystemLoadAverage()phương thức truy vấn không gian đĩa và ổ đĩa chỉ khả dụng trong Java 6. Ngoài ra, một số chức năng JMX có thể không khả dụng cho tất cả các nền tảng (tức là đã được báo cáo getSystemLoadAverage()trả về -1 trên Windows).

Mặc dù ban đầu được cấp phép theo GPL, nó đã được đổi thành Apache 2.0 , thường được sử dụng cho các sản phẩm thương mại, nguồn đóng.


Để làm rõ, sigar api lấy cho bạn thông tin hệ thống. Nếu bạn muốn thông tin jvm sử dụng JMX.
Matt Cummings

SIGAR thuộc GPL không ngăn cản bạn sử dụng nó, điều đó chỉ có nghĩa là bạn phải liên hệ với các tác giả và yêu cầu cấp phép thay thế. Các tác giả thường vui vẻ chấp nhận một khoản phí nhỏ và cho phép cấp phép thương mại.
Alec Thomas

7
Vì phiên bản 1.6.4 SIGAR đang sử dụng giấy phép Apache.
Soundlink

Bạn có biết làm thế nào để tải cho mỗi bộ xử lý riêng lẻ?
zcaudate

Câu trả lời:


67

Dọc theo những gì tôi đã đề cập trong bài viết này . Tôi khuyên bạn nên sử dụng API SIGAR . Tôi sử dụng API SIGAR trong một trong những ứng dụng của riêng tôi và nó rất tuyệt. Bạn sẽ thấy nó ổn định, được hỗ trợ tốt và có đầy đủ các ví dụ hữu ích. Nó là nguồn mở với giấy phép GPL 2 Apache 2.0. Kiểm tra nó ra. Tôi có cảm giác nó sẽ đáp ứng nhu cầu của bạn.

Sử dụng Java và API Sigar, bạn có thể nhận được Bộ nhớ, CPU, Đĩa, Trung bình tải, thông tin và số liệu Giao diện mạng, thông tin Bảng quy trình, Thông tin tuyến đường, v.v.


14
Hãy cẩn thận khi sử dụng Sigar, có vấn đề trên các máy x64 ... stackoverflow.com/questions/23405832/ triệt và có vẻ như thư viện không được cập nhật kể từ năm 2010
Alvaro

56

Sau đây được cho là có CPU và RAM. Xem ManagementFactory để biết thêm chi tiết.

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
Đầu ra mẫu cho mã ở trên. Mã này không hoạt động trên Java 1.5. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r

AFAIK getProcessCpuTime = 390625000 chỉ là thời gian mà chủ đề đó đã chạy. Điều đó không thực sự hữu ích để xác định việc sử dụng bộ xử lý
MikeNereson

2
Không chắc nó thực sự đáng tin cậy. Trên Windows XP với 4GB bộ nhớ vật lý, nó chỉ báo cáo 2GB (được thử nghiệm với Java 6 và Java 7). Tổng kích thước trao đổi cũng sai.
Emmanuel Bourg

4
@EmmanuelBourg chỉ để làm tài liệu cho những người xem chủ đề này, có một lỗi liên quan đến vấn đề này.
Sérgio Michels

2
Phương thức này hoạt động rất tốt cho đến Java 9, giờ đây nó ném java.lang.reflect.InaccessibleObjectException do khung kiểm tra truy cập mới mà Java đang sử dụng.
Thor Lancaster

40

Trong JDK 1.7, bạn có thể nhận được CPU hệ thống và sử dụng bộ nhớ thông qua com.sun.management.OperatingSystemMXBean. Điều này khác hơn 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
Có vẻ như điều này là trúng và bỏ lỡ. Nhận -1 cho tải CPU trên FreeBSD 10 và OpenJDK 8.
cen

kiểm tra câu hỏi này stackoverflow.com/q/19781087/1206998 . Nó nói rằng phải mất vài giây để có hiệu quả. (lưu ý: Tôi đã không thử)
Juh_

25

Điều này hoạt động hoàn hảo với tôi mà không cần bất kỳ API bên ngoài nào, chỉ là tính năng ẩn Java gốc :)

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

Tôi thành thật tìm thấy câu trả lời tốt nhất này, hoạt động trên Linux vì vậy tôi rất vui.
ArsenArsen

1
bất kỳ manh mối tại sao một lời mời thứ 2 hiển thị 0,0? Trên OpenJDK v8.
vorburger

Đừng quên: "nhập java.lang.man quản lý. Quản lýFactory;"
Bernd

1
getProcessCpuLoad và getSystemCpuLoad trả về -1 cho tôi. tôi đang sử dụng jdk 1.8
Burak Akyıldız

Nó không có một phương pháp để có được số lượng chủ đề? Chỉ tự hỏi tại sao?
djangofan

16

Hãy xem bài viết rất đáng ghét này: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuni INTERNalclasstogetJVMCPUtime

Để có được tỷ lệ phần trăm của CPU được sử dụng, tất cả những gì bạn cần là một số phép toán đơn giản:

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+"%");

Lưu ý: Bạn phải nhập com.sun.management.OperatingSystemMXBeanvà không java.lang.management.OperatingSystemMXBean.


Đây là một câu trả lời thực sự tốt. Tất cả các kỹ thuật khác cho kết quả thực sự kỳ lạ và không đáng tin cậy, nhưng kỹ thuật này với một số trung bình kéo dài hoạt động như một cơ duyên đối với tôi.
Fractaly

Khi thời gian cpu cao hơn thời gian đã trôi qua (tôi nhận được hơn 100%), có phải chỉ vì đa luồng, hoặc làm thế nào để hiểu nó?
Lukas Hanacek ngày

8

Đối với không gian đĩa, nếu bạn có Java 6, bạn có thể sử dụng getTotalSpacegetFreeSpace phương pháp trên tập tin. Nếu bạn không dùng Java 6, tôi tin rằng bạn có thể sử dụng Apache Commons IO để tìm đường đến đó.

Tôi không biết bất kỳ cách đa nền tảng nào để sử dụng CPU hoặc sử dụng Bộ nhớ mà tôi sợ.


6

Rất nhiều thứ này đã có sẵn thông qua JMX. Với Java 5, JMX được tích hợp sẵn và chúng bao gồm trình xem bảng điều khiển JMX với JDK.

Bạn có thể sử dụng JMX để theo dõi thủ công hoặc gọi các lệnh JMX từ Java nếu bạn cần thông tin này trong thời gian chạy của riêng bạn.



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

Đoạn mã sau chỉ là Linux (có thể là Unix), nhưng nó hoạt động trong một dự án thực sự.

    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
Đây thực sự là những gì tôi đang tìm kiếm, nhưng mã bị thiếu mẫu REGEX để tìm thông tin cpu từ / Proc / stat
Donal Tobin

mô hình là gì ??
HCarrasko

3

Tạo một tệp bó "Pc.bat" dưới dạng, typeperf -sc 1 "\ mukit \ bộ xử lý (_Total) \ %% Thời gian xử lý"

Bạn có thể sử dụng lớp MProcess,

/ *
 * Md. Mukit Hasan
 * CSE-JU, 35
 ** / nhập java . io . *;

lớp công khai 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()); } }

}

Sau đó, sau một số thao tác chuỗi, bạn có được CPU sử dụng. Bạn có thể sử dụng quy trình tương tự cho các nhiệm vụ khác.

--Mukit Hasan


1
đối với tôi (Win XP) dòng lệnh thích hợp là: typeperf "\processor(_total)\% processor time"Nếu bạn đặt nó vào tệp bó, hãy sử dụng %% thay vì%. Tôi đã sử dụng technet.microsoft.com/en-us/l Library / bb490960.aspx .
tutejszy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.