2

I would like to get cpu usage to update my database using java continuously. At the first loop, this code is readable the correct cpu usage. After then, it returns wrong values less than 0. So, I stucked.

I used jdk 1.8.124.

plz, let me know how to get cpu usage continuously.

lib

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;

src

public static void main(String[] args) {
  OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
      .getOperatingSystemMXBean();

  while (true) {
    System.out.println(bean.getProcessCpuLoad());
    System.out.println(bean.getSystemCpuLoad());
        try {
            Thread.sleep(3000);
        }
        catch (Exception e){
            System.out.println(e.toString());
            break;
        }
  }

}
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
nayang
  • 157
  • 1
  • 14
  • Why not use a library like Dropwizard Metrics or Micrometer ? – OneCricketeer Apr 02 '20 at 06:30
  • Below URL can be helpful. https://stackoverflow.com/questions/47177/how-do-i-monitor-the-computers-cpu-memory-and-disk-usage-in-java – 서민봉 Minbong David Seo Apr 02 '20 at 06:38
  • @cricket_007 I will do it – nayang Apr 03 '20 at 00:02
  • 1
    @서민봉MinbongDavidSeo 해봤는데, 안됩니다. 일단 CPU 사용률 값들이 작업관리자에 나오는 값들과 매칭되질 않아요. 분명 CPU 사용률은 80%이상 올라가 있음에도 불구하고 12%로 계속 뜬다거나, SIGAR API는 특정 컴퓨터에서는 에러 로그만 작성되고 정상적으로 돌지 않습니다. (Windows 환경인데 원보드 타입의 개발보드 (ATOM processor)에서는 특히 작동을 안해요) 다른 것들도 첫번째에서만 제대로된 답을 내놓고 두번째 아웃풋부터는 소숫점 이하의 값을 결과로 보여줍니다 ㅠㅠ – nayang Apr 03 '20 at 00:06
  • => i tried but it's still not working. the CPU usage values was not matched with the values in the task manager. Obviously, even though the cpu usage has risen above 80%, it keeps indicating around 12%. Using sigar API generated an error log file on certain computers and then turned off. ( on windows environment it tested, it doesn't work especially on a dev board(ATOM processor)). Most of sample code gives correct answer at the first time only. Other outputs are still less th – nayang Apr 03 '20 at 00:15
  • an 0. I don't know why .. – nayang Apr 03 '20 at 00:23
  • @nayang 에고 고생 많으시네요;;; 혹시 제가 링크 드린거에 bizzr3 이사람 답변대로 하신건가요??? 자바 버전에 따라서 이슈가 있는거 같아요;; – 서민봉 Minbong David Seo Apr 03 '20 at 00:50
  • @서민봉MinbongDavidSeo 예 해당 부분도 해봤는데 이게 while 문으로 불렀을 때의 슬립시간의 문제인지.. 정확히 모르겠어요. 위에서 이야기 한 것처럼 첫번째 나오는 output은 ManagementFactory 라이브러리 사용시 정상적인 값이 출력되는 것으로 보이는데 다음 출력부터는 이상한 값이 나옵니다. getSystemCpuLoad값은 CPU 값이 아닌 GPU 사용률을 보여주는 것으로 보입니다. 그런 이유로 getProcessCpuLoad를 지속적으로 불러와도 신뢰할 만한 값이 나올 수 있는 방법이 있는지 궁금합니다. 제가 자바를 처음 다뤄봐서 부족한 것 같습니다 ㅠ – nayang Apr 03 '20 at 08:19

2 Answers2

5

It's done by using Oshi lib.

I can get cpu usage every 20 seconds lib

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;

src

private SystemInfo si = new SystemInfo();
private HardwareAbstractionLayer hal = si.getHardware();
private CentralProcessor cpu = hal.getProcessor();
long[] prevTicks = new long[TickType.values().length];

public static double getCPU()
{
    double cpuLoad = cpu.getSystemCpuLoadBetweenTicks( prevTicks ) * 100;
    prevTicks = cpu.getSystemCpuLoadTicks();
    System.out.println("cpuLoad : " + cpuLoad);
    return cpuLoad;
}

public static void main(String[] args) throws Exception{
    while(true) {
        // Sleep 20 seconds
        tCPU = (int)getCPU();
    }
}
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
nayang
  • 157
  • 1
  • 14
  • Actually, under Windows I don't see a big difference between bean.getSystemCpuLoad() and the result of the Oshi lib when Using Java 11. It's pretty much the same. But there is a huge difference to the CPU utilization shown in the Windows task manager. – Stefan Endrullis Feb 22 '23 at 11:14
2

I use the following code to get the CPU load, which works without invoking hidden methods in com.sun.* classes:

public static Double getProcessCpuLoad() {
    try {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
        AttributeList list = mbs.getAttributes(name, new String[]{"ProcessCpuLoad"});

        return Optional.ofNullable(list)
                .map(l -> l.isEmpty() ? null : l)
                .map(List::iterator)
                .map(Iterator::next)
                .map(Attribute.class::cast)
                .map(Attribute::getValue)
                .map(Double.class::cast)
                .orElse(null);

    } catch (Exception ex) {
        return null;
    }
}

Works fine, tested with JRE 8/11/13.

Peter Walser
  • 15,208
  • 4
  • 51
  • 78
  • I added up your code. And multiply getProcessCpuLoad by 10. And, this is a result of it: 7.243884075601578 0.6300612162235574 0.12868694055771907 0.12894463720532992 0.12908448934655176 0.06456276270743097 0.12845790173533678 0.06463014120467704 0.12915222118015093 it still not working. :( – nayang Apr 02 '20 at 07:05
  • why do you multiply by 10 and not by 100 (to the the % value)? Also the values look ok - what was your expectation? – Peter Walser Apr 02 '20 at 10:06
  • it was my typo. I multiplied by 100. So 7.243884075601578 looks right answer but rest of answers were not good. On my task manager, CPU usage indicated more than 30% at the first answer. So, could you gave me more information about this like imported library? – nayang Apr 03 '20 at 00:21