Отримати інформацію про систему на рівні ОС


232

В даний час я будую додаток Java, яке може працювати в багатьох платформах, але це в першу чергу варіанти Solaris, Linux та Windows.

Хтось зміг успішно витягти таку інформацію, як поточний диск, що використовується, використання процесора та пам'ять, що використовується в базовій ОС? А як щодо того, що споживає сама програма Java?

Переважно я хотів би отримати цю інформацію без використання JNI.


3
Щодо вільної пам’яті див. Stackoverflow.com/a/18366283/231397 ( Runtime.getRuntime().freeMemory()як це пропонується у прийнятій відповіді, НЕ дається вам кількість вільної пам’яті.
— Крістіан Фріз

Відповіді:


206

Ви можете отримати обмежену інформацію про пам'ять з класу 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());
    }
  }
}

7
Я думаю, що "Загальна пам'ять, якою зараз користується JVM", є дещо заплутаною. Javadoc каже , що функція повертає «загальний обсяг пам'яті в даний час доступні для поточних і майбутніх об'єктів, виміряних в байтах.» Звучить більше як пам'ять, що залишилася і не використовується.
— Дірк

@Dirk: Я оновив формулювання, щоб вирішити ваш коментар. Дякую!
— Вільям Брендель

@LeonardoGaldioli: Я не знаю характеристики продуктивності цих класів і методів, але я не здивуюсь, якби їх не оптимізували за швидкістю. Інші відповіді пояснюють, як збирати певну інформацію за допомогою JMX, що може бути швидшим.
— Вільям Брендель

15
Це не відповідає правильно на питання. Все це посилається на JVM, а не на ОС ...
— Альваро,

Я знаю, що ця тема досить застаріла. АЛЕ: Якщо вам дійсно потрібна кількість ядер процесора, тоді не використовуйте це рішення. У мене двоядерний процесор з двома потоками для кожного ядра. JVM не повертає апаратні ядра, а швидше програмні ядра / потоки.
— F_Schmidt

95

Пакет java.lang.management дає вам набагато більше інформації, ніж Runtime - наприклад, він надасть вам накопичувальну пам’ять ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()), окремо від пам'яті, що не купує ( ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

Ви також можете отримати процесорне використання процесора (без написання власного коду JNI), але вам потрібно java.lang.management.OperatingSystemMXBeanпередати це com.sun.management.OperatingSystemMXBean. Це працює в Windows та Linux, я не перевіряв його деінде.

Наприклад ... частіше телефонуйте методу 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();
        }
    }
}

10
Щоб отримати його , щоб зібрати, замінити кидання OperatingSystemMXBeanдо com.sun.management.OperatingSystemMXBeanі випередити всі екземпляри getOperatingSystemMXBean()з ManagementFactory.. Вам потрібно імпортувати всі класи відповідно.
— tmarthal

2
Я отримую використання процесора як 0 для всього. я змінив формулу використання процесора на cpuUsage = processCpuTime / systemTime. Я отримую значення для використання процесора, яке я не розумію.
— Радж

чи 1,0 в результаті getCpuUsageозначає, що система використовує всі доступні процесори на 100%?
— користувач454322

2
Я завжди отримую 0, як сказав @Raj ... чи можете ви навести приклад того, як використовувати цей код?
— dm76

