3 ms·
afaik the person you replied to is wrong, using System.arrayCopy would definitely make a copy and not be optimized away. Maybe poster meant only copying the re
by dtech 3y ago
afaik the person you replied to is wrong, using System.arrayCopy would definitely make a copy and not be optimized away.
Maybe poster meant only copying the reference with `char[] copy = original` which indeed does nothing, but that's not a defensive copy.
- deleted 3y ago[deleted]
- marginalia_nu 3y agoThis copy has no external observable effects (it's only temporarily used in the constructor and never stored anywhere), and since the JVM is (under the JMM) permitted work under the assumption the original array doesn't change unless the thread itself changes it or there is some happens-before relationship with something that does, and is permitted to re-order same-thread execution as-if-serial, it's fully permitted to assume the original array is identical to the copied array, and it may elide the copy, since the original array isn't stored or mutated in any way. Whether the JVM actually does this for arraycopy is an implementation detail. The JVM is permitted to perform this type of escape analysis and elision, and definitely does for some allocations. In general arrays and concurrency doesn't mix very well in Java, and is something I'd avoid mixing on principle. You avoid most of these types of problems by having threads talk by passing around immutable objects via concurrency primitives, volatile references, synchronized-blocks, etc.
- orra 3y ago> In general arrays and concurrency doesn't mix very well in Java, and is something I'd avoid mixing on principle. Sound sensible. I think what you've said is any semi-malicious code can give you a primitive array, then modify it from under you in another thread. That's not completely surprising but the clincher is, you can't even take a defensive copy.
- marginalia_nu 3y agoWell I mean there are things you can do prevent the JVM from this particular optimization. But you need to use the right tools to tell Java to expect spooky action at a distance, and arraycopy just isn't sufficient. This would probably do byte[] b; // A synchronized (a) { b = System.arraycopy(a); } // B Here A happens-before B, and you can assume a read fence at the start of synchronized block and a store fence at end of it, so consumers of b should get a consistent view of the array, and the synchronized block tells Java that you expect a to be modified by another thread so it can't assume it stays the same throughout the execution; and elision of the arraycopy isn't possible; so while the array may be in a weird state, it will at least stay consistent throughout the execution.
- guipsp 3y agoYou are incorrect - it is allowed to behave as if the original didn't or did change, that is true and in the memory model. But once the copy is done, then the state is settled, and is no longed allowed to change at any point. There are no more conflicting accesses. It is "fully permitted to assume the original array is identical to the copied array" only to the extent that affects reading from the original array, not the copy (ie, it can pretend that the original didn't change, even it did). Anything else would break causality requirements (JLS§17.4.8.).