Question

I tried Javas Hotswap today, and its working quite nice. During my testing i stumbled upon a rather weird behaviour. This is my Code:

public class Test extends JFrame implements ActionListener{

private JButton c;
private int f =1;
/**
 * @param args
 */
public static void main(String[] args) {
    Test t = new Test();
}

public Test(){
    this.setPreferredSize(new Dimension(800, 600));
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    c = new JButton("Click");
    c.addActionListener(this);
    this.add(c);
    this.pack();
    this.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent e) {
    c.setText(String.valueOf(f++));

}

}

Note the line c.setText(String.valueOf(f++)); near the end. If i switch that to f-- while the program is running, i notice that on the first click on the button after the change, the value is still counting up. The Clicks after that however are counting correctly. The same occurs when changing it back.

The next thing i noticed is: if i change the code to this: c.setText(String.valueOf(f+=1));, run the JVM and Hotswap it to c.setText(String.valueOf(f-=1)); the change is directly applied, with no click-delay.

My question is now: What exactly causes this behaviour? And what are the differences between f++ and f+=1 on JVM Code Level?

Was it helpful?

Solution

Using javap on this code:

public static void main(String[] args) throws Exception {
    int i = 0;
    i++;
    System.out.println(i);
    i+=1;
    System.out.println(i);
}

returns

  0: iconst_0
  1: istore_1
  2: iinc          1, 1
  5: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
  8: iload_1
  9: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
 12: iinc          1, 1
 15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
 18: iload_1
 19: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
 22: return

==> no difference

OTHER TIPS

Have you turned off all optimizations? There are quite a few different tricks the JIT compiler can do behind the scenes dynamically so the resulting underlying code changes multiple times during execution.

Using actionPerformed() you are dealing with asyncronous events which can make following the execution path more difficult even without hotswap issues.

Do the same test code

c.setText(String.valueOf(f++)); 

but do it inside a big loop with a breakpoint set, that way you can test out the variations with fewer moving parts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top