1
Спробуйте((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
— Ентоні О.

43

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

SIGAR == Система інформації, збирання та звітності.


2
@Yohan - Не лінуйся! Це можна дізнатися, прочитавши пов’язану веб-сторінку. (І це залежить від того, що ви маєте на увазі під "платформою незалежною".)
— Stephen C

2
@StephenC: Sigar використовує файли .dll, що робить його платформою залежною. API вищого рівня, можливо, у Java, це вже інша історія
— лимонний сік

1
@Artificial_Intelligence так, але він надає бібліотеки (написані c) для більшості популярних платформ. Це не більше платформи, ніж сама jvm. API API вищого рівня повинен бути узгодженим на всіх платформах.
— Єшурун

8
Sigar не оновлюється з 2010 року і, здається, має помилку в 64-бітових системах: stackoverflow.com/questions/23405832/…
— Alvaro

1
І SIGAR також спричиняє крах JVM (хоча і переривчастий), але я впевнений, що ви не будете ризикувати на виробництві.
— AKS

25

Є проект Java, який використовує JNA (тому не встановлюються рідні бібліотеки) і активно розвивається. В даний час він підтримує Linux, OSX, Windows, Solaris і FreeBSD і надає оперативну пам’ять, процесор, акумулятор та файлові системи.


Жодна рідна бібліотека, можливо, не вводить в оману. Проект використовує рідні бібліотеки, навіть якщо вони не написали жодної, і вам, мабуть, не потрібно встановлювати жодну.
— Stephen C

1
Ти маєш рацію. JNA використовує libffi, які мають вбудовані компоненти. Але для всіх цілей, схоже, немає рідних бібліотек (їх точно не потрібно встановлювати).
— дБ.

@StephenC, хоча те, що ви говорите, є точним, оманливим, тому що це те саме для rt.jar, який також посилається на рідні методи. Єдиною причиною, коли люди турбуються про рідні методи, є те, що їм доводиться збирати та / або встановлювати їх, що часто є нетривіальним завданням. Оскільки libffi настільки широко прийнятий, перенесений та встановлений, він зменшує труднощі. Так, технічно ви праві, але практично це не має значення.
— rbp

@rbp - Є ще одна причина, чому досвідчені розробники Java вважають за краще уникати власних бібліотек. Власна бібліотека, у якій є помилки (включаючи проблеми безпеки потоків або проблеми з управлінням пам'яттю), може дестабілізувати JVM хоста. Це не питання "не має значення" ....
— Стівен C

@StephenC чи є автором веб-сервера додатків для мене достатньо досвіду ?
— rbp

13

За вікнами я пішов цим шляхом.

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

Ось посилання з деталями.


11

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

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

Для інших операційних систем наявність / відсутність та назви відповідних змінних середовищ будуть відрізнятися.


1
Вони залежать від платформи, оскільки імена змінних відрізняються між системами. Про це говорить стаття Oracle про змінні середовища. Я також знаходжу спосіб отримати систему незалежним шляхом.
— Лимонний сік

В Linux (Ubuntu 17.10) не так багато цікавої інформації щодо процесорів у середовищі.
— pveentjer

8

Додайте залежність від 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));
}

OSHI має більшу частину інформації, описаної в інших коментарях. Він використовує JNA, щоб отримати його через рідні дзвінки ОС, коли це можливо.
— Даніель Віддіс

6

Подивіться API, доступні в пакеті java.lang.management . Наприклад:

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

Там також є багато інших корисних речей.


2
OperatingSystemMXBean.getSystemLoadAverage () не реалізується у Windows, тому що "його занадто дорого"
— MikeNereson

1
ThreadMXBean.getCurrentThreadCpuTime () повертає лише те, скільки часу ця нитка працює. Не відсоток використання процесора
— MikeNereson

5

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


5

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

Наприклад, у мене є інтенсивний Java-процес - це єдине, що працює, і процесор знаходиться на 99%, але лише 55% від них повідомляється як "процесор процесора".

навіть не запускайте мене з "середнього завантаження", оскільки це поруч із марним, незважаючи на те, що це єдиний елемент, що стосується процесора на бобі MX. якби тільки сонце в їх випадковій мудрості викривало щось на кшталт "getTotalCpuTime" ...

для серйозного моніторингу процесора SIGAR, згаданий Меттом, здається найкращою ставкою.


4

Увімкнено 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();
    }
}

3

Якщо ви використовуєте Jrockit VM, ось ось інший спосіб використання процесора VM. Режим виконання також може давати вам завантаження процесора на один процесор. Я використовував це лише на Red Hat Linux, щоб спостерігати за роботою Tomcat. Для цього потрібно включити пульт дистанційного керування JMX у 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");

3

Він ще знаходиться на стадії розробки, але вже можна використовувати 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());
//[...]

Приємно, але він використовує версії Guava та JNA, які суперечать моїм потребам (наприклад, див. GLASSFISH-21367 ).
— lu_ko

Привіт, JNA була представлена ​​в 0.8 версії jHardware. Він використовується лише для даних про температуру та датчики. Якщо ця інформація вам не потрібна, ви можете використовувати версію 0.7. Те ж саме і для Гуави. У такому випадку вам доведеться скористатися версією 0.6.3.
— profesor_falken

2

Один простий спосіб, який можна використовувати для отримання інформації про рівень ОС, і я перевірив на своєму Mac, який добре працює:

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

Ви можете знайти багато відповідних показників операційної системи тут


1

Гей, ви можете зробити це за допомогою інтеграції java / com. Доступ до функцій WMI ви можете отримати всю інформацію.


0

Щоб отримати середнє завантаження системи 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.