As others have said, portability is a somewhat fuzzy concept. From a certain point of view, C is actually more portable than Java. C makes very few assumptions about basic hardware. It does not even assume that the byte is 8 bits, or that negative numbers should be represented using two additions. Theoretically, as long as you have a Von Neumann based machine and compiler, you can go with C.
In fact, the Hello world program written in C will run on many other platforms than the Hello world program written in Java. You could probably get the exact same hello world program that runs on PDP-11 and iPhone.
However, the reality is that most real-world programs do a lot more than the output of "Hello world". Java has a reputation for being more portable than C, because in practice it takes a lot more effort to port real C programs to different platforms than in real Java programs.
This is because C is ANSI-C, which is a general-purpose language with bare bones. It does not support network programming, threads, or GUI development. Therefore, as soon as you write a program that includes any of these things, you should abandon a less portable extension in C, such as Win32 or POSIX or something else.
But with the help of Java, network programming, streaming, and GUI tools are language-defined and built into every VM implementation.
However, I think that many programmers also underestimate the progress of modern C / C ++ regarding portability these days. POSIX is essential for providing cross-platform streaming, and when it comes to C ++, Boost provides network and streaming libraries that are basically as portable as everyone in Java. These libraries have some platform-specific quirks, but also Java.
Essentially, Java relies on every platform that has a virtual machine implementation that will interpret byte-code in a predictable way, while C / C ++ uses libraries that contain platform-specific code using a preprocessor ( #ifdef s). Both strategies allow cross-platform streaming processing, networking and GUI development. It's just that Java has made faster progress than C / C ++ when it comes to portability. The Java language specification was associated with streams, networks, and the graphical interface from almost the first day, while the Boost network library appeared only in 2005, and only in 2011 with C ++ 11 standard portable streaming processing was included in C ++.