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