Получить системную информацию на уровне ОС

В настоящее время я создаю Java-приложение, которое может работать на многих разных платформах, но в первую очередь это варианты Solaris, Linux и Windows.

Кто-нибудь был в состоянии успешно извлечь информацию, такую ​​как текущее используемое дисковое пространство, загрузка ЦП и память, используемая в основной ОС? Как насчет того, что потребляет само приложение Java?

Желательно, чтобы я получил эту информацию без использования JNI.

25.08.2008 01:49:55
Что касается свободной памяти, см. Stackoverflow.com/a/18366283/231397 ( Runtime.getRuntime().freeMemory()как указано в принятом ответе, НЕ дает вам объем свободной памяти.
Christian Fries 14.09.2014 12:16:17
16 ОТВЕТОВ
РЕШЕНИЕ

Вы можете получить ограниченную информацию о памяти из класса Runtime. Это действительно не совсем то, что вы ищете, но я подумал, что предоставлю это для полноты картины. Вот небольшой пример. Изменить: Вы также можете получить информацию об использовании диска из класса java.io.File. Для использования дискового пространства требуется Java 1.6 или выше.

public class Main {
  public static void main(String[] args) {
    /* Total number of processors or cores available to the JVM */
    System.out.println("Available processors (cores): " + 
        Runtime.getRuntime().availableProcessors());

    /* Total amount of free memory available to the JVM */
    System.out.println("Free memory (bytes): " + 
        Runtime.getRuntime().freeMemory());

    /* This will return Long.MAX_VALUE if there is no preset limit */
    long maxMemory = Runtime.getRuntime().maxMemory();
    /* Maximum amount of memory the JVM will attempt to use */
    System.out.println("Maximum memory (bytes): " + 
        (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

    /* Total memory currently available to the JVM */
    System.out.println("Total memory available to JVM (bytes): " + 
        Runtime.getRuntime().totalMemory());

    /* Get a list of all filesystem roots on this system */
    File[] roots = File.listRoots();

    /* For each filesystem root, print some info */
    for (File root : roots) {
      System.out.println("File system root: " + root.getAbsolutePath());
      System.out.println("Total space (bytes): " + root.getTotalSpace());
      System.out.println("Free space (bytes): " + root.getFreeSpace());
      System.out.println("Usable space (bytes): " + root.getUsableSpace());
    }
  }
}
206
10.01.2014 19:34:10
Я думаю, что «Общая память, используемая в настоящее время JVM» немного сбивает с толку. Javadoc говорит , что функция возвращает «общий объем памяти в настоящее время доступны для текущих и будущих объектов, измеренных в байтах.» Звучит больше как память, оставшаяся и не используемая.
Dirk 30.06.2012 00:46:30
@Dirk: я обновил формулировку в соответствии с вашим комментарием. Спасибо!
William Brendel 24.01.2014 22:46:12
@LeonardoGaldioli: я не знаю характеристик производительности этих классов и методов, но я не удивлюсь, если они не будут оптимизированы для скорости. Другие ответы объясняют, как собирать определенную информацию с помощью JMX, что может быть быстрее.
William Brendel 24.01.2014 22:46:50
Это не отвечает на вопрос правильно. Все эти данные передаются в JVM, а не в ОС ...
Alvaro 19.02.2014 10:33:38

Я думаю, что лучший способ - реализовать API SIGAR от Hyperic . Он работает для большинства основных операционных систем (чертовски близко ко всему современному) и с ним очень легко работать. Разработчики очень быстро реагируют на свои форумы и списки рассылки. Мне также нравится, что это лицензия GPL2 Apache . Они также предоставляют множество примеров на Java!

SIGAR == Инструмент системной информации, сбора и отчетности.

42
27.09.2017 19:24:20
@ Йохан - Не ленись! Вы можете узнать это, прочитав связанную веб-страницу. (И это зависит от того, что вы подразумеваете под «независимостью от платформы».)
Stephen C 26.02.2013 06:10:57
@StephenC: Sigar использует файлы .dll, что делает его зависимым от платформы. API более высокого уровня может быть в Java, это другая история
Lemon Juice 26.02.2013 06:49:14
@Artificial_Intelligence да, но он предоставляет библиотеки (написанные на с) для большинства популярных платформ. Он не более зависим от платформы, чем сам jvm. Java API более высокого уровня должен быть совместимым на всех платформах.
Jeshurun 21.08.2013 15:29:51
Sigar не обновляется с 2010 года и, похоже, имеет ошибку в 64-битных системах: stackoverflow.com/questions/23405832/…
Alvaro 6.05.2014 11:07:01
И SIGAR также делает сбой JVM (хотя и с перерывами), но я уверен, что вы не возьмете этот риск в производство.
AKS 14.06.2017 09:26:59

Посмотрите на API, доступные в пакете java.lang.management . Например:

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

Там также есть множество других полезных вещей.

6
26.08.2008 07:09:20
OperatingSystemMXBean.getSystemLoadAverage () не реализован в Windows, потому что «это слишком дорого»
MikeNereson 14.07.2009 15:36:47
ThreadMXBean.getCurrentThreadCpuTime () только возвращает продолжительность работы этого потока. Не процент использования процессора.
MikeNereson 14.07.2009 15:37:19

Пакет java.lang.management предоставляет вам гораздо больше информации, чем среда выполнения - например, он даст вам кучную память ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) отдельно от не кучевой памяти ( ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

Вы также можете получить нагрузку на процессор (без написания собственного кода JNI), но вам нужно привести java.lang.management.OperatingSystemMXBeanк com.sun.management.OperatingSystemMXBean. Это работает на Windows и Linux, я не проверял это в другом месте.

Например ... вызывайте метод get getCpuUsage () чаще, чтобы получить более точные показания.

public class PerformanceMonitor { 
    private int  availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
    private long lastSystemTime      = 0;
    private long lastProcessCpuTime  = 0;

    public synchronized double getCpuUsage()
    {
        if ( lastSystemTime == 0 )
        {
            baselineCounters();
            return;
        }

        long systemTime     = System.nanoTime();
        long processCpuTime = 0;

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }

        double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );

        lastSystemTime     = systemTime;
        lastProcessCpuTime = processCpuTime;

        return cpuUsage / availableProcessors;
    }

    private void baselineCounters()
    {
        lastSystemTime = System.nanoTime();

        if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
        {
            lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
        }
    }
}
94
17.05.2011 02:59:50
Чтобы получить его для компиляции, замените приведение OperatingSystemMXBeanна com.sun.management.OperatingSystemMXBeanи предварите все экземпляры getOperatingSystemMXBean()с ManagementFactory.. Вы должны импортировать все классы соответствующим образом.
tmarthal 10.02.2011 02:47:53
Я получаю использование процессора как 0 за все. я изменил формулу использования процессора на cpuUsage = processCpuTime / systemTime. Я получаю значение для использования процессора, которое я не понимаю.
Raj 27.02.2012 11:08:37
делает 1.0 в качестве результата от getCpuUsageсреднего , что система использует все свои availableProcessors на 100%?
user454322 5.09.2012 09:00:56
Я всегда получаю 0, как сказал @Raj ... не могли бы вы привести пример, как использовать этот код?
dm76 28.11.2012 15:25:07
Попробуйте((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
Anthony O. 1.05.2013 10:36:51

Эй, вы можете сделать это с интеграцией Java / Com. Получая доступ к функциям WMI, вы можете получить всю информацию.

1
24.03.2009 12:32:46

Обычно, чтобы получить информацию об ОС низкого уровня, вы можете вызывать специальные команды ОС, которые предоставляют вам необходимую информацию с помощью Runtime.exec (), или читать файлы, такие как / proc / * в Linux.

5
24.03.2009 19:43:26

Использование ЦП не является простым - java.lang.management через com.sun.management.OperatingSystemMXBean.getProcessCpuTime подходит близко (см. Превосходный фрагмент кода Патрика выше), но обратите внимание, что он дает только доступ ко времени, потраченному ЦП в вашем процессе. он не скажет вам о времени процессора, потраченном на другие процессы, или даже о времени процессора, потраченном на выполнение системных операций, связанных с вашим процессом.

например, у меня есть интенсивный по сети процесс Java - он работает только и процессор на 99%, но только 55% из них, как сообщается, «процессор процессора».

даже не заводите меня на «среднюю нагрузку», так как она почти бесполезна, несмотря на то, что это единственный элемент, связанный с процессором, в компоненте MX. лишь бы солнце в их редкой мудрости выставляло что-то вроде "getTotalCpuTime" ...

для серьезного мониторинга процессора SIGAR, упомянутый Мэттом, кажется лучшим выбором.

5
2.06.2009 02:01:18

Есть Java-проект, который использует JNA (поэтому нет собственных библиотек для установки) и находится в активной разработке. В настоящее время он поддерживает Linux, OSX, Windows, Solaris и FreeBSD и предоставляет информацию об оперативной памяти, процессоре, батарее и файловой системе.

24
1.09.2016 15:56:47
Нет родных библиотек, возможно, вводит в заблуждение. В проекте используются нативные библиотеки, даже если они еще не написаны, и вам, очевидно, не нужно их устанавливать.
Stephen C 1.04.2011 11:06:02
Ты прав. JNA использует libffi, который имеет нативные компоненты. Но для всех целей, похоже, нет нативных библиотек (определенно нет для установки).
dB. 12.05.2011 04:15:57
@StephenC, хотя то, что вы говорите, верно, оно вводит в заблуждение, потому что то же самое для rt.jar, который также вызывает нативные методы. единственная причина, по которой люди заботятся о нативных методах, заключается в том, что им приходится компилировать и / или устанавливать их, что часто является нетривиальной задачей. Поскольку libffi широко используется, портирован и установлен, это уменьшает трудности. так что технически вы правы, но практически это не имеет значения.
rbp 7.06.2013 10:03:43
@ rbp - есть еще одна причина, по которой люди, которые опытные Java-разработчики предпочитают избегать нативных библиотек Собственная библиотека с ошибками (включая проблемы безопасности потоков или проблемы с управлением памятью) может дестабилизировать JVM хоста. Это не проблема "это не имеет значения" ....
Stephen C 7.06.2013 12:09:52
@StephenC делает мой сервер достаточно опытным ?
rbp 7.06.2013 15:37:49

Если вы используете виртуальную машину Jrockit, то вот другой способ получить использование процессора виртуальной машины. Компонент времени выполнения также может дать вам нагрузку на процессор на процессор. Я использовал это только в Red Hat Linux для наблюдения за производительностью Tomcat. Вы должны включить JMX remote в catalina.sh, чтобы это работало.

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);     
MBeanServerConnection conn = jmxc.getMBeanServerConnection();       
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");
2
10.11.2011 07:55:07

Вы можете получить некоторую информацию системного уровня System.getenv(), передав в качестве параметра имя соответствующей переменной среды. Например, в Windows:

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

Для других операционных систем наличие / отсутствие и имена соответствующих переменных среды будут отличаться.

11
16.08.2012 15:39:38
Они зависят от платформы, потому что имена переменных различаются в разных системах. Об этом говорится в статье Oracle о переменных среды. Я также нахожу способ получить независимый от системы способ.
Lemon Juice 9.09.2012 14:02:09
Под Linux (Ubuntu 17.10) не так много интересной информации о процессорах в среде.
pveentjer 21.07.2017 05:49:45

Он все еще находится в стадии разработки, но вы уже можете использовать jHardware

Это простая библиотека, которая удаляет системные данные, используя Java. Работает как в Linux, так и в Windows.

ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());        
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]
3
3.09.2016 17:54:36
Хорошо, но он использует версии Guava и JNA, которые конфликтуют с моими потребностями (например, см. GLASSFISH-21367 ).
lu_ko 23.02.2017 08:39:07
Здравствуйте, JNA была представлена ​​в версии 0.8 jHardware. Используется только для данных о температуре и датчиках. Если вам не нужна эта информация, вы можете использовать версию 0.7. То же самое для гуавы. В этом случае вам придется использовать версию 0.6.3.
profesor_falken 24.02.2017 22:47:35

