Here is the part that matters in practice, and none of it was mentioned in the original.
**Locale-sensitive methods.** The classic demonstration, which I ran on one machine with one class file:
default locale = en_IN "title".toUpperCase() = TITLEdefault locale = tr_TR "title".toUpperCase() = TİTLE
Identical bytecode. Identical JVM. Different output, because the no-argument toUpperCase() consults the **default locale**, and Turkish has a dotless uppercase I. A method that passes a test in one region can fail in another for no apparent reason. This is not exotic: it has repeatedly broken real systems sorting user-facing text and comparing usernames.
**Default character encoding.** Verified on this machine:
file.encoding = UTF-8native.encoding = UTF-8line.separator = \nfile.separator = /path.separator = :
All four are platform-dependent, and one changed recently. **JEP 400 made UTF-8 the default file.encoding from JDK 18**, where before it followed the platform's locale. So code written against JDK 17 or earlier can behave differently when moved to 18+. Conversely, JDK 8's default is not UTF-8 on Windows, where it is typically windows-1252. Any code relying on the default rather than an explicit charset is relying on something that has changed across versions.
**String comparison.** "a".compareTo("B") returns **31**, not a negative number, because compareTo is a raw UTF-16 code-unit comparison. Humans expect "a" before "B". Getting linguistic ordering requires java.text.Collator, which is locale-dependent and therefore reintroduces platform dependence in exchange for correctness.
**Native code and file paths.** JNI libraries are per-platform binaries. Paths differ by separator, by case sensitivity (Windows and macOS are typically case-insensitive, Linux is not), and by reserved characters.
| Difference | Linux | Windows |
|---|
| Path separator | / | \ |
| Path case sensitivity | Case sensitive | Case insensitive |
| Line separator | \n | \r\n |
| Drive letters | None | C:\ |
| Max path length | Deeply nested | Historically 260 chars |
Case sensitivity alone causes real bugs: code that passes on Windows can throw FileNotFoundException on Linux because the filename case no longer matches.