The Java team at Oracle writes about OpenJDK developments such as virtual threads, value classes, Valhalla, and data-oriented programming.
Commenters recommend it, including its podcast, as an official source from the Java developers, and cite it for talks and posts on Valhalla and Loom.
> Most of Java problems come down to unfortunate design choices in the past. E.g. checked exceptions vs lambdas
Funnily enough, your example has actually supported my point.
They just released a proposal that effectively side-steps the problem of checked-exceptions-in-lambdas. Here is a link -- https://inside.java/2023/12/15/switch-case-effect/
This is still just a proposal, so nothing is hammered out. And we can talk about the merits of this solution. But my point is, by focusing on designing features the way they have, you can minimize intrusion while maximizing the value provided. I think this proposal demonstrates that extremely well.
This proposal allows the developer to maintain all the good parts about checked exceptions and lambdas, while being able to side-step the major downside.
> Don't think like Java is a good example of that, more like the anti-example. Plenty of more sophisticated languages move way faster without negative effects on long term progress (C#, Kotlin, to some extent Scala)
To be clear, when I say long term, I am measuring on the scale of decades. In that respect, I actually don't think your statement is correct.
To give an example with Kotlin, someone (I think Brian) talked about Kotlin's release strategy for features being great for short term, but costly in the long term. Kotlin had record-esque classes long before Java ever got theirs, but now that Java finally has theirs, Kotlin is using an annotation to disambiguate between Java style…
Java had an extremely advanced and strict sandbox for many years.
It offered of course also the possibility to blacklist everything by default.
The problem with such a granular sandbox is that it's too complex for most use cases.
When you need to whitelist any and every call to the outside world this becomes very tedious.
That's why Java now removes the sandbox…
https://inside.java/2021/04/23/security-and-sandboxing-post-securitymanager/
Let's see how this works out for WASM.
I guess: Without resorting to using some language(s) with build-in support for capability security a whitelist based sandbox approach won't ever work without issues.
First of all you can forget about C/C++. Everything in this languages assumes free access to the system.
Rust does not have any support for capabilities either (yet, and for the years to come at least).
The best current WASM sandbox implementation, which is in WasmTime not Wasmer, is not more than a FS block. (And the memory safety guaranties you get in any VM language, of course).
https://docs.wasmtime.dev/security.html
I don't find any such feature mentioned in the Wasmer docs. It seems completely without any sandbox! (To stress it once more: All VM languages are memory safe. That's not sandboxing. All the "sandboxed by default" claims are misleading, at least).
https://github.com/wasmerio/wasmer/issues/221
That even people here on HN believe in the currently unfulfilled WASM security promises shows only how good the WASM…
They wouldn't have had better performance, though. There is no significant performance penalty we're paying, although there's a nuance here that may be worth pointing out.
There are two different usecases for coroutines that may tempt implementors to address with a single implementation, but the usecases are sufficiently different to separate into two different implementations. One is the generator use case. What makes it special is that there are exactly two communicating parties, and both of their state may fit in the CPU cache. The other use case is general concurrency, primarily for IO. In that situation, a scheduler juggles a large number of user-mode threads, and because of that, there is likely a cache miss on every context switch, no matter how efficient it is. However, in the second case, almost all of the performance is due to Little's law rather than context switch time (see my explanation here: https://inside.java/2020/08/07/loom-performance/).
That means that a "stackful" implementation of user-mode threads can have no significant performance penalty for the second use case (which, BTW, I think has much more value than the first), even though a more performant implementation is possible for the first use case. In Java we decided to tackle the second use case with virtual threads, and so far we've not offered something for the first (for which the demand is significantly lower).
What happens in languages that choose to tackle both use cases with the same…
> They just released a proposal that effectively side-steps the problem of checked-exceptions-in-lambdas. Here is a link -- https://inside.java/2023/12/15/switch-case-effect/
This is fine but removes only about 10% of the pain of mandatory exception handling inside typical lambda.
Nothing short of making exceptions transparent to lambda receivers will cut it for me.
> Kotlin is using an annotation to disambiguate between Java style records and Kotlin style records
This is inherent risk of building on top of something you don't control. Don't really see this as fair comparison. It's a known design constraint. The only way to avoid it is to not build on top of Java or not adding any features on top of Java.
> To give another example with C#, there has been a lot of recent discussion about finding potential alternatives to their async-await concurrency model. They cite the level of effort it takes to maintain the async await style code and the costs that come from this.
I had a very different take-away. They did PoC with virtual threads and decided it's not worth the switch now and async-await that they have is good enough.
https://github.com/dotnet/runtimelab/issues/2398
> Some of the languages it gets compared too aren't even that old yet.
C# is more than old enough to drink and Scala just had its 20th birthday this weekend :) Java is only 4 years older than C#.
I like:
Defn: https://podtail.com/en/podcast/defn/
The REPL: https://www.therepl.net/episodes/ (Seems to have gone quiet)
ClojureScript Podcast: https://clojurescriptpodcast.com/
Functional Design in Clojure: https://clojuredesign.club/ (Also seems to have gone quiet since December)
LispCast by Eric Normand: https://lispcast.com/
Cognitect, the company behind Clojure also has their own podcast but I haven't found it to be that interesting most of the time, at least yet: https://www.cognitect.com/cognicast/index.html
Not specifically Clojure-related but has discussed a few times including wit Rich Hickey (as well as other unrelated great conversations!): CaSe https://www.case-podcast.org/
Completely not at all about Clojure but great software podcasts:
Go Time: Even though I hardly ever write Go, I find their conversations to be really great and having lessons beyond Go. It helps that I am interested in the language though: https://changelog.com/gotime
Web Development and Development in general - The Bike Shed: https://www.bikeshed.fm/
Software Engineering Radio: https://www.se-radio.net/
CoRecursive: https://corecursive.com/
Inside Java: https://inside.java/
> If that were true then they wouldn't be heap allocations.
"Heap" is a misnomer. It's not called that due to the classic CS "heap" datastructure. It's called that for the same reason it's called a heap allocation in C++. Modern C++ allocators don't use a heap structure either.
How the JVM does allocations for all it's collectors is in fact a bump allocator in the heap space. There are some weedsy details (for example, threads in the JVM have their own heap space for doing allocation to avoid contention in allocation) but suffice it to say it ultimately translates into a region check then pointer bump. This is why the JVM is so fast at allocation, much faster than C++ can be. [1] [2]
> I don't know what this means.
JVM allocations are typically pointer bumps, adding a number to a register. There's really nothing faster than it. If you are implementing an arena then you've already lost in terms of performance.
[1] https://www.datadoghq.com/blog/understanding-java-gc/#memory-compaction
[2] https://inside.java/2020/06/25/compact-forwarding/