I worked on this years ago. Gcj did support loading and interpreting bytecode alongside the AOT-compiled code. libffi's closures were originally implemented to support calling interpreted methods from AOT-compiled code, because a class's vtable could include a mix of AOT-compiled and interpreted methods. You could also compile jar files directly into .so files, which would get loaded and used at runtime if a classloader ever loaded the corresponding jar.