Java'da bilgisayarın CPU, bellek ve disk kullanımını nasıl izlerim?


180

Java'da aşağıdaki sistem bilgilerini izlemek istiyorum:

  • Geçerli CPU kullanımı ** (yüzde)
  • Kullanılabilir bellek * (boş / toplam)
  • Kullanılabilir disk alanı (boş / toplam)

    * Sadece JVM için değil, tüm sistem için kullanılabilir toplam bellek anlamına geldiğimi unutmayın.

Harici programları çağıran veya JNI kullanan kendi koduma dayanmayan bir platformlar arası çözüm (Linux, Mac ve Windows) arıyorum. Bunlar uygulanabilir seçenekler olmasına rağmen, birisinin zaten daha iyi bir çözümü varsa, işletim sistemine özgü kodu kendim korumamayı tercih ederim.

Dışarıda bunu güvenilir, platformlar arası bir şekilde yapan ücretsiz bir kütüphane varsa, bu harika olurdu (harici aramalar yapsa veya yerel kod kullansa bile).

Herhangi bir öneriniz çok takdir edilmektedir.

Açıklığa kavuşturmak için, sadece Java işlem (ler) i değil, tüm sistem için geçerli CPU kullanımını almak istiyorum.

SIGAR API, aradığım tüm işlevleri tek bir pakette sunar, bu yüzden şu ana kadar sorumun en iyi yanıtıdır. Ancak, GPL kapsamında lisanslandığı için, orijinal amacım (kapalı kaynak, ticari ürün) için kullanamıyorum. Hyperic'in SIGAR'ı ticari kullanım için lisanslaması mümkündür, ancak buna bakmadım. GPL projelerim için kesinlikle SIGAR'ı gelecekte ele alacağım.

Şu anki ihtiyaçlarım için aşağıdakilere yöneliyorum:

  • CPU kullanımı için, OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(işlemci başına yük ortalaması)
  • Bellek için OperatingSystemMXBean.getTotalPhysicalMemorySize()veOperatingSystemMXBean.getFreePhysicalMemorySize()
  • Disk alanı için File.getTotalSpace()veFile.getUsableSpace()

Sınırlamalar:

getSystemLoadAverage()Ve disk alanı sorgulama yöntemleri Ayrıca Java 6. altında, bazı JMX işlevselliği tüm platformlar için geçerli olmayabilir ancak mevcut (yani o bildirilmiş olduğu getSystemLoadAverage()döner -1 Windows üzerinde).

Aslen GPL lisanslı olsa da, değişmiştir için Apache 2.0 genellikle kapalı bir kaynaktan, ticari ürünler için de kullanılabilir.


Açıklığa kavuşturmak için, sigar api size sistem bilgisini verir. Jvm bilgi istiyorsanız JMX kullanın.
Matt Cummings

SIGAR'ın GPL kapsamında olması, onu kullanmanızı engellemez, sadece yazarlarla iletişime geçmeniz ve alternatif lisans istemeniz gerektiği anlamına gelir. Yazarlar genellikle küçük bir ücreti kabul etmekten ve ticari lisanslamaya izin vermekten mutluluk duyarlar.
Alec Thomas

7
1.6.4 sürümünden beri SIGAR Apache lisansını kullanmaktadır.
Soundlink

Her bir işlemci için yükü nasıl alacağınızı biliyor musunuz?
zcaudate

Yanıtlar:


67

Bu yazıda bahsettiğim şeyler boyunca . SIGAR API'sını kullanmanızı öneririm . SIGAR API'sını kendi uygulamalarımdan birinde kullanıyorum ve harika. İstikrarlı, iyi desteklenmiş ve faydalı örneklerle dolu olduğunu göreceksiniz. GPL 2 Apache 2.0 lisansı ile açık kaynak kodludur . Bunu kontrol et. İhtiyaçlarınızı karşılayacağını hissediyorum.

Java ve Sigar API'sını kullanarak Bellek, CPU, Disk, Yük-Ortalama, Ağ Arayüzü bilgisi ve metrikleri, İşlem Tablosu bilgileri, Rota bilgileri vb.


14
Sigar'ı kullanırken dikkatli olun, x64 makinelerinde sorunlar var ... stackoverflow.com/questions/23405832/… ve kütüphanenin 2010'dan beri güncellenmediği görülüyor
Alvaro

56

Aşağıdaki sözde size CPU ve RAM alır. Daha fazla bilgi için ManagementFactory bölümüne bakın .

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
Yukarıdaki kod için örnek çıktı. Bu kod Java 1.5 üzerinde çalışır. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r

