RFC: Change C++ ABI so that interface dispatch does not depend on reflection.

David Daney ddaney@avtrex.com
Tue Jan 31 07:07:00 GMT 2006


Background:

I have been looking at removing reflection data from objects compiled 
with the C++ ABI in the interests of reducing the size of the generated 
code/data.  Currently reflection data is about 15% - 20% of the size (as 
reported by size) of a 1000 class application linked with libgcj.  As it 
turns out, some of the reflection data is currently needed at runtime. 
Two places that it currently seems essential are:

1) The <clinit> method.  _Jv_InitClass checks to see if a class has a 
method named <clinit>.  If it does, it executes it at class 
initialization time.  The check uses reflection data.

2) Creation of interface dispatch tables.  The class initialization code 
  builds interface tables based on the method names in the reflection data.

The first case is simple to handle.  If a method is the <clinit> method 
just emit the reflection data.

For interfaces it the problem is intractable.  You can emit reflection 
data for the methods that implement an interface, but you never know if 
a method might implement an interface in a sub class.

Example:

public class X
{
     public void run() {System.out.println("Running");}
}

public class Y extends X implements Runnable
{
     public static void main(String args[]) {....}
}

For class X I cannot omit reflection data for run() as it may be needed 
in a subclass.  If fake reflection data for run() were emitted for class 
Y so that interface dispatch worked properly then 
Class.getDeclaredMethods would return incorrect data.

Proposal:

Build interface dispatch tables at compile/link time.

Change runtime to use new tables instead of building its own at class 
init time.

New option -fno-reflection to disable generation of reflection data 
(except <clinit>).

Alternative:

New option -fno-reflection to disable generation of most reflection 
data.  Still emit data for methods that implement interfaces.  If super 
class method supplies interface method but does not implement the 
interface, then generate fake data (we are trashing reflection so who 
cares about having it be even more incorrect).

Pros and Cons:

If the proposal is implemented the amount of static data associated with 
uninitialized classes will increase thus increasing the executable image 
size and perhaps adversely effecting data cache performance by 
decreasing locality.  Overall memory usage after all classes are 
initialized would be similar to current.  Some of the data cache 
problems may be avoided if the interface tables are put in their own 
section.

In the case of -fno-reflection there would still be an overall savings 
as the reflection data is usually larger than the interface dispatch 
tables.  It would only be worse in pathological cases (many interfaces 
all with the same methods).

Class initialization (and thus application startup) would be faster as 
the compiler and linker are doing some of the work.

For the Alternative the advantage is that with out -fno-reflection 
nothing changes.

The disadvantage is that with -fno-reflection the executable and in 
memory sizes are larger than with the proposed change.

Of the two the Alternative is probably quite a bit easier to implement.

Thoughts?

David Daney



More information about the Java mailing list