Can you back that up?
Modern JVM bytecode is cheap to verify and gives you very strong properties like memory and type safety, i.e. the app will not have buffer overflows or type confusion attacks in it.
WASM gives you virtually no guarantees about the software running in it, beyond that it (maybe) can't escape its sandbox.
It's a much better universal bytecode than any other offerings currently available.
I think that's a very strong statement for something so debatable.
WASM appears, to me eyes, to have numerous serious flaws that make me wonder why people are so excited about it. JVM bytecode appears to beat it in every aspect.
1. No GC support, no real workable plan to get there because there's also no type system worth a damn. They've been looking at it for years and this article says all they've got is a tiny stepping stone - no actual GC, just a way to mark pointers to things that came from JS in the type system. This wouldn't matter if the future of the web was software written in C, but if it is, god help us all.
2. No threading. JVM has been thread safe from the start, and has had a huge amount of work put into its memory model, so you can reason about the nature of bytecode when run on different CPUs and in the presence of multi-threading. Moreover making a runtime like V8 fast is much harder if you try to make it thread safe. JVMs have a long history of being fast in the presence of large scale threading but no WASM supporting VMs do.
3. No support for exceptions, apparently at least one failed attempt to add it. Even LLVM has support for exceptions. Again, no big deal if the future of the web is C99 but what a bad joke if it is.
4. No FFI of any use.
5. No dynamic code loading.
6. Tooling is poor or non-existent.
7. Ignoring these differences, WASM bytecode looks a lot like JVM bytecode e.g. is a stack based language that requires compilation client side via JITC to approach good performance.
As far as I can tell it's a significant regression from what Java could do even 20 years ago. And don't start talking about security. WASM integrations already opened up critical security bugs in browsers:
https://bugs.chromium.org/p/chromium/issues/detail?id=729991 https://bugs.chromium.org/p/chromium/issues/detail?id=729991
https://bugs.chromium.org/p/chromium/issues/detail?id=794091 https://bugs.chromium.org/p/chromium/issues/detail?id=794091
https://news.ycombinator.com/item?id=15712270 https://news.ycombinator.com/item?id=15712270
If you think WASM is magically immune to sandbox bugs, you're wrong.
> WASM appears, to me eyes, to have numerous serious flaws that make me wonder why people are so excited about it.
The reason to be excited about it is to have a universal sandbox to portably run untrusted code regardless of the source. That's unprecedented flexibility for something so widely deployed.
Neither the JVM or the CLR provide such a sandbox for code that uses pointers. LLVM IR is not portable, is not sandboxed and is always in flux.
As for your list of "flaws", they aren't flaws at all. A flaw is a feature that cannot be supported, even in principle. Everything you list are possible as extensions to the core type system.
WASM was designed with efficient verification in mind, and with mechanized formal proofs as I point out at [1]. Java's verification was always a hack, and the mechanized proofs of Java's verification procedure never encompassed all JVM bytecodes, and full verification was always too costly to perform at runtime. Java has numerous security problems, not just with verification, but also vulnerabilities due to full abstraction failures.
As I mentioned in [1], the security-focused Joe-E language explicitly chose to decompile JVM bytecode to plain Java to avoid all of the numerous documented full abstraction failures of the JVM [2].
The similarities between the stack-oriented bytecodes are entirely superficial.
[1] https://news.ycombinator.com/item?id=17575111 https://news.ycombinator.com/item?id=17575111
[2] http://lambda-the-ultimate.org/node/3830 http://lambda-the-ultimate.org/node/3830
Neither the JVM or the CLR provide such a sandbox for code that uses pointers. LLVM IR is not portable, is not sandboxed and is always in flux.
Actually, the CLR supports pointers and the JVM can run arbitrary LLVM bitcode (so C, C++, Rust etc) in a memory safe way with bounds checking and garbage collection these days. Check out Sulong and Safe Sulong:
http://ssw.jku.at/General/Staff/ManuelRigger/ASPLOS18.pdf http://ssw.jku.at/General/Staff/ManuelRigger/ASPLOS18.pdf
JVMs can also manually allocate memory using the Unsafe class, I suppose if you wanted WASM like protection semantics that API could be constrained to a particular memory region and become "SortaUnsafe" for example. You could then compile C to such a dialect. The LLVM bitcode on Graal approach is likely to work better though,.
However, realistically most new software is not being written in C or even C++ for that matter. Most developers use managed languages. And the JVM can do a much better job of that than WASM can.
A flaw is a feature that cannot be supported, even in principle.
This is a fascinating definition of flaw that I haven't previously encountered.
In what sense does the JVM not do "full verification at runtime"? Also if you have some more material on which bits of the JVM bytecode set aren't formally verified I'd like to read that. I can imagine, that the latest features may not have been done, but the older JVM bytecode sets were formally verified at least.
> Actually, the CLR supports pointers
I said it doesn't provide a sandbox for pointers. CLR pointers can corrupt your whole VM instance. WASM's lightweight bytecode with no runtime can support in-process heap isolation.
> JVM can run arbitrary LLVM bitcode (so C, C++, Rust etc) in a memory safe way with bounds checking and garbage collection these days. Check out Sulong and Safe Sulong:
Nice find. Still, look to be interpreted though.
> In what sense does the JVM not do "full verification at runtime"?
The last report of a formalized semantics for verification that I saw was over 10 years old:
https://repositories.lib.utexas.edu/handle/2152/2763 https://repositories.lib.utexas.edu/handle/2152/2763
The JVM bytecode has significant verification challenges as discussed in this paper and by Leroy in the other papers I linked. The Joe-E papers I linked also discuss the problems of targeting the JVM at length.
As I linked in my other comment, WASM was built with mechanized proofs nearly from the outset. They learned from the mistakes made in the CLR and JVM.
All of your "serious flaws" are actually fixable. Obviously WASM tooling isn't as mature as other older ecosystems, this will get fixed over time.
I don't think JVMs where without any security bugs, since WASM is mainly used in browsers right now, security is a MAJOR concern. Java-Bytecode was designed for a different purpose. Try to compile a language with multi-inheritance to Java-Bytecode, it's a pain. WASM is designed in a more language-agnostic way, that's why GC and Exception Handling is much harder to specify than in the JVM.
BTW: GC'ed languages can already be compiled to WASM: they more or less "just" need to compile the GC to WASM too. The GC proposal would only allow to reuse the embedder's (most likely the browser) GC.
Sure, but see the comment by munificent. You're saying, well JVM bytecode sucks because it's hard to compile C++ to because it lacks multiple inheritance, and arguing this makes WASM more language agnostic.
But. Then you admit that compiling Java to WASM is hard because there's no GC, you'd have to ship your entire GC with the app and it wouldn't be fast because GCs like to integrate with the JIT compiler and WASM is the JIT compiler here. Also WASM JITs don't really understand managed code patterns well.
So how is WASM more language agnostic? Seems like (if we ignore Graal) WASM has trouble with languages JVM bytecode is good at, and vice-versa. Quite comparable, no?
BTW even saying C++ is easy to compile to WASM is tricky because WASM apparently has no exception support, and exceptions are a part of the C++ language. Likewise for vendor extensions like vector intrinsics, inline assembly etc. At best you can handle a subset of the language.
So in the end I don't buy that it's really more generic. As munificent says, it seems more like people aren't really sinking their teeth into the tradeoffs involved.
Let me be clear on this: I am NOT saying that Java-Bytecode sucks. I am simply saying that WASM is better for the Web's use case. There is no shame in that, WASM was designed for that and could learn from the experience with many bytecode formats and also asm.js.
Even if we would agree that the JVM is as good as WASM as a language-agnostic bytecode, WASM still makes sense since it doesn't come with all the baggage of the JVM like class files, many bytecodes that exactly match the Java semantics but can't be used in other languages. Browser-vendors would still have to add new bytecodes for common operations for both size and speed reasons. So it made sense to design a new bytecode format. WASM even allows streaming compilation: The browser can start compiling bytecode before it downloaded the whole file.
Yes, there are a few features missing from WASM. But just look how many applications have already been compiled for the web. The missing features are not that relevant for many large existing and performance-sensitive native applications written in C/C++. We don't need to rewrite this applications in JS. I mean JS wouldn't even be fast enough for that anyways. That's what WASM was designed for and even according to you WASM is better suited for this than Java-Bytecode.
Inline assembly and vector extensions would also be problematic in Java Bytecode.
The JVM doesn't even have unsigned types.
There is a reason why every "C on the JVM" project, of which there have been many, used MIPS GCC and then interpreted the MIPS machine code at runtime. (Yes, really.)
> No GC support
> No threading
> No exceptions
Along with not forcing any object model, this looks like very reasonable design choices to me. (I'd add "no global mutable state", but it's being added.)
Reason 1: this is very similar to what a (RISC) CPU would offer. If anyone need to implement these features, they can be implemented on top of WASM, as they can be implemented on top of a CPU IS. A small specification not loaded with such complex issues as GC or object model is much easier to keep correct and fast. Also, any advances in e.g. GC can be pushed to older WASM implementations, because they don't replace the VM, they are libraries.
Reason 2: Using message-passing between processes ("workers") instead of threading, and Option/Maybe instead of exceptions, is a known way to avoid a large number of problems. The current WASM design makes this approach simple and reasonably natural. There's a reason why Erlang is designed as it is; WASM can take a page from its book.
JVM's most significant vulnerability is non-technical, and it's already been p0wned by the Larry Ellison Attack.
Does WASM have in place any mechanisms to prevent Oracle or other malicious destructive companies from co-opting it, copyrighting its APIs, and running it into the ground for profit?