Добавьте OSHI-зависимость через maven:

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

Получите емкость аккумулятора в процентах:

SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
    System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}
7
10.04.2016 18:01:01
OSHI имеет большую часть информации, описанной в других комментариях. Он использует JNA, чтобы по возможности получать его через собственные вызовы ОС.
Daniel Widdis 13.04.2016 15:21:21

Для окон я пошел по этому пути.

    com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    long physicalMemorySize = os.getTotalPhysicalMemorySize();
    long freePhysicalMemory = os.getFreePhysicalMemorySize();
    long freeSwapSize = os.getFreeSwapSpaceSize();
    long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();

Вот ссылка с деталями.

12
13.01.2017 11:50:11

На Windows, вы можете запустить systeminfoкоманду и возвращает свой выход, например , с помощью следующего кода:

private static class WindowsSystemInformation
{
    static String get() throws IOException
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("systeminfo");
        BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder stringBuilder = new StringBuilder();
        String line;

        while ((line = systemInformationReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }

        return stringBuilder.toString().trim();
    }
}
4
27.10.2016 09:56:54

Один простой способ, который можно использовать для получения информации об уровне ОС, и я протестировал его на моем Mac, который хорошо работает:

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

Вы можете найти много соответствующих метрик операционной системы здесь

2
24.04.2019 14:44:03

