2008-09-06 35 views
137

Tôi muốn giám sát các hệ thống thông tin sau đây trong Java:Làm cách nào để theo dõi CPU, bộ nhớ và mức sử dụng đĩa của máy tính trong Java?

  • sử dụng CPU hiện tại ** (phần trăm)
  • sẵn bộ nhớ * (miễn phí/tổng số)
  • không gian đĩa có sẵn (miễn phí/tổng số)

    * 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ỉ là JVM.

Tôi đang tìm 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 lựa chọn khả thi, tôi không muốn 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ó thư viện miễn phí ở đó thực hiện điều này một cách đáng tin cậy, đa nền tảng, điều đó sẽ tuyệt vời (ngay cả khi thực hiện cuộc gọi bên ngoài hoặc sử dụng mã gốc).

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

Để làm rõ, tôi muốn 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ả chức năng tôi đang tìm kiếm trong một gói, do đó, đó là câu trả lời hay nhất cho câu hỏi của tôi cho đến thời điểm này. Tuy nhiên, do nó đượ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ó khả năng Hyperic có thể cấp phép 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 nghiêng về phía sau:

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

Hạn chế:

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

Mặc dù ban đầu được cấp phép theo GPL, nó has been changed đến Apache 2.0, thường có thể được sử dụng cho nguồn đóng, sản phẩm thương mại.

+0

Để làm rõ, các API SIGAR được cho bạn thông tin hệ thống. Nếu bạn muốn thông tin jvm sử dụng JMX. –

+0

SIGAR thuộc GPL không ngăn cản bạn sử dụng nó, nó 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 mừng chấp nhận một khoản phí nhỏ và cho phép cấp phép thương mại. –

+4

Kể từ phiên bản 1.6.4 SIGAR đang sử dụng giấy phép Apache. – Soundlink

Trả lời

59

Dọc theo dòng những gì tôi đã đề cập in this post. Tôi khuyên bạn nên sử dụng SIGAR API. Tôi sử dụng API SIGAR trong một trong các ứ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à đầy đủ các ví dụ hữu ích. Đây là mã nguồn mở với giấy phép số 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à các API SIGAR bạn có thể nhận được bộ nhớ, CPU, đĩa, Load-trung bình, thông tin giao diện mạng và số liệu, xử lý thông tin Bảng, thông tin Route vv

+8

Hãy cẩn thận khi sử dụng Sigar, có vấn đề về máy x64 ... http://stackoverflow.com/questions/23405832/sigar-1-6-4-is-useless-exception-access-violation và có vẻ như thư viện không được cập nhật kể từ năm 2010 – Alvaro

8

Đối với dung lượng ổ đĩa, nếu bạn có Java 6, bạn có thể sử dụng các phương pháp getTotalSpacegetFreeSpace trên Tệp. Nếu bạn không sử dụng Java 6, tôi tin rằng bạn có thể sử dụng Apache Commons IO để nhận một số cách ở đó.

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

43

Sau đây được cho là CPU và RAM của bạn. 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 hoạt động trên Java 1.5. getCommittedVirtualMemorySize = 28.622.848 getFreePhysicalMemorySize = 228.462.592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390.625.000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295 – blak3r

+0

AFAIK getProcessCpuTime = 390.625.000 chỉ bao lâu chủ đề đó đã được chạy. Điều đó không thực sự hữu ích để xác định cách sử dụng bộ vi xử lý – MikeNereson

+1

Không chắc chắn 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 hoán đổi cũng sai. –

5

Rất nhiều 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 một trình xem giao diện đ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.

3

Mã sau đây là Linux (có thể là Unix), nhưng nó hoạt động trong một dự án thực.

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(pattern); 
      Thread.sleep(delay); 
      long cput2 = getCpuT(pattern); 
      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(Pattern pattern) throws FileNotFoundException, IOException { 
    BufferedReader reader = new BufferedReader(new FileReader("/proc/stat")); 
    String line = reader.readLine(); 
    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; 
} 
+0

Đây thực sự là những gì tôi đang tìm kiếm, nhưng mã thiếu mẫu REGEX để tìm thông tin cpu từ/proc/stat –

+0

mẫu là gì ?? – HCarrasko

3

Thực hiện một tập tin thực thi "Pc.bat" như, typeperf -sc 1 "\ mukit \ xử lý (_Total) \ %% Processor Time"

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

 
/* 
*Md. Mukit Hasan 
*CSE-JU,35 
**/ 
import java.io.*;

public class 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 khi một số thao tác chuỗi, bạn sẽ có được việc sử dụng CPU. Bạn có thể sử dụng quy trình tương tự cho các tác vụ khác.

--Mukit Hasan

+1

cho tôi (Win XP) dòng lệnh thích hợp là: 'typeperf" \ processor (_total) \% thời gian xử lý "' Nếu bạn đặt nó vào tập tin batch, sử dụng %% thay vì%. Tôi đã sử dụng [technet.microsoft.com/en-us/library/bb490960.aspx] (http://technet.microsoft.com/en-us/library/bb490960.aspx). – tutejszy

14

Có xem xét bài viết rất detailled này: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

Để có được tỷ lệ phần trăm CPU sử dụng, bạn chỉ cần có một số toán học đơ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.OperatingSystemMXBean và không phải java.lang.management.OperatingSystemMXBean.

23

Trong JDK 1.7, bạn có thể sử dụng CPU hệ thống và sử dụng bộ nhớ qua com.sun.management.OperatingSystemMXBean. Số này khác với 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. 
+0

Đang sử dụng java1.8. nhập java.lang.management.ManagementFactory; nhập java.lang.management.OperatingSystemMXBean; public class Test { \t public static void main (String [] a) { \t \t OperatingSystemMXBean oSMXBean = ManagementFactory.getOperatingSystemMXBean(); \t \t \t} } Trong mã trên không thể tìm thấy các phương pháp được chỉ định. Tôi đã kiểm tra các tài liệu có phương pháp có sẵn cho lớp này. Nhưng tôi không thể tìm thấy trong mã. Hãy giúp tôi; – Abdul

+3

Dường như điều này bị đánh và bỏ lỡ. Bắt -1 cho CPU tải trên FreeBSD 10 và OpenJDK 8. – cen

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) { } 
     } 
    } 
12

này làm việc cho tôi một cách hoàn hảo mà không cần bất kỳ API bên ngoài, chỉ có nguồn gốc Java ẩn tính năng :)

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

Tôi thành thật tìm thấy câu trả lời tốt nhất, làm việc trên Linux vì vậy tôi là fella hạnh phúc. – ArsenArsen

+1

bất kỳ đầu mối nào tại sao lệnh gọi thứ hai hiển thị 0.0? Trên OpenJDK v8. – vorburger

+0

Đừng quên: "nhập java.lang.management.ManagementFactory;" –

Các vấn đề liên quan