I'm observing some weird behavior with Java 8 (several versions, in particular 1.8.0_111) when running a Swing app in a VM. The VM is a Windows 10 machine running in VMware that I am remote-desktoping into. I have not tried to do this with an actual desktop, rather than a VM, but am planning to ASAP to potentially remove an extra failure point.
I've managed to reproduce it with this minimal program:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
for (int i = 0; i < 3; i++) {
JPanel subpanel = new JPanel();
JComboBox<?> box = new JComboBox<>();
subpanel.add(box);
panel.add(subpanel);
}
frame.add(panel);
frame.pack();
frame.setVisible(true);
Timer timer = new Timer(1000, e -> {
frame.repaint();
});
timer.setRepeats(true);
timer.start();
});
}
Now if I just start it normally, it repaints, no problems at all, just a frame with 3 empty combo boxes, as expected. The problem appears if I minimize the RDP session window. If that happens (and the frame was not iconified), then Swing starts eating up unhealthy amounts of CPU until I open the RDP window again.
I have tried minimizing the code example further, however reducing the combo-box count to 2, removing the subpanel
or setting a single-fire timer (rather than repeating, even if the repaint would happen while the RDP is minimized) all prevented the bug from happening.
Here's the CPU utilization graph:
http://i67.tinypic.com/23rwglx.png
I've tried profiling the application during these spikes to try and see what the hell is happening. Here's the result from the profiler in JVisualVM:
http://i68.tinypic.com/apdwed.png
And the sampler (after removing the package filter):
http://i67.tinypic.com/2071735.png
I couldn't readily see what could be eating up the CPU in ProcessingRunnable
. Does anyone have any experience with what Swing does when it suddenly has no screen to draw onto?
subpanel
or reducing the count to 2 or making the timer non-repeating all prevent the issue. – HardwareTimer
nature, and looks like documentation says im right, quote the action event handlers for Timers execute on another thread -- the event-dispatching thread from docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html, so it on EDT anyway. – McdevittTimer
does fire the event on the EDT, you are right, but trashgod was correct, in that Swing components should all be constructed on the EDT, regardless of where they are used later. However, it's a non-issue, since the problem persists when the entire thing happens on the EDT as well. – Hardware