Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting performance in different levels when casting down

Lets assume we have three (or more) classes

public class A {}

public class B extends A {}

public class C extends B implements G {}

Assume each class has its own 20 (or more) methods.

Is casting to C vs casting to A has larger impact on performance? How does Java casting work under the hood?

Does it have to check for all methods and fields for presence by reflection when casting down?

Edit: Does the size of classes (number of fields and methods) impacts the performance when casting? I'm interested in both OpenJRE and Dalvik.

For the reference, I know that upcasting can be done with no problems.

like image 951
Yaroslav Mytkalyk Avatar asked May 24 '13 18:05

Yaroslav Mytkalyk


2 Answers

The performance of the casting depends on the JVM implementation.

The JLS 5.5 only determines the requirements for the casting (which includes a recursive algorithm), but does not set any requirements upon the implementation. Actually the runtime cast rules in 5.5.3 are also determined the same way. All JVM implementations that produce th same result as the proposed algorithm are accepted as a proper JVM.

Generally, casting down to C takes a little bit more time since the JVM must examine the runtime type of the object. When casting up to A it has no reason to do the same check, since B extends A.

Actually, the JVM does not care about the number of methods and fields. It only compares the type hierarchy, the same you can examine with reflection (o.getClass())

I made a sample code as follows, one downcast, then an upcast:

Object o = new Integer(1);
Integer i = (Integer) o;

Object o2 = i;

The compiled bytecode is the following:

 0  new java.lang.Integer [16]
 3  dup
 4  iconst_1       <-- 1 as a parameter to the constructor
 5  invokespecial java.lang.Integer(int) [18]   <-- constructor
 8  astore_1 [o]       <-- store in 'o'
 9  aload_1 [o]
10  checkcast java.lang.Integer [16]    <-- DOWNCAST CHECK, SPECIAL BYTECODE
13  astore_2 [i]
14  aload_2 [i]
15  astore_3 [o2]   <-- WITH UPCAST NO CHECK

So, there is a specific JVM instruction that checks the element on the top of the stack with a given class.

With upcast, there is no check at all.

The size of the classes (number of fields, methods, actual footprint) does not matter, because the casting examines the Class (the metadata, which is actually an object).

The number of hierarchy levels, and the number if implemented interfaces (if casting to an interface) does matter, because that is the traversable inheritance/implementation tree to check.

I would be surprised if there wouldn't be some kind of cache for this check.

like image 55
gaborsch Avatar answered Oct 07 '22 02:10

gaborsch


For a detailed architecture of checkcast (which was mentioned in other response as a JVM mechanism for downcasting) in HotSpot, take a look at this conference paper:

Fast subtype checking in the HotSpot JVM

A quote from the abstract:

In actual benchmark runs our technique performs complete subtype checks in 3 instructions (only 1 memory reference) essentially all the time. In rare instances it reverts to a slower array scan. Memory usage is moderate (6 words per class) and can be traded off for time.

So if you don't write some very low-level code with a lot of casting, the impact is negligible.

like image 32
pwes Avatar answered Oct 07 '22 03:10

pwes