Changing to an archive that stores a bunch of classes in a single file should help quite a bit. In essence, every time we run a Java applet we're paying a startup penalty so the developer doesn't have to do a link step. Since the Java classes don't change all that often, doing the link and placing the linked classes in an archive is generally preferable. This leaves execution performance as the biggest problem. The best solution to this difference in performance is to translate Java source or byte code into native code.
Most platforms have native code translators either already available or under development.
This means more work for the memory manager and the garbage collector. And for many application there is a specific solution to memory allocation and reclamation that will outperform the general one. Nonvirtual methods are implemented at functions, while virtual methods require an extra level of indirection through a method table. All Java methods are virtual, which means more overhead on every method invocation. This does make life a lot easier for the programmer, who doesn't have to worry about which methods are resolved when.