Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why java.lang.Object.getClass() (and reflection) is slower than usual?

We are encountering some strange JVM performance issues.

We have a large and somewhat opaque GUI component (Actuate Formula 1 spreadsheet).

If we initialize all of it from the Event Dispatch Thread (as you should), we find that the code runs considerably more slowly (dragging the mouse to select cells, there's a noticeable lag).

If we initialize it the first time in the main launcher thread, and only then start using it in the EDT, it runs much more quickly.

When I look at why it is performing slowly using a profiler, the method calls that are taking all of the time are:

  • java.lang.Object.getClass()
  • java.lang.reflect.Array.newInstance(Class, int)
  • java.lang.Class.getComponentType()
  • java.lang.Thread.currentThread()

We are using the 64-bit Sun Hotspot JVM on Windows 7 (the one that comes with the JDK).

Does anyone know of any reason why the above methods might perform drastically slower that usual?

I am thinking that maybe it has something to do with the order in which the classes are loaded.... is that a reasonable theory? Does anyone know of any other ways in which I can diagnose why these method calls might be taking a long time?

I've attached two screenshots from the profiler. In both, all I did was drag the mouse around the spreadsheet cells while the profiler was running. So it's just updating the GUI component and not doing very much else.

The first one is spending a lot of time in a method called "releaseLock()". For some reason, this is taking a long time because "getComponentType()" is taking a much longer time than usual.

releaseLock

The second one is after I did a "hack" to remove the cost of "releaseLock()" - but now it just spends lots of time in "getLock()" due to getClass() and currentThread() taking much longer than normal:

getLock

But the important thing is that if I simply change the order in which the code is initialized, none of this code takes very long to execute (it doesn't even show up in the profiler at all).

If I was to optimize getLock() the application still performs much more slowly. The problem really seems to be that methods such as getClass() are taking too long. There's no way to compensate for this - getClass() gets called in too many places!

The performance difference is noticeable even without the profiler running.

Please also remember that we cannot change any of this code - it's an external component. The challenge is to explain why the code executes so much more slowly in some circumstances vs others.

like image 941
Paul Hollingsworth Avatar asked Jan 09 '13 09:01

Paul Hollingsworth


1 Answers

You could try to take several mixed (java+native) jstack -m thread dumps of the application under the load.

This would probably give some hints on what is happening under the hood of Object.getClass().

See also If profiler is not the answer, what other choices do we have?.

Also take a look at What does thread dump looks like when JVM spent time in GC. Cause usual JVM thread dumps may not always be perfectly accurate as they happen only on safepoints.

like image 123
Vadzim Avatar answered Oct 21 '22 00:10

Vadzim