As the Android Runtime later demonstrated, nothing prevents you from distributing an architecture-independent representation, AoT-compiling to native code at installation time, instrumenting the native code, and then re-optimizing at runtime and/or in a background batch process if your instrumentation statistics deviate substantially from what was available the last time you re-optimized.
Apart from the extra disk space for both bytecode and native representations, something like TIMI allows for the best of both worlds as far as AoT and JIT. (It's also nice that TIMI doesn't require a garbage collector to be running.)
I'm not aware of modern AS/400 dynamically re-optimizing binaries, but doing so wouldn't break anything. Given the conservative nature of mainframe users, I imagine dynamic re-compilation would need to be an opt-in feature.