Live data from Hacker News

Breaking java.lang.String

wouter.coekaerts.be

91–100 of 206 posts

Re: Breaking java.lang.String

#91
post #85

Earlier quoted context omitted.

Accepting an issue doesn't mean that there is a bug. > While the javadoc doesn't state it explicitly, immutable classes in the core library are expected to be thread safe. If it's not documented it's just an assumption.

Yes, but at some point one has come out of the theory domain and face the real world. So in practical terms it’s closer to a bug and even the “official” guys from Java accepted it as a bug.

Could you provide a link to the documentation to proof it's a bug?

The author could call it 'probably bug' or 'misleading String constructor documentation' but instead they state it's a bug without any proofs.

Re: Breaking java.lang.String

#92
post #75

Earlier quoted context omitted.

Author of the blog here. Yes, this is a bug. While the javadoc doesn't state it explicitly, immutable classes in the core library are expected to be thread safe. Java tries to be and mostly succeeds at being a safe language, where (by default) the guarantees of its internals cannot be broken no matter what user code does. The JVM preserves its own integrity. There are some other deliberate holes in that safety, such…

Dunno, this seems like you're violating the java memory model and then then fully expected weird shit happens. If you're mutating a shared state between threads without proper synchronization, and there is no way for String to do this on its own, the CPU is permitted to do stuff like out-of-order execution as there is no happens-before relationship between the write and the read. The JVM is further permitted to optim…

Something like a ConcurrentModificationException would be nice to have in the "weird shit happens" case, because you may not even be aware of it, and then it might cause headache much further down the line. If you could point upstream that would save a lot of headache and grey hair...

Re: Breaking java.lang.String

#93
post #92

Earlier quoted context omitted.

Dunno, this seems like you're violating the java memory model and then then fully expected weird shit happens. If you're mutating a shared state between threads without proper synchronization, and there is no way for String to do this on its own, the CPU is permitted to do stuff like out-of-order execution as there is no happens-before relationship between the write and the read. The JVM is further permitted to optim…

Something like a ConcurrentModificationException would be nice to have in the "weird shit happens" case, because you may not even be aware of it, and then it might cause headache much further down the line. If you could point upstream that would save a lot of headache and grey hair...

There's no way to reliably detect this type of concurrent modification that doesn't involve introducing expensive barrier operations that evict the CPU cache on multiple points along the code flow and choke out-of-order execution and limit what the JIT can do. If you do not have such a barrier, the CPU is permitted to assume the data hasn't been changed, and may cache it, making detection of concurrent modification impossible. The JIT will also optimize your code based on this assumption. Even if you go out of your way to check that the data is the same you may see stale data when you check!

It may run your code out of order, and even JIT-recompile it out of order, and your code that's like

  int oldValue = val;
  doSomething(val); 
  if (val != oldValue) throw new ConcurrentModificationException();
may be re-recompiled like this, since it looks like doSomething can't modify val or oldValue

  int oldValue = val;
  if (val != oldValue) throw new ConcurrentModificationException();

  doSomething(val);
and then since this if check is trivially always unnecessary, and nothing of consequence ever reads oldValue it may delete them entirely

  doSomething(val);
Introducing a barrier would likely make most Java programs 10x slower 'cause Java does a lot of throwaway string allocation on the assumption it's cheap and short-lived GC is virtually free.

The Java Memory Model is a great accomplishment and if you heed it you will write performant multi-threaded applications with an ease that is rare in other languages. If on the other hand you do not heed the JMM, you will at best get a CME alerting you of this case, but in most cases just get holes in your feet.

Re: Breaking java.lang.String

#94
post #91

Earlier quoted context omitted.

Yes, but at some point one has come out of the theory domain and face the real world. So in practical terms it’s closer to a bug and even the “official” guys from Java accepted it as a bug.

Could you provide a link to the documentation to proof it's a bug? The author could call it 'probably bug' or 'misleading String constructor documentation' but instead they state it's a bug without any proofs.

