I've been thinking about how J2EE containers work. They provide a world of many layers: application-container, container-Java libraries, Java libraries-byte code, byte code-JVM, JVM-platform libraries, platform libraries-native code, native code-OS, OS-hardware. (And there are, of course, calls from higher layers to lower layers even further down.) That's a lot of layers. I wonder what could be stripped out?
For example, Java handles thread scheduling for Java code, but the OS does the same for native code. How much are Java threads mapped onto native threads? (The answer varies quite a bit between platform and JVM implementation.) The same question arises comparing byte code to native CPU instructions. How much of a JVM could be performed directly by an OS?
There is plenty of research in these areas already (I was going to make a list of interesting links, but Google turned up so much, it hardly seems worth the effort—Google sure changes how research works), so I am looking forward to reading more about these ideas over time. Layers are good for abstraction, but over time the most successful abstractions become concrete and implementors take advantage to improve performance and transparancy. Witness pointers: C abstracted hardware addressing as pointers, which then C++ abstracted as virtual methods, which then Java abstracted as methods: success begats success.
I expect the same trend to continue as byte code slowly displaces native code and JVM-like things appear more in hardware and operating systems such as the cool work at Transmeta.