<p dir="ltr">Interesting.  There's intrinsic code in library_ call.cpp for this method.  It looks like that code may be missing some flavor of MemBarNode that kills enregistering/hoisting of the interrupted field.  This should probably be sent to the compiler folks.</p>

<p dir="ltr">Sent from my phone</p>
<div class="gmail_quote">On Nov 7, 2012 5:14 PM, "Dr Heinz M. Kabutz" <<a href="mailto:heinz@javaspecialists.eu">heinz@javaspecialists.eu</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
During a hands-on session today of my new Concurrency Specialist Course, one of my students discovered what we think might be an interesting and potentially serious bug in the JVM.  It seems that the Server HotSpot in OpenJDK 7 may sometimes hoist the value of the _interrupted field.  This is interesting, since the value is not stored in Java, but rather in the OSThread.hpp file in the jint _interrupted field.  It is also pretty serious, because it means we cannot rely on the interrupted status in order to shut down threads.  This will affect Future.cancel(), ExecutorService.shutdownNow() and a whole bunch of other mechanisms that use interruptions to cooperatively cancel tasks.  (Obviously the exercise was more involved than the code presented in this email, after all the course is aimed at intermediate to advanced Java developers.  So please don't expect that this won't happen in your code - I've just taken away unnecessary code until we can see the bug without any of the paraphernalia that might distract.)<br>

<br>
First off, some code that works as expected.  As soon as you interrupt the thread, it breaks out of the while() loop and exits:<br>
<br>
   public void think() {<br>
       while (true) {<br>
           if (Thread.currentThread().<u></u>isInterrupted()) break;<br>
       }<br>
       System.out.println("We're done thinking");<br>
   }<br>
<br>
However, if you extract the "Thread.currentThread().<u></u>isInterrupted()" into a separate method, then that might be optimized by HotSpot to always return false and the code then never ends:<br>
<br>
   public void think() {<br>
       while (true) {<br>
           if (checkInterruptedStatus()) break;<br>
       }<br>
       System.out.println("We're done thinking");<br>
   }<br>
<br>
   private boolean checkInterruptedStatus() {<br>
       return Thread.currentThread().<u></u>isInterrupted();<br>
   }<br>
<br>
My assumption is that the checkInterruptedStatus() method is aggressively optimized and then the actual status is not read again.  This does not happen with the client hotspot and also not with Java 1.6.0_37.  It does happen with the 1.8 EA that I've got on my MacBook Pro.  The student was using a Windows machine, so this not just a Mac problem. <br>

Here is the complete code:<br>
<br>
public class InterruptedVisibilityTest {<br>
   public void think() {<br>
       while (true) {<br>
           if (checkInterruptedStatus()) break;<br>
       }<br>
       System.out.println("We're done thinking");<br>
   }<br>
<br>
   private boolean checkInterruptedStatus() {<br>
       return Thread.currentThread().<u></u>isInterrupted();<br>
   }<br>
<br>
   public static void main(String[] args) throws InterruptedException {<br>
       final InterruptedVisibilityTest test =<br>
               new InterruptedVisibilityTest();<br>
       Thread thinkerThread = new Thread("Thinker") {<br>
           public void run() {<br>
               test.think();<br>
           }<br>
       };<br>
       thinkerThread.start();<br>
       Thread.sleep(500);<br>
       thinkerThread.interrupt();<br>
       long timeOfInterruption = System.currentTimeMillis();<br>
       thinkerThread.join(500);<br>
       if (thinkerThread.isAlive()) {<br>
           System.err.println("Thinker did not shut down within 500ms");<br>
           System.err.println("Error in Java Virtual Machine!");<br>
           System.err.println("<u></u>Interrupted: " + thinkerThread.isInterrupted())<u></u>;<br>
           System.err.println();<br>
           System.err.println("(Let's see if the thread ever dies and how long it takes)");<br>
           while (thinkerThread.isAlive()) {<br>
               thinkerThread.join(1000);<br>
               if (thinkerThread.isAlive()) {<br>
                   System.err.println("  ... still waiting");<br>
               }<br>
           }<br>
       }<br>
       System.err.println("Finally, the thread has died - that took " +<br>
               (System.currentTimeMillis() - timeOfInterruption) + "ms");<br>
   }<br>
}<br>
<br>
As I said, the original code was more involved, but this demonstrates the essentials.  I hope some of you might be able to take a look at what's going on.<br>
<br>
Regards<br>
<br>
Heinz<br>
-- <br>
Dr Heinz M. Kabutz (PhD CompSci)<br>
Author of "The Java(tm) Specialists' Newsletter"<br>
Sun Java Champion<br>
IEEE Certified Software Development Professional<br>
<a href="http://www.javaspecialists.eu" target="_blank">http://www.javaspecialists.eu</a><br>
Tel: <a href="tel:%2B30%2069%2075%20595%20262" value="+306975595262" target="_blank">+30 69 75 595 262</a><br>
Skype: kabutz<br>
<br>
<br>
______________________________<u></u>_________________<br>
Concurrency-interest mailing list<br>
<a href="mailto:Concurrency-interest@cs.oswego.edu" target="_blank">Concurrency-interest@cs.<u></u>oswego.edu</a><br>
<a href="http://cs.oswego.edu/mailman/listinfo/concurrency-interest" target="_blank">http://cs.oswego.edu/mailman/<u></u>listinfo/concurrency-interest</a><br>
</blockquote></div>