[deleted]

Re: Breaking java.lang.String

#95
post #75

Is this actually a bug? The default assumption in Java is that types are not thread-safe unless otherwise specified. Attempting to use types in a way that exceeds their documented thread safety has always been allowed to leave your program in an inconsistent state.

Author of the blog here. Yes, this is a bug. While the javadoc doesn't state it explicitly, immutable classes in the core library are expected to be thread safe. Java tries to be and mostly succeeds at being a safe language, where (by default) the guarantees of its internals cannot be broken no matter what user code does. The JVM preserves its own integrity. There are some other deliberate holes in that safety, such…

char[] is not an immutable class. Thread safety issue happens on that type, not the fault of String type.

It is weird Java considered it a bug, I expect it to be resolved as "wont do"

Re: Breaking java.lang.String

#96
post #75

Earlier quoted context omitted.

Author of the blog here. Yes, this is a bug. While the javadoc doesn't state it explicitly, immutable classes in the core library are expected to be thread safe. Java tries to be and mostly succeeds at being a safe language, where (by default) the guarantees of its internals cannot be broken no matter what user code does. The JVM preserves its own integrity. There are some other deliberate holes in that safety, such…

char[] is not an immutable class. Thread safety issue happens on that type, not the fault of String type. It is weird Java considered it a bug, I expect it to be resolved as "wont do"

Thread safety of char[] is the cause of the bug, but the effect is that String instances can violate their invariants, which they shouldn't even in case of thread-unsafe code.

Re: Breaking java.lang.String

#97

Is this actually a bug? The default assumption in Java is that types are not thread-safe unless otherwise specified. Attempting to use types in a way that exceeds their documented thread safety has always been allowed to leave your program in an inconsistent state.

It's a TOCTOU bug [1], a well known category of bugs. [1] https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use

Also one more argument for “parse don’t validate”. The code validates a mutable input, and assumes that validation holds thereafter. An incorrect assumption as it turns out.

Re: Breaking java.lang.String

#98
post #74

This is the exact kind of bug that Rust solves with its borrowing system. The problem is that Java has no way to express the concept of "something that nothing else can modify while I'm looking at it".

Arguably, C++ arguably already solved that specific problem with const safety. I was flabbergasted back in 1995 that Java had dropped that notion.

I don't think it does. In C++ taking a const argument just means that you can't change it. But since the caller can pass non-const as const there is nothing stopping them from mutating it.

Re: Breaking java.lang.String

#99
post #75

Is this actually a bug? The default assumption in Java is that types are not thread-safe unless otherwise specified. Attempting to use types in a way that exceeds their documented thread safety has always been allowed to leave your program in an inconsistent state.

Author of the blog here. Yes, this is a bug. While the javadoc doesn't state it explicitly, immutable classes in the core library are expected to be thread safe. Java tries to be and mostly succeeds at being a safe language, where (by default) the guarantees of its internals cannot be broken no matter what user code does. The JVM preserves its own integrity. There are some other deliberate holes in that safety, such…

In my opinion this is not a bug and there is no general fix for that without significant overhaul of the whole runtime and standard library.

In my opinion the author might need to read the vm and memory model spec and understand that such things are expected in Java.

There are real bugs in standard library singletons (e.g. concurrent Filesystem calls might fail during singleton initialization, while plugins are loaded). These bugs are being ignored for years.

The author must not expect any "fix" for this in foreseeable future, but they might expect being laughed at.

Re: Breaking java.lang.String

#100
post #83
post #81

Earlier quoted context omitted.

How would you fix this? Possibly by copying the input array to a local array as the first step? But then you might copy a lot of data, which is in 99% of the cases totally unnecessary. Have a separate threadsafe and a non-threadsafe constructor for char[]? EDIT: another idea is to do a hash of the input array, and compare between start and end. But that also requires an O(n) walk through the input...

/s redesign a language to prevent parallel mutable use of the array

This won't happen (unfortunately) for obvious reasons.
Post reply on HN