If you think about it, "cross-platform Java" is mostly a Unix/Linux phenomenon. A lot of the Java API and behavior is copied from and influenced by Unix/Linux/Posix. Really cross-platform Java code ("write once, run everywhere") is mostly run under Unix web servers. It is virtually non-existent on desktop and server Windows (which is, by the way, 90% of all desktops, 70% of netbooks, around 30% of servers). Java is widely used in mobile devices, however there Java is hardly cross-platform: mobile devices are resource-constrained so that Sun had to invent different reduced sets of Java (Java ME etc.), and different phone models run Java so differently that developers had to produce different versions of a same application for each model! (at least it was true a couple of years ago, don't know how it is today, with smarter phones; i'm phone-agnostic)
Both Java and C# (through mono) support a wide range of processor architectures, with C# lacking support for some rarely-used architectures. All in all, x86 and x64 are still dominant nowadays, and both frameworks provide equally good support for them.
So if you think about it, the Java guys behave the same way the Windows guys do: they live in their little world and believe their little world is everything while in fact they're bound to a specific platform few people outside that platform care about.
.NET Api is based on WinApi? Java API is based on Unix/Posix.
.NET isn't popular on Linux? Java isn't popular on Windows.
.NET isn't installed by default on Linux? Java isn't installed by default on Windows.
et cetera, et cetera.
All in all, in practice .NET isn't much less "cross-platform" than Java, in my opinion. They're two sides of the same coin. Just because JVM has an official implementation for Windows, doesn't tell much.
BTW, Java HotSpot contains A LOT of inline assembly making it very difficult to port to other processor architectures. If I were going to be cross-platform, I myself would consider using as much C as possible in the first place. Wikipedia:"Ports of HotSpot (OpenJDK's Virtual Machine) are difficult because the code contains a lot of assembly in addition to the C++ core." They even developed a project, zero-assembler Hotspot, to make the "cross-platform" JDK be adequately portable.
Both Java and C# (through mono) support a wide range of processor architectures, with C# lacking support for some rarely-used architectures. All in all, x86 and x64 are still dominant nowadays, and both frameworks provide equally good support for them.
So if you think about it, the Java guys behave the same way the Windows guys do: they live in their little world and believe their little world is everything while in fact they're bound to a specific platform few people outside that platform care about.
.NET Api is based on WinApi? Java API is based on Unix/Posix.
.NET isn't popular on Linux? Java isn't popular on Windows.
.NET isn't installed by default on Linux? Java isn't installed by default on Windows.
et cetera, et cetera.
All in all, in practice .NET isn't much less "cross-platform" than Java, in my opinion. They're two sides of the same coin. Just because JVM has an official implementation for Windows, doesn't tell much.
BTW, Java HotSpot contains A LOT of inline assembly making it very difficult to port to other processor architectures. If I were going to be cross-platform, I myself would consider using as much C as possible in the first place. Wikipedia:"Ports of HotSpot (OpenJDK's Virtual Machine) are difficult because the code contains a lot of assembly in addition to the C++ core." They even developed a project, zero-assembler Hotspot, to make the "cross-platform" JDK be adequately portable.