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


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.