Bagaimana cara saya memonitor penggunaan CPU, memori, dan disk komputer di Java?

180

Saya ingin memantau informasi sistem berikut di Jawa:

  • Penggunaan CPU saat ini ** (persen)
  • Memori yang tersedia * (gratis / total)
  • Ruang disk yang tersedia (gratis / total)

    * Perhatikan bahwa maksud saya keseluruhan memori tersedia untuk seluruh sistem, bukan hanya JVM.

Saya mencari solusi lintas platform (Linux, Mac, dan Windows) yang tidak bergantung pada kode saya sendiri yang memanggil program eksternal atau menggunakan JNI. Walaupun ini adalah opsi yang layak, saya lebih suka tidak memelihara kode spesifik OS sendiri jika seseorang sudah memiliki solusi yang lebih baik.

Jika ada perpustakaan gratis di luar sana yang melakukan ini dengan cara yang dapat diandalkan, lintas-platform, itu akan bagus (bahkan jika itu membuat panggilan eksternal atau menggunakan kode asli itu sendiri).

Semua saran sangatlah diapresiasi.

Untuk memperjelas, saya ingin mendapatkan penggunaan CPU saat ini untuk seluruh sistem, bukan hanya proses Java.

SIGAR API menyediakan semua fungsionalitas yang saya cari dalam satu paket, jadi ini adalah jawaban terbaik untuk pertanyaan saya sejauh ini. Namun, karena dilisensikan di bawah GPL, saya tidak dapat menggunakannya untuk tujuan asli saya (sumber tertutup, produk komersial). Mungkin saja Hyperic melisensikan SIGAR untuk penggunaan komersial, tetapi saya belum memeriksanya. Untuk proyek GPL saya, saya pasti akan mempertimbangkan SIGAR di masa depan.

Untuk kebutuhan saya saat ini, saya condong ke arah yang berikut:

  • Untuk penggunaan CPU, OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(load rata-rata per cpu)
  • Untuk memori, OperatingSystemMXBean.getTotalPhysicalMemorySize()danOperatingSystemMXBean.getFreePhysicalMemorySize()
  • Untuk ruang disk, File.getTotalSpace()danFile.getUsableSpace()

Keterbatasan:

The getSystemLoadAverage()dan disk yang metode ruang query hanya tersedia di bawah Jawa 6. Juga, beberapa fungsi JMX mungkin tidak tersedia untuk semua platform (yaitu itu telah melaporkan bahwa getSystemLoadAverage()pengembalian -1 pada Windows).

Meskipun awalnya dilisensikan di bawah GPL, itu telah diubah menjadi Apache 2.0 , yang umumnya dapat digunakan untuk produk komersial, sumber tertutup.

David Crow
sumber
Untuk memperjelas, api sigar memberi Anda info sistem. Jika Anda ingin info jvm gunakan JMX.
Matt Cummings
SIGAR berada di bawah GPL tidak menghalangi Anda untuk menggunakannya, itu hanya berarti Anda harus menghubungi penulis dan meminta lisensi alternatif. Penulis sering senang menerima sedikit biaya dan mengizinkan lisensi komersial.
Alec Thomas
7
Sejak versi 1.6.4 SIGAR menggunakan lisensi Apache.
Soundlink
Anda tahu cara mendapatkan beban untuk setiap prosesor individu?
zcaudate

Jawaban:

67

Sejalan dengan apa yang saya sebutkan di posting ini . Saya sarankan Anda menggunakan SIGAR API . Saya menggunakan SIGAR API di salah satu aplikasi saya sendiri dan ini sangat bagus. Anda akan menemukannya stabil, didukung dengan baik, dan penuh dengan contoh-contoh berguna. Ini adalah open-source dengan lisensi GPL 2 Apache 2.0. Saksikan berikut ini. Saya merasa itu akan memenuhi kebutuhan Anda.

Menggunakan Java dan Sigar API Anda bisa mendapatkan Memori, CPU, Disk, Beban Rata-Rata, info dan metrik Antarmuka Jaringan, informasi Tabel Proses, info Rute, dll.

Matt Cummings
sumber
14
Hati-hati saat menggunakan Sigar, ada masalah pada mesin x64 ... stackoverflow.com/questions/23405832/… dan tampaknya perpustakaan tidak diperbarui sejak 2010
Alvaro
56