Чтобы получить среднее значение загрузки системы, равное 1 минуте, 5 минутам и 15 минутам внутри Java-кода, вы можете сделать это, выполнив команду, cat /proc/loadavgиспользуя и интерпретируя ее, как показано ниже:

    Runtime runtime = Runtime.getRuntime();

    BufferedReader br = new BufferedReader(
        new InputStreamReader(runtime.exec("cat /proc/loadavg").getInputStream()));

    String avgLine = br.readLine();
    System.out.println(avgLine);
    List<String> avgLineList = Arrays.asList(avgLine.split("\\s+"));
    System.out.println(avgLineList);
    System.out.println("Average load 1 minute : " + avgLineList.get(0));
    System.out.println("Average load 5 minutes : " + avgLineList.get(1));
    System.out.println("Average load 15 minutes : " + avgLineList.get(2));

И получить физическую системную память , выполнив команду free -mи затем интерпретировав ее, как показано ниже:

Runtime runtime = Runtime.getRuntime();

BufferedReader br = new BufferedReader(
    new InputStreamReader(runtime.exec("free -m").getInputStream()));

String line;
String memLine = "";
int index = 0;
while ((line = br.readLine()) != null) {
  if (index == 1) {
    memLine = line;
  }
  index++;
}
//                  total        used        free      shared  buff/cache   available
//    Mem:          15933        3153        9683         310        3097       12148
//    Swap:          3814           0        3814

List<String> memInfoList = Arrays.asList(memLine.split("\\s+"));
int totalSystemMemory = Integer.parseInt(memInfoList.get(1));
int totalSystemUsedMemory = Integer.parseInt(memInfoList.get(2));
int totalSystemFreeMemory = Integer.parseInt(memInfoList.get(3));

System.out.println("Total system memory in mb: " + totalSystemMemory);
System.out.println("Total system used memory in mb: " + totalSystemUsedMemory);
System.out.println("Total system free memory in mb: "   + totalSystemFreeMemory);
0
1.01.2020 11:18:46