Skip to main content

Reflection, Field.get, and Class.isAssignableFrom

1 reply [Last post]
atripp
Offline
Joined: 2003-07-15

Hi,

I'm hitting a major performance problem while using reflection. I'm reading data off of disk as a sequence of bytes, and decoding the bytes and storing them in Java object instances (I'm decoding COBOL/EBCDIC files). In my test app, I read 1,000,000 lines of text, each about 70 bytes, and each line gets decoded and stored into a Java object, and then doing some calculations.

The problem is that the Field.get() call is taking far longer than all other processing, *including* actually reading data from disk. Here is the top part of the "hprof" output:

rank self accum count trace method
1 33.05% 33.05% 307 300380 java.lang.Class.isAssignableFrom
2 7.97% 41.01% 74 300388 java.lang.Class.isAssignableFrom
3 2.91% 43.92% 27 300395 java.lang.Class.isAssignableFrom
4 2.26% 46.18% 21 300411 java.lang.Double.doubleToLongBits
5 2.15% 48.33% 20 300404 sun.nio.cs.SingleByteEncoder.encodeArrayLoop
6 1.83% 50.16% 17 300420 sun.nio.cs.SingleByteDecoder.decode
7 1.72% 51.88% 16 300449 java.io.DataOutputStream.write
8 1.61% 53.50% 15 300398 sun.nio.cs.SingleByteDecoder.decode
9 1.51% 55.01% 14 300422 sun.nio.cs.SingleByteEncoder.encodeArrayLoop
10 1.51% 56.51% 14 300423 java.lang.StrictMath.floor
11 1.40% 57.91% 13 300473 sun.nio.cs.SingleByteEncoder.encodeArrayLoop

And here is one of the stack traces:
TRACE 300380:
java.lang.Class.isAssignableFrom(Class.java:Unknown line)
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36) sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
java.lang.reflect.Field.get(Field.java:357)

So we can see that almost half of the time the app is in the Class.isAssignableFrom() method. I can see from the stack traces in the hprof output that all calls to Class.isAssignableFrom() originate from Field.get().

Looking at the source for Field.get(), I can't see any workaround. Does anyone have an suggestions for how I might be able to turn this checking off or speed it up? I've already called Field.setAccessible(true), which cleared up another bottleneck, but not this one.

It seems to me that there's a real design flaw here. I've got a Field instance and I call get() and pass an object of a particular class. Once this "isAssignableFrom" check passes, we know it will pass on all subsequent calls to get() with an instance of that same class. No need to keep checking on every call.

Thoughts?
Andy

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
briand
Offline
Joined: 2005-07-11

We are aware of a performance problem with isAssignableFrom.
See the following bug report:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6461827

The cause is known and a solution is being worked. Due to
how late we are in the JDK 6 release cycle, the fix will
not show up in the initial release of JDK 6. You may want
to add a vote for this bug or escalate it if you have a
service contact.

HTH
Brian