I'm currently learning about the Java Memory Model, and how it affects the reorderings that a compiler may make. However, I'm a bit confused about external operations. The JMM defines them as an action that may be observable outside of on operation. Going off of this question, I understand external actions to be things like printing a value, writing to a file, network operations, etc.
Now, how are external actions affected by reordering? I think it's obvious that an external action cannot be reordered with another external action, as this will change the observable behaviour of the program (and thus is not a valid transformation according to the JMM). But what about reordering an external action with a normal memory access, or a synchronisation action? For example:
volatile int v = 5;
int x = v;
System.out.println("!");
Can the print and int x = v
be reordered here? I can't see it changing behaviour, but the read of volatile v is the same as a monitor acquire, so I don't think the reordering is valid.
External actions are added to avoid surprising outcomes:
class ExternalAction {
int foo = 0;
void method() {
jni();
foo = 42;
}
native void jni(); /* {
assert foo == 0;
} */
}
Assuming that the JNI method was implemented to run the same assertion, you would not expect this to fail. The JIT compiler cannot determine the outcome of anything external such that the JMM forbidds such reorderings, too.