It's interesting to look at the "why" here. Note that C and UNIX were born together. The UNIX linker and the C language both had no idea at all of function overloading. Because of this (and to some extent, the cause of this) the symbols that the linker would work with consisted only of function names, not argument lists as in Java method signatures. Therefore, C allows main to have 0 or 2 (or even 3 -- did you know that historically, you could retrieve a pointer to an environment block as the last argument to main() ?) argument, merely because the linker couldn't tell the difference, since it has no idea how many arguments there are anyway. If the runtime library asks for "main", it gets "main", regardless of how many arguments.
C++ supports overloading, and so it can't use plain function names as linker symbols. Instead, it uses name mangling -- a process by which names are decorated with extra data to describe the argument lists. The linker then works with these mangled names. This has many side effects. For example, for a C++ function to be callable from C, it has to be marked as extern "C". This turns off name mangling. Another side effect is that you often can't link C++ object files emitted by different compilers, since the name-mangling scheme (and actually, lots of other stuff) isn't specified by the language standard.
Java's different because everything is specified, by design. And therefore, the signature of main() is specified exactly, too.