AFAIK getProcessCpuTime = 390625000 yalnızca bu iş parçacığının ne kadar süredir çalıştığıdır. İşlemci kullanımını belirlemek için gerçekten kullanışlı değil
MikeNereson

2
Gerçekten güvenilir olduğundan emin değilim. 4 GB fiziksel belleğe sahip Windows XP'de yalnızca 2 GB rapor eder (Java 6 ve Java 7 ile test edilmiştir). Toplam takas boyutu da yanlış.
Emmanuel Bourg

4
@EmmanuelBourg sadece bu konuyu gören insanlar için belge, bununla ilgili bir hata var .
Sérgio Michels

2
Bu yöntem Java 9'a kadar harika çalıştı, şimdi Java'nın kullandığı yeni erişim denetimi çerçevesi nedeniyle bir java.lang.reflect.InaccessibleObjectException oluşturuyor.
Thor Lancaster

40

JDK 1.7'de sistem CPU'sunu ve bellek kullanımını alabilirsiniz com.sun.management.OperatingSystemMXBean. Bu farklı 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
Bu vuruldu ve özledim gibi görünüyor. FreeBSD 10 ve OpenJDK 8'de CPU yükü için -1 elde ediliyor
cen

bu soruyu kontrol et stackoverflow.com/q/19781087/1206998 . etkili olmasının birkaç saniye sürdüğünü söylüyor. (not:
Denemedim

25

Bu, herhangi bir harici API olmadan mükemmel çalışıyor, sadece yerel Java gizli özelliği :)

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

Dürüst olmak gerekirse bu en iyi cevabı buluyorum, Linux üzerinde çalışıyor, bu yüzden mutlu dostum.
ArsenArsen

1
herhangi bir ipucu neden 2. invocation 0.0 gösterir? OpenJDK v8'de.
vorburger

Unutmayın: "import java.lang.management.ManagementFactory;"
Bernd

1
getProcessCpuLoad ve getSystemCpuLoad -1 döndürür. im jdk 1.8 kullanarak
Burak Akyıldız

Konu sayısını elde etmek için bir yöntemi yok mu? Sadece nedenini merak mı ediyorsunuz?
djangofan

16

Bu çok ayrıntılı makaleye bir göz atın: http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUzaman

Kullanılan CPU yüzdesini elde etmek için tek ihtiyacınız olan basit matematik:

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

Not: İçe aktarmalısınız com.sun.management.OperatingSystemMXBean, almamalısınız java.lang.management.OperatingSystemMXBean.


Bu gerçekten iyi bir cevap. Diğer tüm teknikler gerçekten garip ve güvenilmez sonuçlar veriyor, ancak bazı takip eden ortalamalara sahip olan bu benim için bir cazibe gibi çalıştı.
Fractaly

İşlemci süresi geçen süreden daha yüksek olduğunda (% 100'den fazla alıyorum), sadece çoklu iş parçacığı nedeniyle mi yoksa nasıl anlaşılır?
Lukas Hanacek


6

Bunların çoğu JMX aracılığıyla zaten mevcut. Java 5 ile JMX yerleşiktir ve JDK ile birlikte bir JMX konsol görüntüleyicisi içerir.

Manuel olarak izlemek için JMX'i kullanabilir veya kendi çalışma zamanınızda bu bilgilere ihtiyacınız varsa Java'dan JMX komutlarını çağırabilirsiniz.



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

Aşağıdaki kod yalnızca Linux'tur (belki Unix), ancak gerçek bir projede çalışır.

    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
Bu aslında aradığım şey, ancak kod / proc / stat
Donal Tobin

desen nedir ??
HCarrasko

3

"Pc.bat" adlı bir toplu iş dosyası yazın, typeperf -sc 1 "\ mukit \ işlemci (_Total) \ %% İşlemci Süresi"

MProcess sınıfını kullanabilirsiniz,

/ *
 * Md. Mukit Hasan
 * CSE-JU, 35
 ** / içe aktar java . io . *;

genel sınıf 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()); } }

}

Sonra bazı dize manipülasyon sonra CPU kullanımı olsun. Aynı işlemi diğer görevler için de kullanabilirsiniz.

--Mukit Hasan


1
benim için (Win XP) doğru komut satırı şuydu: typeperf "\processor(_total)\% processor time"Toplu iş dosyasına koyarsanız,% yerine %% kullanın. Technet.microsoft.com/en-us/library/bb490960.aspx kullandım .
tutejszy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.