7079260: InputContext leaks memory
Replaced strong refs with weak refs Reviewed-by: art, serb
This commit is contained in:
parent
f44592861c
commit
42b8720bef
@ -33,6 +33,7 @@ import java.awt.event.InputMethodListener;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextHitInfo;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.AttributedString;
|
||||
@ -55,7 +56,7 @@ class CompositionAreaHandler implements InputMethodListener,
|
||||
|
||||
private AttributedCharacterIterator composedText;
|
||||
private TextHitInfo caret = null;
|
||||
private Component clientComponent = null;
|
||||
private WeakReference<Component> clientComponent = new WeakReference<>(null);
|
||||
private InputMethodContext inputMethodContext;
|
||||
|
||||
/**
|
||||
@ -76,8 +77,9 @@ class CompositionAreaHandler implements InputMethodListener,
|
||||
}
|
||||
// If the client component is an active client using below-the-spot style, then
|
||||
// make the composition window undecorated without a title bar.
|
||||
if(clientComponent!=null){
|
||||
InputMethodRequests req = clientComponent.getInputMethodRequests();
|
||||
Component client = clientComponent.get();
|
||||
if(client != null){
|
||||
InputMethodRequests req = client.getInputMethodRequests();
|
||||
if (req != null && inputMethodContext.useBelowTheSpotInput()) {
|
||||
setCompositionAreaUndecorated(true);
|
||||
}
|
||||
@ -86,7 +88,7 @@ class CompositionAreaHandler implements InputMethodListener,
|
||||
}
|
||||
|
||||
void setClientComponent(Component clientComponent) {
|
||||
this.clientComponent = clientComponent;
|
||||
this.clientComponent = new WeakReference<>(clientComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,8 +258,9 @@ class CompositionAreaHandler implements InputMethodListener,
|
||||
* the composed text are forwarded to the client component.
|
||||
*/
|
||||
InputMethodRequests getClientInputMethodRequests() {
|
||||
if (clientComponent != null) {
|
||||
return clientComponent.getInputMethodRequests();
|
||||
Component client = clientComponent.get();
|
||||
if (client != null) {
|
||||
return client.getInputMethodRequests();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -57,6 +57,7 @@ import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
@ -104,7 +105,7 @@ public abstract class X11InputMethod extends InputMethodAdapter {
|
||||
|
||||
//reset the XIC if necessary
|
||||
private boolean needResetXIC = false;
|
||||
private Component needResetXICClient = null;
|
||||
private WeakReference<Component> needResetXICClient = new WeakReference<>(null);
|
||||
|
||||
// The use of compositionEnableSupported is to reduce unnecessary
|
||||
// native calls if set/isCompositionEnabled
|
||||
@ -272,14 +273,14 @@ public abstract class X11InputMethod extends InputMethodAdapter {
|
||||
called on the passive client when endComposition is called.
|
||||
*/
|
||||
if (needResetXIC && haveActiveClient() &&
|
||||
getClientComponent() != needResetXICClient){
|
||||
getClientComponent() != needResetXICClient.get()){
|
||||
resetXIC();
|
||||
|
||||
// needs to reset the last xic focussed component.
|
||||
lastXICFocussedComponent = null;
|
||||
isLastXICActive = false;
|
||||
|
||||
needResetXICClient = null;
|
||||
needResetXICClient.clear();
|
||||
needResetXIC = false;
|
||||
}
|
||||
}
|
||||
@ -417,7 +418,7 @@ public abstract class X11InputMethod extends InputMethodAdapter {
|
||||
isLastXICActive = false;
|
||||
|
||||
resetXIC();
|
||||
needResetXICClient = null;
|
||||
needResetXICClient.clear();
|
||||
needResetXIC = false;
|
||||
}
|
||||
}
|
||||
@ -478,7 +479,7 @@ public abstract class X11InputMethod extends InputMethodAdapter {
|
||||
disableInputMethod();
|
||||
if (needResetXIC) {
|
||||
resetXIC();
|
||||
needResetXICClient = null;
|
||||
needResetXICClient.clear();
|
||||
needResetXIC = false;
|
||||
}
|
||||
}
|
||||
@ -877,7 +878,7 @@ public abstract class X11InputMethod extends InputMethodAdapter {
|
||||
boolean active = haveActiveClient();
|
||||
if (active && composedText == null && committedText == null){
|
||||
needResetXIC = true;
|
||||
needResetXICClient = getClientComponent();
|
||||
needResetXICClient = new WeakReference<>(getClientComponent());
|
||||
return;
|
||||
}
|
||||
|
||||
|
112
jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java
Normal file
112
jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Robot;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import test.java.awt.regtesthelpers.Util;
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 7079260
|
||||
@summary XInputContext leaks memory by needRecetXXIClient field
|
||||
@author Petr Pchelko
|
||||
@library ../../regtesthelpers
|
||||
@build Util
|
||||
@compile InputContextMemoryLeakTest.java
|
||||
@run main/othervm -Xmx20M InputContextMemoryLeakTest
|
||||
*/
|
||||
public class InputContextMemoryLeakTest {
|
||||
|
||||
private static JFrame frame;
|
||||
private static WeakReference<JTextField> text;
|
||||
private static WeakReference<JPanel> p;
|
||||
private static JButton button;
|
||||
|
||||
public static void init() throws Throwable {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame = new JFrame();
|
||||
frame.setLayout(new FlowLayout());
|
||||
JPanel p1 = new JPanel();
|
||||
button = new JButton("Test");
|
||||
p1.add(button);
|
||||
frame.add(p1);
|
||||
text = new WeakReference<JTextField>(new JTextField("Text"));
|
||||
p = new WeakReference<JPanel>(new JPanel(new FlowLayout()));
|
||||
p.get().add(text.get());
|
||||
frame.add(p.get());
|
||||
frame.setBounds(500, 400, 200, 200);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
Util.focusComponent(text.get(), 500);
|
||||
Util.clickOnComp(button, new Robot());
|
||||
//References to objects testes for memory leak are stored in Util.
|
||||
//Need to clean them
|
||||
Util.cleanUp();
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frame.remove(p.get());
|
||||
}
|
||||
});
|
||||
|
||||
Util.waitForIdle(null);
|
||||
//After the next caret blink it automatically TextField references
|
||||
Thread.sleep(text.get().getCaret().getBlinkRate() * 2);
|
||||
Util.waitForIdle(null);
|
||||
assertGC();
|
||||
}
|
||||
|
||||
public static void assertGC() throws Throwable {
|
||||
List<byte[]> alloc = new ArrayList<byte[]>();
|
||||
int size = 1024 * 10;
|
||||
while (true) {
|
||||
try {
|
||||
alloc.add(new byte[size]);
|
||||
} catch (OutOfMemoryError err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
alloc = null;
|
||||
if (text.get() != null) {
|
||||
throw new Exception("Test failed: JTextField was not collected");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
init();
|
||||
}
|
||||
}
|
@ -463,6 +463,13 @@ public final class Util {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Cleans all the references
|
||||
public static void cleanUp() {
|
||||
apListener = null;
|
||||
fgListener = null;
|
||||
wgfListener = null;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Some stuff to test focus.
|
||||
|
Loading…
Reference in New Issue
Block a user