Not at all. jar is just a zip with a different extension +some metadata in META-INF (including dependencies). class are compiled java files but they do contain all kinds of metadata, including variable names and debug info (if you choose to retain it). they contain all methods and fields with their original names (along with annotations), so the reflection APIs work. Decompiling a class file is trivial to a point the original line numbers can be restored.
>Otherwise perhaps Java would've completely obsoleted C
Java does require a managed runtime written mostly in C/C++.
>Some of us design applications which can't tolerate the worst case GC pauses
The current breed or low latency GCs w/o a stop-the-world phase should suffices for a large set of applications.
>we can't afford to spend extra time heap-allocating nearly everything.
That has not been an issue for quite some time, heap allocation can be elided, and under normal condition is just a pointer bump. Per thread private allocation is by far the most common case - the garbage collection of non old-gen referenced objects is totally trivial too (i.e. memset). Even shared (cross thread/area) allocation is a CAS'd bump in most cases. Note: copy/generational garbage collectors copy objects that are referenced by non-young-gen ones to another area, then zero the original area.
With that being said - Java (and managed languages) are no panacea.
Java can be optimized beyond all recognition, into bytecode that can no longer be represented by the Java language. At least that used to be the case in the past. It is not different from other binaries, except the target system is a virtual CPU rather than a real one.
Java also deprecated all sorts of things over the years. Not to mention applets being completely killed off. I have Java binaries from 25 years ago that could no longer run at all with a contemporary run-time already 10-15 years ago.
Not to mention much of real-world Java is platform-specific. Not often native code perhaps, but more subtle things like hardcoded paths or forgetting to properly use the correct path-separator. Installers used to often be platform-specific as well. Maybe that has been solved, but you would still run into trouble trying to install an old Java application that has an installer only supporting contemporary Windows and Mac systems.
> Java can be =optimized= beyond all recognition, into bytecode that can no longer be represented by the Java language.
I am not sure how that works, Java is all about JIT. Bytecode almost doesn't matter. Personally I can read assembly (and years [decades] back could just read hex). So even obfuscated (not optimizied) Java is quite readable. Still, the class files do retain all method declarations, all constant pool entries and all bytecode (again trivial to decompile). There have been few changes in the class format of course.
> Java binaries from 25 years ago that could no longer run at all with a contemporary run-time already 10-15 years ago.
Need a shorter frame, Java 8 (10y back) could run pretty much anything from java 1.0 (or even 0.9). It's quite more recent - Java 9 (2017) that introduced project jigsaw. Prior that Java was by far the most backward compatible platform. Still is, for most applications. Do note deprecation mean(t) - do not use in new projects, not it has been removed; again those are more recent changes.
>Not to mention much of real-world Java is platform-specific.
Again, that's super rare nowadays. Stuff like zstd might load a library but even then the native code interfaces are the same across pretty much all platforms. If you talk about native UIs you might have some point, of course.
>to properly use the correct path-separator.
Windows with its backslash is notorious, yet - there is no reason to use backslash any longer, for like 25years now. All Windows paths do work with forward slash (aside that the separator is readily available in java.io.File)
Not at all. jar is just a zip with a different extension +some metadata in META-INF (including dependencies). class are compiled java files but they do contain all kinds of metadata, including variable names and debug info (if you choose to retain it). they contain all methods and fields with their original names (along with annotations), so the reflection APIs work. Decompiling a class file is trivial to a point the original line numbers can be restored.
>Otherwise perhaps Java would've completely obsoleted C
Java does require a managed runtime written mostly in C/C++.
>Some of us design applications which can't tolerate the worst case GC pauses
The current breed or low latency GCs w/o a stop-the-world phase should suffices for a large set of applications.
>we can't afford to spend extra time heap-allocating nearly everything.
That has not been an issue for quite some time, heap allocation can be elided, and under normal condition is just a pointer bump. Per thread private allocation is by far the most common case - the garbage collection of non old-gen referenced objects is totally trivial too (i.e. memset). Even shared (cross thread/area) allocation is a CAS'd bump in most cases. Note: copy/generational garbage collectors copy objects that are referenced by non-young-gen ones to another area, then zero the original area.
With that being said - Java (and managed languages) are no panacea.