Details
-
Bug
-
Resolution: Fixed
-
P4
-
jfx13
-
b24
-
generic
-
generic
Description
ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows [Version 10.0.17134.1040]
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment AdoptOpenJDK (build 13+33)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 13+33, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
ControlAcceleratorSupport menu items listener is not cleared in removeAcceleratorsFromScene action, which causes memory leak while moving MenuBar with items to other scene. Removing is called in javafx.scene.control.skin.MenuButtonSkinBase#sceneChangeListener, but it does not handle the items' listener, so it just constantly adds new listeners on scene change, which grow up in memory.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open provided TwoStagesMenuBarLeakSample.
2. Keep pressing F11.
3. Observe the ControlAcceleratorSupport count in memory analyzing tools - jvisualvm or Eclipse MAT.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After 3. the ControlAcceleratorSupport count should be moreless the same as after 1.
ACTUAL -
lambda from ControlAcceleratorSupport count keeps growing up in the memory causing memory leak
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TwoStagesMenuBarLeakSample
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( TwoStagesMenuBarLeakSample.MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
final BorderPane borderPane = new BorderPane( new VBox( new Label( "sample" ) ) );
final Menu one = new Menu( "_One" );
one.getItems().add( new MenuItem( "Sample 1" ) );
one.getItems().add( new MenuItem( "Sample 2" ) );
one.getItems().add( new MenuItem( "Sample 3" ) );
one.getItems().add( new MenuItem( "Sample 4" ) );
final var menuBar = new MenuBar( one );
borderPane.setTop( menuBar );
borderPane.setCenter( new Label( "Press F11 to switch MenuBar to other window." ) );
Scene scene = new Scene( borderPane, 800, 600 );
primaryStage.setScene( scene );
primaryStage.show();
final var stage2 = new Stage( StageStyle.DECORATED );
final BorderPane stage2Container = new BorderPane();
stage2Container.setCenter( new Label( "Press F11 to switch MenuBar to other window." ) );
stage2.setScene( new Scene( stage2Container, 800, 600 ) );
primaryStage.addEventHandler( KeyEvent.KEY_PRESSED, aKeyEvent -> {
if( KeyCombination.keyCombination( "F11" ).match( aKeyEvent ) )
{
stage2Container.setTop( menuBar );
stage2.requestFocus();
}
} );
stage2.addEventHandler( KeyEvent.KEY_PRESSED, aKeyEvent -> {
if( KeyCombination.keyCombination( "F11" ).match( aKeyEvent ) )
{
borderPane.setTop( menuBar );
primaryStage.requestFocus();
}
} );
stage2.show();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Recreating menu bar on scene change.
FREQUENCY : always
Microsoft Windows [Version 10.0.17134.1040]
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment AdoptOpenJDK (build 13+33)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 13+33, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
ControlAcceleratorSupport menu items listener is not cleared in removeAcceleratorsFromScene action, which causes memory leak while moving MenuBar with items to other scene. Removing is called in javafx.scene.control.skin.MenuButtonSkinBase#sceneChangeListener, but it does not handle the items' listener, so it just constantly adds new listeners on scene change, which grow up in memory.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open provided TwoStagesMenuBarLeakSample.
2. Keep pressing F11.
3. Observe the ControlAcceleratorSupport count in memory analyzing tools - jvisualvm or Eclipse MAT.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After 3. the ControlAcceleratorSupport count should be moreless the same as after 1.
ACTUAL -
lambda from ControlAcceleratorSupport count keeps growing up in the memory causing memory leak
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TwoStagesMenuBarLeakSample
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( TwoStagesMenuBarLeakSample.MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
final BorderPane borderPane = new BorderPane( new VBox( new Label( "sample" ) ) );
final Menu one = new Menu( "_One" );
one.getItems().add( new MenuItem( "Sample 1" ) );
one.getItems().add( new MenuItem( "Sample 2" ) );
one.getItems().add( new MenuItem( "Sample 3" ) );
one.getItems().add( new MenuItem( "Sample 4" ) );
final var menuBar = new MenuBar( one );
borderPane.setTop( menuBar );
borderPane.setCenter( new Label( "Press F11 to switch MenuBar to other window." ) );
Scene scene = new Scene( borderPane, 800, 600 );
primaryStage.setScene( scene );
primaryStage.show();
final var stage2 = new Stage( StageStyle.DECORATED );
final BorderPane stage2Container = new BorderPane();
stage2Container.setCenter( new Label( "Press F11 to switch MenuBar to other window." ) );
stage2.setScene( new Scene( stage2Container, 800, 600 ) );
primaryStage.addEventHandler( KeyEvent.KEY_PRESSED, aKeyEvent -> {
if( KeyCombination.keyCombination( "F11" ).match( aKeyEvent ) )
{
stage2Container.setTop( menuBar );
stage2.requestFocus();
}
} );
stage2.addEventHandler( KeyEvent.KEY_PRESSED, aKeyEvent -> {
if( KeyCombination.keyCombination( "F11" ).match( aKeyEvent ) )
{
borderPane.setTop( menuBar );
primaryStage.requestFocus();
}
} );
stage2.show();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Recreating menu bar on scene change.
FREQUENCY : always
Attachments
Issue Links
- blocks
-
JDK-8241364 ☂ Cleanup skin implementations to allow switching
- Open
- relates to
-
JDK-8244075 Accelerator of ContextMenu's MenuItem is not removed when ContextMenu is removed from Scene
- Resolved