3

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.

1
  • My understanding ( which could be flawed ) is that there's no priority in terms of protected operations. So neither the volatile read, nor the external write can be re-ordered, so your 3 line example remains fixed. You can test it by sticking it in a method and calling it a few (hundred?)thousand times while using both -server and -XX:+PrintCompilation and compare the JIT results. Commented Sep 22, 2015 at 13:20

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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).

According to the JLS, observable behaviour doesn't require a total order of all external actions:

Note that a behavior B does not describe the order in which the external actions in B are observed, but other (internal) constraints on how the external actions are generated and performed may impose such constraints.

It seems that two external actions cannot be reordered if the result of the 1st external action is used as a parameter of the 2nd external action (either used directly, or indirectly — to compute the value of a parameter)
This is what the JLS says about the result of an external action:

An external action tuple contains an additional component, which contains the results of the external action as perceived by the thread performing the action. This may be information as to the success or failure of the action, and any values read by the action.

I suppose there could be strong ordering guarantees for external action which might access JVM's internal state — like jndi as explained in the Rafael's answer.

Other than that it seems like the JLS allows almost anything:

An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model.

This provides a great deal of freedom for the implementor to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization.

Of course, Java implementations can provide stronger guarantees. This would be legal because stronger guarantees don't produce new behaviours.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.