Posted by philonoist 12 hours ago
I really hope they give an escape hatch for this. It will make it really hard to extract a lot of the benefit of valhala if you can't make a thread unsafe value class. It's also one of those problems that will be quite hard to run into. You basically need something like this
class Bar {
static Foo value[] = new Foo[10];
static void setFooFromManyThreads(Foo foo) {
value[0] = foo;
}
value record Foo(int x, int y, int z) {};
}
Not something you typically run into and generally already a thread safety problem.The solution is also simple, a `synchronized{}` block will fix it if you need to have a tearable class that's written from multiple threads.
But the other thing is that for SIMD operations, you really need flattening, and that really does typically mean having something like `Foo(double x, double y, double z)` in play. It'd be a shame if the way we have to do this is a struct of arrays.
If I have a function that has a value `x` that erases to `java.lang.Object` (e.g. a parametric function with no lower bound); then it used to be safe to check for nullity and then synchronize on the object.
This is no longer safe: This can now throw `IdentityException` into your face. (it was _never_ a good idea)
In other words, a lot of old code must be reviewed.
I suspect that `-XX:DiagnoseSyncOnValueBasedClasses=2` will need to stay (with the semantics: if user tries to synchronize on identity-less object, then log a JFR event and make it a NOP, don't throw an exception)!
The current JEP text is a little too ambiguous to figure out whether that is the plan, anyways.
I don’t know if this is fair way to try to disarm your critics. The only thing that’s remained after this decade is the slogan so it’s a real ship of Theseus question if Valhalla has shipped since what’s delivered doesn’t achieve it. Congrats on the accomplishment, but from looking at what ended up, I’m not sure it’s a huge improvement.
> The trouble is that this optimization is unpredictable and fragile.
Is this describing escape analysis or value classes? Because the list of exclusions where this does anything is so large and the conversion to a heap type under the hood is so transparent and opaque, I think it can describe this technique as well.
Also, the whole “works like an int” motto is violated - int is never null, int-> integer boxing is explicit and well understood.
> In the new model, the wrapper classes themselves become value classes (when preview is on, Integer, Long, Double, and company lose their identity
Oh neat, they sidestep that by changing the definition of an int. I’m sure it’ll be trivial to turn this on in the wild on code that may be relying on identity for boxed numerics. I think this alone shows this project can’t ever be turned on by default and now we’ll have a decade of two Java languages (one with value types and one without) as they try to convince everyone to migrate and then just turn it on (ie python3).
So much opportunity squandered and dismissing critics as always having something to complain about is a neat way to sidestep legitimate criticism that this approach is not going to work out for Java.
Not sure if it covers exactly the same terrain, but perusing the article, it seems to be the case, with a single instance being the degenerate case.
I've made something like this in the past. And I did it exactly because `List<Foo>` was too expensive and slow.
class FooSOA extends Collection<Foo> {
double x[];
double y[];
double z[];
Foo get(int index) { return new Foo(index); }
record Foo(int index) {
double x() { return FooSOA.this.x[i]; }
double y() { return FooSOA.this.y[i]; }
double z() { return FooSOA.this.z[i]; }
}
}Since when? I’m pretty sure structs didn’t have identity last time I used C#, and that would be a very surprising thing to add.
If you want to change an element of such an array you need to create a new immutable struct which in practice it is quite fast, but a bit verbose to write.
Java is generally backwards compatible, so unless you're using fat frameworks that use shady internals or known-deprecated APIs, you should generally be fine immediately upgrading to the latest LTS, possibly even non-LTS versions if you have confidence in your stack.
Mostly just hit the LTSes is what we've been doing and since about 17 it's been a pretty easy process in general.
Protip: If you ditch lombok everything gets a lot easier.