3

For the life of me, I cannot figure out why this program does not work in Java 7. I've run it with no problems in using Java 6, but as soon as I run it with Java 7, it doesn't work.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class HelloWorld implements ActionListener {

JButton button;
boolean state;

public HelloWorld(){
    init();
    state = false;
    System.out.println("state - "+state);

    while (true){
        if (state == true){
            System.out.println("Success");
        }
    }
}

private void init(){
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    button = new JButton("Button");
    button.addActionListener(this);
    frame.add(button);
    frame.pack();
    frame.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent e) {
    JButton source = (JButton)e.getSource();

    if (source == button){
        state = !state;
        System.out.println("state - "+state);
    }
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    new HelloWorld();
}

}

Using Java 6, if I press the button, it will print out the phrase "Success" until I hit the button again. Using Java 7 registers that the button was pressed and the value of state was changed to true, but the phrase "Success" is never printed. What's going on?

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
user1630640
  • 33
  • 1
  • 1
  • 4

2 Answers2

4

Add volatile to the field declaration.

Without volatile, changes in the field are not guaranteed to be visible on other threads.
In particular, the JITter is free to believe that the field never changes on the main thread, allowing it to remove the if entirely.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    Thank you so much! That was it. Is this a new feature of Java 7? I have to admit my knowledge of Java is entirely self-taught so I can be ignorant of a great number of things, but I've never seen that term before. – user1630640 Oct 10 '12 at 01:21
  • @user1630640: No; it's probably a change in the JITter. If you want to do multi-threaded development, I recommend reading Java Concurrency in Practice. If not you should stick to the Swing worker thread. Multi-threading is _hard_. – SLaks Oct 10 '12 at 01:26
0

When you show the JFrame

 frame.setVisible(true); 

The Java Show the window and stop the execution on this line.

You configured the window to exit on close:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

This program will terminate after you close the window.

So the code after the init() call will never be executed.

thiago.lenz
  • 399
  • 4
  • 11
  • He already did that in `init()`. Also, `setVisible()` will _never_ stop execution. That line just prevents the JVM from terminating when the main thread stops. He actually _doesn't_ need it at all. – SLaks Oct 10 '12 at 01:32
  • That would be true if I closed the window, but I don't have to. After the frame is initialized and the button added, which happens in the init() method, the next thing to be processed is the while loop (so long as I don't close the window). Basically the while loop perpetually runs while the JFrame is open. My problem was that the if statement was not working in the while loop. – user1630640 Oct 10 '12 at 01:35