Berikut ini seharusnya memberi Anda CPU dan RAM. Lihat ManagementFactory untuk lebih jelasnya.

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
}
Eugene Yokota
sumber
3
Contoh output untuk kode di atas. Kode ini berfungsi di Java 1.5. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r
AFAIK getProcessCpuTime = 390625000 hanya berapa lama utas itu telah berjalan. Itu tidak benar-benar berguna untuk menentukan penggunaan prosesor
MikeNereson
2
Tidak yakin itu benar-benar dapat diandalkan. Pada Windows XP dengan memori fisik 4GB hanya melaporkan 2GB (diuji dengan Java 6 dan Java 7). Ukuran total swap juga salah.
Emmanuel Bourg
4
@EmmanuelBourg hanya untuk mendokumentasikan bagi orang-orang yang melihat topik ini, ada bug yang terkait dengan ini.
Sérgio Michels
2
Metode ini bekerja sangat baik sampai Java 9, sekarang melempar java.lang.reflect.InaccessibleObjectException karena kerangka kerja pemeriksaan akses baru yang digunakan Java.
Thor Lancaster
40

Di JDK 1.7, Anda bisa mendapatkan CPU sistem dan penggunaan memori melalui com.sun.management.OperatingSystemMXBean. Ini berbeda dari 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.
Gp2you
sumber
5
Sepertinya ini adalah hit and miss. Mendapatkan -1 untuk beban CPU pada FreeBSD 10 dan OpenJDK 8.
cen
periksa pertanyaan ini stackoverflow.com/q/19781087/1206998 . itu mengatakan bahwa butuh beberapa detik untuk menjadi efektif. (catatan: Saya tidak mencoba)
Juh_
25

Ini berfungsi dengan baik untuk saya tanpa API eksternal, hanya fitur tersembunyi Java asli :)

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());
bizzr3
sumber
Jujur saya temukan ini jawaban terbaik, bekerja di Linux jadi saya senang teman.
ArsenArsen
1
ada petunjuk mengapa doa kedua menunjukkan 0,0? Pada OpenJDK v8.
vorburger
Jangan lupa: "import java.lang.management.ManagementFactory;"
Bernd
1
getProcessCpuLoad dan getSystemCpuLoad mengembalikan -1 dari saya. im menggunakan jdk 1.8
Burak Akyıldız
Itu tidak memiliki metode untuk mendapatkan jumlah Thread? Hanya ingin tahu mengapa?
djangofan
16

Lihat artikel yang sangat membosankan ini: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

Untuk mendapatkan persentase CPU yang digunakan, yang Anda butuhkan hanyalah beberapa matematika sederhana:

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

Catatan: Anda harus mengimpor com.sun.management.OperatingSystemMXBeandan tidak java.lang.management.OperatingSystemMXBean.

ludovicc
sumber
Ini jawaban yang sangat bagus. Semua teknik lain memberikan hasil yang benar-benar aneh dan tidak dapat diandalkan, tetapi yang ini dengan beberapa rata-rata tertinggal bekerja seperti pesona bagi saya.
Fractaly
Ketika waktu cpu lebih tinggi dari waktu yang telah berlalu (saya mendapatkan lebih dari 100%), apakah itu hanya karena multithreading, atau bagaimana memahaminya?
Lukas Hanacek
8

Untuk ruang disk, jika Anda memiliki Java 6, Anda dapat menggunakan metode getTotalSpace dan getFreeSpace di File. Jika Anda tidak menggunakan Java 6, saya yakin Anda dapat menggunakan Apache Commons IO untuk mendapatkan beberapa cara di sana.

Saya tidak tahu ada cara lintas platform untuk mendapatkan penggunaan CPU atau penggunaan memori.

Matt Sheppard
sumber
6

Banyak dari ini sudah tersedia melalui JMX. Dengan Java 5, JMX built-in dan mereka termasuk penampil konsol JMX dengan JDK.

Anda dapat menggunakan JMX untuk memonitor secara manual, atau menjalankan perintah JMX dari Java jika Anda memerlukan informasi ini di run-time Anda sendiri.

Jason Cohen
sumber
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) { }
        }
    }
pragati
sumber
4

Kode berikut ini hanya Linux (mungkin Unix), tetapi bekerja dalam proyek nyata.

    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;
}
Charis Theo
sumber
1
Ini sebenarnya yang saya cari, tetapi kode tersebut tidak memiliki pola REGEX untuk menemukan informasi CPU dari / proc / stat
Donal Tobin
apa polanya ??
HCarrasko
3

Buat file batch "Pc.bat" sebagai, typeperf -sc 1 "\ mukit \ processor (_Total) \ %% Waktu Prosesor"

Anda dapat menggunakan kelas MProcess,

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

MProcessor kelas publik {

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

}

Kemudian setelah beberapa manipulasi string, Anda mendapatkan penggunaan CPU. Anda dapat menggunakan proses yang sama untuk tugas-tugas lain.

--Mukit Hasan

Md. Mukit Hasan
sumber
1
bagi saya (Win XP) baris perintah yang tepat adalah: typeperf "\processor(_total)\% processor time"Jika Anda memasukkannya ke file batch, gunakan %% bukan%. Saya menggunakan technet.microsoft.com/en-us/library/bb490960.aspx .
tutejszy