Як слідкувати за використанням процесора, пам'яті та диска комп'ютера на Java?


180

Я хотів би стежити за наступною системною інформацією на Java:

  • Поточне використання процесора ** (у відсотках)
  • Доступна пам'ять * (вільна / загальна)
  • Вільний простір на диску (вільний / загальний)

    * Зауважте, що я маю на увазі загальну пам'ять, доступну для всієї системи, а не лише для JVM.

Я шукаю крос-платформенне рішення (Linux, Mac та Windows), яке не покладається на власний код, що викликає зовнішні програми або використовує JNI. Хоча це життєздатні варіанти, я вважаю за краще не підтримувати специфічний для себе код, якщо у когось вже є краще рішення.

Якщо там є безкоштовна бібліотека, яка робить це надійно, на платформі, це було б чудово (навіть якщо вона здійснює зовнішні дзвінки або використовує власний код).

Будь-які пропозиції дуже вдячні.

Для уточнення, я хотів би отримати поточне використання процесора для всієї системи, а не лише Java-процесів.

API SIGAR забезпечує всю функціональність, яку я шукаю в одному пакеті, тому це найкраща відповідь на моє запитання поки що. Однак, оскільки він отримав ліцензію відповідно до GPL, я не можу використовувати його для своєї первісної мети (закрите джерело, комерційний продукт). Можливо, що Hyperic може ліцензувати SIGAR для комерційного використання, але я не розглядав це. Що стосується моїх проектів GPL, я, безумовно, буду вважати SIGAR в майбутньому.

Для моїх поточних потреб я схиляюся до наступного:

  • Для використання процесора OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(середнє завантаження на процесор)
  • Для пам’яті OperatingSystemMXBean.getTotalPhysicalMemorySize()таOperatingSystemMXBean.getFreePhysicalMemorySize()
  • Для місця на диску File.getTotalSpace()іFile.getUsableSpace()

Обмеження:

getSystemLoadAverage()І методи простору Виконання запитів диска доступні тільки в Java 6. Крім того , деякі функціональні можливості JMX не можуть бути доступні для всіх платформ (тобто було повідомлено , що getSystemLoadAverage()повертає -1 на Windows).

Хоча спочатку була ліцензована під GPL, вона була змінена на Apache 2.0 , яка, як правило, може використовуватися для комерційних продуктів із закритим кодом.


Для уточнення, sigar api отримує інформацію про систему. Якщо ви хочете інформацію про jvm, використовуйте JMX.
Метт Каммінгс

Якщо SIGAR перебуває під GPL, це не заважає вам використовувати його, це просто означає, що вам потрібно зв’язатися з авторами та вимагати альтернативного ліцензування. Автори часто раді прийняти невелику плату і дозволити комерційне ліцензування.
Алек Томас

7
Оскільки версія 1.6.4 SIGAR використовує ліцензію Apache.
Soundlink

чи знаєте ви, як отримати навантаження для кожного окремого процесора?
zcaudate

Відповіді:


67

По суті, про що я згадував у цій публікації . Рекомендую використовувати API SIGAR . Я використовую API SIGAR в одному з моїх власних додатків, і це чудово. Ви знайдете, що вона стабільна, добре підтримується та сповнена корисних прикладів. Це відкритий код з ліцензією GPL 2 Apache 2.0. Перевір. У мене є відчуття, що воно буде відповідати вашим потребам.

Використовуючи Java та API Sigar, ви можете отримати пам'ять, процесор, диск, середню завантаженість, інформацію та показники мережевого інтерфейсу, інформацію про таблицю обробки, інформацію про маршрути тощо.


14
Будьте обережні при використанні Sigar, є проблеми на машинах x64 ... stackoverflow.com/questions/23405832/… і, здається, бібліотека не оновлюється з 2010 року
Альваро

56

Наступне нібито отримує вам процесор і оперативну пам’ять. Докладніше див. У розділі 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 з 4 Гб фізичної пам’яті він повідомляє лише про 2 ГБ (тестовано на Java 6 та Java 7). Загальний розмір свопу також неправильний.
Еммануель Бург

4
@EmmanuelBourg просто для документації для людей, які бачать цю тему, є помилка, пов’язана з цим.
Серхіо Міхельс

2
Цей метод працював чудово до Java 9, тепер він викидає java.lang.reflect.InaccessibleObjectException завдяки новій системі перевірки доступу, яку використовує Java.
Тор Ланкастер

40

У JDK 1.7 ви можете отримати системний процесор та використання пам'яті через 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 для завантаження процесора на 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, тому я щасливий, приятель.
АрсенАрсен

1
будь-яка підказка, чому друга виклик показує 0,0? На OpenJDK v8.
vorburger

Не забудьте: "import java.lang.management.ManagementFactory;"
Бернд

1
getProcessCpuLoad та getSystemCpuLoad return -1 формують мене. im using 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

Щоб отримати відсоток використовуваного процесора, все, що вам потрібно, - це проста математика:

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.OperatingSystemMXBeanа не java.lang.management.OperatingSystemMXBean.


Це дійсно гарна відповідь. Всі інші методи дають дійсно дивні та недостовірні результати, але ця з певним усередненням працювала як шарм для мене.
Fractaly

Коли час процесора перевищує минулий час (я отримую понад 100%), це лише через багатопоточність чи як його зрозуміти?
Лукаш Ханачек

8

Для місця на диску, якщо у вас є Java 6, ви можете використовувати методи getTotalSpace та getFreeSpace у файлі. Якщо ви не на Java 6, я вважаю, що ви можете скористатись AOche Commons IO, щоб отримати частину шляху.

Я не знаю жодного кроссплатформенного способу отримати використання процесора або використання пам'яті.


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. Мукіт Хасан
 * CSE-JU, 35
 ** / імпорт Java . іо . *;

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

}

Потім після деяких рядкових маніпуляцій ви отримуєте використання процесора. Ви можете використовувати той самий процес для інших завдань.

--Мукіт Хасан


1
Для мене (Win XP) правильним командним рядком було: typeperf "\processor(_total)\% processor time"Якщо ви помістите його в пакетний файл, використовуйте %% замість%. Я використовував technet.microsoft.com/en-us/library/bb490960.aspx .
tutejszy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.