Как в Java контролировать использование ЦП, памяти и диска компьютера?

Я хотел бы отслеживать следующую системную информацию на Java:

  • Текущая загрузка ЦП ** (в процентах)
  • Доступная память * (свободная / всего)
  • Доступное дисковое пространство (свободное / всего)

    * Обратите внимание, что я имею в виду общую память, доступную для всей системы, а не только для JVM.

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

Если есть бесплатная библиотека, которая делает это надежным кроссплатформенным способом, это было бы здорово (даже если она выполняет внешние вызовы или использует собственный код).

Любые предложения очень ценятся.

Чтобы уточнить, я хотел бы получить текущее использование ЦП для всей системы, а не только для процесса (ов) Java.

SIGAR API предоставляет все функции, которые я ищу, в одном пакете, так что это пока лучший ответ на мой вопрос. Однако из-за того, что он находится под лицензией 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, который обычно можно использовать для коммерческих продуктов с закрытым исходным кодом.


person David Crow    schedule 06.09.2008    source источник
comment
Чтобы уточнить, sigar api предоставляет вам системную информацию. Если вам нужна информация о jvm, используйте JMX.   -  person Matt Cummings    schedule 08.09.2008
comment
SIGAR под лицензией GPL не препятствует вам использовать ее, это просто означает, что вы должны связаться с авторами и запросить альтернативное лицензирование. Авторы часто рады принять небольшую плату и разрешить коммерческое лицензирование.   -  person Alec Thomas    schedule 28.11.2008
comment
Начиная с версии 1.6.4 SIGAR использует лицензию Apache.   -  person Soundlink    schedule 31.01.2011
comment
вы знаете, как получить нагрузку для каждого отдельного процессора?   -  person zcaudate    schedule 12.09.2012


Ответы (10)


В соответствии с тем, что я упомянул в этом сообщении . Я рекомендую вам использовать SIGAR API. Я использую SIGAR API в одном из своих приложений, и это здорово. Вы найдете его стабильным, хорошо поддерживаемым и полным полезных примеров. Это открытый исходный код с лицензией Apache 2.0 GPL 2. Проверить это. Я чувствую, что это удовлетворит ваши потребности.

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

person Matt Cummings    schedule 06.09.2008
comment
Будьте осторожны при использовании Sigar, на машинах x64 есть проблемы ... stackoverflow.com/questions/23405832/, и кажется, что библиотека не обновляется с 2010 года. - person Alvaro; 01.05.2014

Следующее предположительно дает вам процессор и оперативную память. Подробнее см. 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
}
person Eugene Yokota    schedule 06.09.2008
comment
Пример вывода для приведенного выше кода. Этот код действительно работает на Java 1.5. getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwap294967Space - person blak3r; 20.05.2009
comment
AFAIK getProcessCpuTime = 390625000 - это только то, как долго этот поток был запущен. Это не очень полезно для определения использования процессора. - person MikeNereson; 14.07.2009
comment
Не уверен, что это действительно надежно. В Windows XP с 4 ГБ физической памяти отображается только 2 ГБ (проверено с Java 6 и Java 7). Общий размер свопа также неверен. - person Emmanuel Bourg; 28.07.2011
comment
@EmmanuelBourg - просто чтобы документировать людям, которые видят эту тему, есть ошибка связанные с этим. - person ; 13.09.2012
comment
Этот метод отлично работал до Java 9, теперь он выдает исключение java.lang.reflect.InaccessibleObjectException из-за новой инфраструктуры проверки доступа, которую использует Java. - person Thor Lancaster; 26.07.2019

В JDK 1.7 вы можете получить информацию об использовании ЦП и памяти системы с помощью _ 1_. Это отличается от 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.
person Gp2you    schedule 23.10.2012
comment
Похоже, это хит и промах. Получение -1 для загрузки процессора в FreeBSD 10 и OpenJDK 8. - person cen; 18.02.2016
comment
проверьте этот вопрос stackoverflow.com/q/19781087/1206998. в нем говорится, что для достижения эффекта требуется пара секунд. (примечание: я не пробовал) - person Juh_; 25.05.2018

Это отлично работает для меня без какого-либо внешнего 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());
person bizzr3    schedule 03.12.2014
comment
Я честно считаю, что это лучший ответ, работает в Linux, так что я счастлив, парень. - person ArsenArsen; 04.10.2016
comment
любая подсказка, почему второй вызов показывает 0,0? В OpenJDK v8. - person vorburger; 10.07.2017
comment
Не забывайте: import java.lang.management.ManagementFactory; - person Bernd; 06.01.2018
comment
getProcessCpuLoad и getSystemCpuLoad возвращают -1 от меня. Я использую jdk 1.8 - person Burak Akyıldız; 14.04.2018
comment
У него нет способа получить количество потоков? Просто интересно, почему? - person djangofan; 16.10.2018
comment
Этот работал у меня как на Windows 10, так и на macOS High Sierra. - person gbmhunter; 14.11.2018
comment
Это работает, если вы используете Oracle JVM. Если вы контролируете, какая версия Java установлена, это отличное решение. Однако он не будет работать с Open JDK, на который переходят все больше и больше пользователей, поскольку Oracle изменила лицензионные требования на JDK11. - person Daniel Widdis; 16.05.2019
comment
Это правильный ответ, начиная с Java 9. Цикл по свойствам java.lang OperatingSystemMXBean вместо com.sun теперь выдает исключение. - person Thor Lancaster; 26.07.2019


Для дискового пространства, если у вас Java 6, вы можете использовать getTotalSpace и методы getFreeSpace в файле. Если вы не используете Java 6, я считаю, что вы можете использовать Apache Commons IO, чтобы кое-что исправить.

Боюсь, что я не знаю какого-либо кроссплатформенного способа получить использование ЦП или использование памяти.

person Matt Sheppard    schedule 06.09.2008

Принятый ответ в 2008 году рекомендовал SIGAR. Однако, как говорится в комментарии от 2014 года (@Alvaro):

Будьте осторожны при использовании Sigar, на машинах x64 есть проблемы ... Sigar 1.6.4 дает сбой: EXCEPTION_ACCESS_VIOLATION, и кажется, что библиотека не обновляется с 2010 года.

Я рекомендую использовать https://github.com/oshi/oshi.

Или упомянутый выше ответ.

person OhadR    schedule 15.05.2019

Многие из них уже доступны через JMX. В Java 5 встроен JMX, и они включают средство просмотра консоли JMX с JDK.

Вы можете использовать JMX для мониторинга вручную или вызывать команды JMX из Java, если вам нужна эта информация во время выполнения.

person Jason Cohen    schedule 07.09.2008

Следующий код предназначен только для 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;
}
person Community    schedule 07.05.2009
comment
На самом деле это то, что я искал, но в коде отсутствует шаблон REGEX для поиска информации о процессоре из файла / proc / stat. - person Donal Tobin; 07.03.2012
comment
какой узор ?? - person HCarrasko; 27.01.2015

Создайте командный файл "Pc.bat" как, typeperf -sc 1 "\ mukit \ processor (_Total) \ %% Processor Time"

Вы можете использовать класс MProcess,

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

}

Затем после некоторых манипуляций со строкой вы получаете использование ЦП. Вы можете использовать тот же процесс для других задач.

- Мукит Хасан

person Md. Mukit Hasan    schedule 15.05.2010
comment
для меня (Win XP) правильная командная строка была: typeperf "\processor(_total)\% processor time" Если вы поместите ее в пакетный файл, используйте %% вместо%. Я использовал technet.microsoft.com/en-us/library/bb490960.aspx < / а>. - person tutejszy; 21.01.2013