1) I have a native java function which passes several params and its implementation is a native C++ constructor to create an object and returns a long which is cast from the pointer to object. This object's constructed members are effectively immutable. The C++ object then can do work based on its constructed state.
2) java code that gets the result of the function call safely publishes the longified version of the pointer somewhere (without mutex) and changes a volatile variable to hopefully publish the memory changes in the native C++ object to other threads
Now another thread reads that volatile variable of 2), and then picks up that published long, and calls another native function that accesses that effectively immutable object in the C++ memory space to do some work.
Question: Is that other thread guaranteed to see the fully constructed native object because of the Java Memory Model guarantees about volatiles and fences? I would bet the answer is yes on some platforms, but I see that different chips work in different ways with using fences, and was wondering about all platforms for which java is available.
A co-author of JCIP answered the question on the JSR mailing list for concurrency.
He says: "JMM [makes no] guarantees extending to anything outside the Java heap - or more specifically it only applies to Java fields", but that "In practice the barriers/fences used today are coarse-grained and will affect all memory equally", so "that in practice this [the volatile publishing attempt described in the question] will work fine (as long as you are using normal process memory)".
Another respondent on the mailing list says: "Some of us have definitely considered it a goal to ensure that Java, C, and C++ synchronization works together as expected, with Java synchronization providing the right visibility guarantees for C or C++ variables, and conversely" but adds that "there is no written guarantee of that [behavior]".
What you pass from java code to native code is copied and passed in the appropriate datatypes for the native code (for example C++
has unsigned int
while Java
does not, null
terminated strings etc).
After that, any threading issues are related to the implementation of the native code.
Essentially it is the same an API. What are the contracts for the API? Does it specify that it can be accessed safely by multiple threads or not?
Java doesn't even know about the existence of the native object you created in your C code, so how can its memory model possibly provide any guarantees about it? All that Java knows about, and can guarantee the behavior of, is the volatile long.