What is the underlying reason for this?
Most terminals is line buffered by default, Java does not receive input until a newline.
Is it a limitation of Java?
Some ancient terminals might only have line-buffered input; though it should be possible to disable buffering in most modern terminal.
Is this behavior system-dependent (I'm on Ubuntu)? How does it work on Mac? Windows?
Yes.
Is it dependent on the specific terminal I run the application in? (For me it behaves like this in Eclipse and in gnome-terminal)
Yes.
Is there a workaround?
There are platform specific hacks. curse
in Linux and Unix-like platforms, and getch() in Windows. I'm not aware of any cross-platform way.
related: Why "Press any key to continue" is bad idea:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…