Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java application CPU/load much higher when built against JDK8

I have a Java application developed in Eclipse Luna in Windows that runs in Amazon EC2 (c3.large, Amazon Linux). This application processes work at a very consistent incoming rate. When I build the application against JDK 8u31, the EC2 CPU load is much higher than the same application built against JDK 7u75.

The application originally ran with the default JRE on EC2, and I added the OpenJDK 1.8.0.31 to take advantage of the Java 8 Process waitFor(long timeout, TimeUnit unit). The main work this application does involves invoking an application using Runtime.exec.

$ sudo alternatives --config java

There are 2 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*  1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
 + 2           /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.31-2.b13.5.amzn1.x86_64/jre/bin/java

Example load average when the application is built against 1.7:

top - 00:20:28 up 4 days, 10:41,  4 users,  load average: 0.37, 0.26, 0.52

Example load average when the application is built against 1.8:

top - 23:45:52 up 4 days, 10:06,  4 users,  load average: 2.28, 2.60, 2.01

It seems like it may be related to the Open JDK 1.8.0.31, but I don't know how to debug this. There are no code changes, I'm only changing the compliance level and build between 1.7 and 1.8 in Eclipse Luna. Any idea why the load would be so much different?

UPDATE:

I see similar high CPU load when I use the Oracle JDK on EC2.

$ sudo alternatives --config java

There are 3 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
   1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
   2           /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.31-2.b13.5.amzn1.x86_64/jre/bin/java
*+ 3           /usr/java/jdk1.8.0_31/bin/java

Load average:

top - 01:45:27 up 4 days, 12:06,  4 users,  load average: 2.28, 1.50, 1.04
like image 446
DanielB6 Avatar asked Feb 22 '15 00:02

DanielB6


2 Answers

You've described symptoms, but I don't think this is enough to go on, if only because it will be impossible to search for things like "java 8 high CPU" anywhere (google, the java bug parade, etc.) and find useful results. Unfortunately, you need to collect more information about what's using CPU. Here are some thoughts on how to do so:

  1. Profile with a tool such as VisualVM. The load differences are extreme, so you might just be able to spot what's using the CPU.
  2. Find the busy threads. You can take a bunch of thread snapshots and eyeball it, or try a tool such a jvmtop.
  3. Check what the garbage collector is doing, either by enabling GC logging or with a tool such as jstat.
  4. Use strace to trace the execution of system calls.
like image 160
jtoberon Avatar answered Oct 16 '22 18:10

jtoberon


The documentation says: "The default implementation of this methods polls the exitValue to check if the process has terminated. Concrete implementations of this class are strongly encouraged to override this method with a more efficient implementation."

I strongly suspect this to be the reason.

See http://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#waitFor--

like image 45
Gerhard Wesp Avatar answered Oct 16 '22 17:10

Gerhard Wesp