Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8116176

Memory leak on Windows screen lock

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Duplicate
    • Affects Version/s: 7u21
    • Fix Version/s: 8
    • Component/s: javafx
    • Labels:

      Description

      The attached sample program produces a memory leak when the screen lock is active on windows.


      package com.thalesgroup.de.gsr.test.testplugin.javafx.regionimage;

      import java.nio.ByteBuffer;
      import java.util.LinkedList;
      import java.util.List;

      import javafx.embed.swt.FXCanvas;
      import javafx.geometry.Rectangle2D;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.canvas.Canvas;
      import javafx.scene.canvas.GraphicsContext;
      import javafx.scene.image.PixelFormat;
      import javafx.scene.image.PixelWriter;
      import javafx.scene.paint.Color;

      import org.apache.log4j.BasicConfigurator;
      import org.apache.log4j.Logger;
      import org.eclipse.swt.SWT;
      import org.eclipse.swt.layout.FillLayout;
      import org.eclipse.swt.widgets.Composite;
      import org.eclipse.swt.widgets.Display;
      import org.eclipse.swt.widgets.Shell;

      /**
       * @author Jochen Mönch
       */
      public class StandaloneTestJavaFX {

          private static final Logger log = Logger.getLogger( StandaloneTestJavaFX.class );
          private static final int WIDTH = 1280;
          private static final int HEIGHT = 1000;
          private FXCanvas fxCanvas;
          public Color color = Color.rgb( 255, 0, 0 );
          private Canvas canvas;
          private PixelFormat<ByteBuffer> pixelFormat;
          private byte[] imageData;
          private int cycles = 0;
          private long lastCycleRateLog = System.currentTimeMillis();
          private int overallCycles = 0;
          private final byte blueByte;
          private final byte greenByte;
          private final byte redByte;
          private final byte alphaByte;
          private long lastUpdate = System.currentTimeMillis();
          private long lastAdd = System.currentTimeMillis();
          private final List<Rectangle2D> pendingRectangles = new LinkedList<Rectangle2D>();
          private boolean changed = false;
          private boolean stop = false;
          private Shell shell;

          public static void main(final String[] args) {

              BasicConfigurator.configure();
              StandaloneTestJavaFX test = new StandaloneTestJavaFX();
              test.run();
          }

          /**
           * Constructor. Opens Gui.
           *
           * @param parent
           */
          public StandaloneTestJavaFX() {

              createShell();
              createGUI( shell );
              createImageData();
              blueByte = (byte) (Math.round( color.getBlue() * 255 ) & 0xff);
              greenByte = (byte) (Math.round( color.getGreen() * 255 ) & 0xff);
              redByte = (byte) (Math.round( color.getRed() * 255 ) & 0xff);
              alphaByte = (byte) 0xff;
          }

          public void run() {

              shell.open();

              new Thread( new Runnable() {

                  @Override
                  public void run() {

                      while( !stop ) {
                          doWork();
                      }
                  }
              }, "FXPainter" ).start();
              while( !shell.isDisposed() ) {
                  if( !shell.getDisplay().readAndDispatch() ) {
                      shell.getDisplay().sleep();
                  }
              }
          }

          private void createShell() {

              shell = new Shell( Display.getDefault() );
              shell.setSize( WIDTH, HEIGHT );
              shell.setLayout( new FillLayout() );
          }

          private void createGUI(final Composite parent) {

              fxCanvas = new FXCanvas( parent, SWT.NONE );
              Group rootGroup = new Group();
              rootGroup.setCache( false );
              Scene scene = new Scene( rootGroup, Color.TRANSPARENT );
              fxCanvas.setScene( scene );
              canvas = createCanvas();
              rootGroup.getChildren().add( canvas );
          }

          private void createImageData() {

              imageData = new byte[WIDTH * 4 * HEIGHT];
              pixelFormat = PixelFormat.getByteBgraInstance();
              for( int y = 0; y < HEIGHT; y++ ) {
                  for( int x = 0; x < WIDTH; x++ ) {
                      int startIdx = getStartIndex( y, x );
                      imageData[startIdx] = 0x0;
                      imageData[startIdx + 1] = 0x0;
                      imageData[startIdx + 2] = 0x0;
                      imageData[startIdx + 3] = 0x0;
                  }
              }
          }

          private Canvas createCanvas() {

              Canvas canvas = new Canvas();
              canvas.setCache( true );
              canvas.setWidth( WIDTH );
              canvas.setHeight( HEIGHT );
              canvas.setVisible( true );
              return canvas;
          }

          private void doWork() {

              final long now = System.currentTimeMillis();
              if( now - lastAdd >= 1 ) {
                  addNewData( 1000 );
                  lastAdd = now;
              }
              if( now - lastUpdate >= 50 ) {
                  updateContent( (int) Math.round( 255.0 / 30.0 ) );
                  lastUpdate = now;
              }

              if( !fxCanvas.isDisposed() ) {
                  if( now - lastCycleRateLog > 1000 ) {
                      double timeSpend = (now - lastCycleRateLog) / 1000.0;
                      double cycleRate = cycles / timeSpend;
                      log.info( "CycleRate: " + cycleRate + ", total cycles: " + cycles );
                      lastCycleRateLog = now;
                      cycles = 0;
                  }
                  paintContent( overallCycles );
                  cycles++;
                  overallCycles++;
              } else {
                  stopWork();
              }
          }

          private void stopWork() {

              stop = true;
          }

          private void addNewData(final int numRects) {

              synchronized( imageData ) {
                  for( int i = 0; i < numRects; i++ ) {
                      int x = (int) Math.round( Math.random() * (WIDTH - 5) );
                      int y = (int) Math.round( Math.random() * (HEIGHT - 5) );
                      pendingRectangles.add( new Rectangle2D( x, y, 5, 5 ) );
                  }
              }
          }

          private void updateContent(final int decreaseAlphaBy) {

              synchronized( imageData ) {
                  adjustAlpha( imageData, decreaseAlphaBy );
                  for( Rectangle2D rectangle : pendingRectangles ) {
                      fillRect( imageData, color, (int) Math.round( rectangle.getMinX() ),
                              (int) Math.round( rectangle.getMinY() ), (int) Math.round( rectangle.getWidth() ),
                              (int) Math.round( rectangle.getHeight() ) );
                  }
                  pendingRectangles.clear();
                  changed = true;
              }
          }

          private void paintContent(final int cycle) {

              synchronized( imageData ) {
                  if( changed ) {
                      GraphicsContext gc = canvas.getGraphicsContext2D();
                      PixelWriter pixelWriter = gc.getPixelWriter();
                      pixelWriter.setPixels( 0, 0, WIDTH, HEIGHT, pixelFormat, imageData, 0, WIDTH * 4 );
                      changed = false;
                  }
              }
          }

          private void adjustAlpha(final byte[] imageData, final int decreaseBy) {

              for( int i = 0; i < imageData.length; i += 4 ) {
                  imageData[i + 3] = (byte) Math.max( (imageData[i + 3] & 0xff) - decreaseBy, 0x0 );
              }
          }

          private void fillRect(final byte[] imageData, final Color color, final int startX, final int startY,
                  final int width, final int height) {

              for( int y = startY; y < startY + height; y++ ) {
                  for( int x = startX; x < startX + width; x++ ) {
                      int index = getStartIndex( y, x );
                      imageData[index] = blueByte;
                      imageData[index + 1] = greenByte;
                      imageData[index + 2] = redByte;
                      imageData[index + 3] = alphaByte;
                  }
              }
          }

          private int getStartIndex(final int row, final int column) {

              return row * WIDTH * 4 + column * 4;
          }
      }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                kcr Kevin Rushforth
                Reporter:
                duke J. Duke (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported: