8376232: Remove AppContext from Swing synth related classes

Reviewed-by: serb, azvegint
This commit is contained in:
Phil Race 2026-01-26 18:53:39 +00:00
parent 3220c4cb43
commit c69275ddfe
8 changed files with 30 additions and 307 deletions

View File

@ -32,7 +32,6 @@ import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.synth.*;
import sun.awt.AppContext;
import sun.awt.UNIXToolkit;
import sun.swing.SwingUtilities2;
import javax.swing.plaf.synth.SynthIcon;
@ -961,11 +960,11 @@ class GTKStyle extends SynthStyle implements GTKConstants {
static class GTKStockIconInfo {
private static Map<String,Integer> ICON_TYPE_MAP;
private static final Object ICON_SIZE_KEY = new StringBuffer("IconSize");
private static Dimension[] iconSizesMap;
private static Dimension[] getIconSizesMap() {
AppContext appContext = AppContext.getAppContext();
Dimension[] iconSizes = (Dimension[])appContext.get(ICON_SIZE_KEY);
Dimension[] iconSizes = iconSizesMap;
if (iconSizes == null) {
iconSizes = new Dimension[7];
@ -976,7 +975,7 @@ class GTKStyle extends SynthStyle implements GTKConstants {
iconSizes[4] = new Dimension(20, 20); // GTK_ICON_SIZE_BUTTON
iconSizes[5] = new Dimension(32, 32); // GTK_ICON_SIZE_DND
iconSizes[6] = new Dimension(48, 48); // GTK_ICON_SIZE_DIALOG
appContext.put(ICON_SIZE_KEY, iconSizes);
iconSizesMap = iconSizes;
}
return iconSizes;
}

View File

@ -24,8 +24,6 @@
*/
package javax.swing.plaf.nimbus;
import sun.awt.AppContext;
import java.awt.image.BufferedImage;
import java.lang.ref.SoftReference;
@ -81,13 +79,10 @@ abstract class Effect {
// =================================================================================================================
// Static data cache
private static final ArrayCache ARRAY_CACHE = new ArrayCache();
protected static ArrayCache getArrayCache() {
ArrayCache cache = (ArrayCache)AppContext.getAppContext().get(ArrayCache.class);
if (cache == null){
cache = new ArrayCache();
AppContext.getAppContext().put(ArrayCache.class,cache);
}
return cache;
return ARRAY_CACHE;
}
protected static class ArrayCache {

View File

@ -28,7 +28,6 @@ import java.awt.*;
import java.lang.ref.WeakReference;
import java.net.*;
import javax.swing.*;
import sun.awt.AppContext;
import sun.swing.plaf.synth.Paint9Painter;
/**
@ -41,8 +40,6 @@ import sun.swing.plaf.synth.Paint9Painter;
* @author Scott Violet
*/
class ImagePainter extends SynthPainter {
private static final StringBuffer CACHE_KEY =
new StringBuffer("SynthCacheKey");
private Image image;
private Insets sInsets;
@ -53,22 +50,17 @@ class ImagePainter extends SynthPainter {
private Paint9Painter imageCache;
private boolean center;
private static volatile WeakReference<Paint9Painter> cacheRef;
private static Paint9Painter getPaint9Painter() {
// A SynthPainter is created per <imagePainter>. We want the
// cache to be shared by all, and we don't use a static because we
// don't want it to persist between look and feels. For that reason
// we use a AppContext specific Paint9Painter. It's backed via
// cache to be shared by all. It's held via
// a WeakRef so that it can go away if the look and feel changes.
synchronized(CACHE_KEY) {
@SuppressWarnings("unchecked")
WeakReference<Paint9Painter> cacheRef =
(WeakReference<Paint9Painter>)AppContext.getAppContext().
get(CACHE_KEY);
synchronized(ImagePainter.class) {
Paint9Painter painter;
if (cacheRef == null || (painter = cacheRef.get()) == null) {
painter = new Paint9Painter(30);
cacheRef = new WeakReference<Paint9Painter>(painter);
AppContext.getAppContext().put(CACHE_KEY, cacheRef);
}
return painter;
}

View File

@ -24,8 +24,6 @@
*/
package javax.swing.plaf.synth;
import sun.awt.AppContext;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@ -72,8 +70,6 @@ import javax.swing.UIDefaults;
* @author Scott Violet
*/
public class Region {
private static final Object UI_TO_REGION_MAP_KEY = new Object();
private static final Object LOWER_CASE_NAME_MAP_KEY = new Object();
/**
* ArrowButton's are special types of buttons that also render a
@ -425,10 +421,10 @@ public class Region {
*/
public static final Region VIEWPORT = new Region("Viewport", false);
private static Map<String, Region> getUItoRegionMap() {
AppContext context = AppContext.getAppContext();
@SuppressWarnings("unchecked")
Map<String, Region> map = (Map<String, Region>) context.get(UI_TO_REGION_MAP_KEY);
private static Map<String, Region> regionMap;
private static synchronized Map<String, Region> getUItoRegionMap() {
Map<String, Region> map = regionMap;
if (map == null) {
map = new HashMap<String, Region>();
map.put("ArrowButtonUI", ARROW_BUTTON);
@ -476,18 +472,18 @@ public class Region {
map.put("ToolBarSeparatorUI", TOOL_BAR_SEPARATOR);
map.put("TreeUI", TREE);
map.put("ViewportUI", VIEWPORT);
context.put(UI_TO_REGION_MAP_KEY, map);
regionMap = map;
}
return map;
}
private static Map<Region, String> getLowerCaseNameMap() {
AppContext context = AppContext.getAppContext();
@SuppressWarnings("unchecked")
Map<Region, String> map = (Map<Region, String>) context.get(LOWER_CASE_NAME_MAP_KEY);
private static Map<Region, String> lcRegionMap;
private static synchronized Map<Region, String> getLowerCaseNameMap() {
Map<Region, String> map = lcRegionMap;
if (map == null) {
map = new HashMap<Region, String>();
context.put(LOWER_CASE_NAME_MAP_KEY, map);
lcRegionMap = map;
}
return map;
}

View File

@ -25,8 +25,6 @@
package javax.swing.plaf.synth;
import sun.awt.AppContext;
import javax.swing.*;
import java.awt.*;
import java.beans.*;

View File

@ -60,7 +60,6 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.swing.DefaultLookup;
import sun.swing.SwingAccessor;
@ -101,31 +100,13 @@ public class SynthLookAndFeel extends BasicLookAndFeel {
static final Insets EMPTY_UIRESOURCE_INSETS = new InsetsUIResource(
0, 0, 0, 0);
/**
* AppContext key to get the current SynthStyleFactory.
*/
private static final Object STYLE_FACTORY_KEY =
new StringBuffer("com.sun.java.swing.plaf.gtk.StyleCache");
private static ComponentUI selectedUI;
private static int selectedUIStateValue;
/**
* AppContext key to get selectedUI.
*/
private static final Object SELECTED_UI_KEY = new StringBuilder("selectedUI");
/**
* AppContext key to get selectedUIState.
*/
private static final Object SELECTED_UI_STATE_KEY = new StringBuilder("selectedUIState");
/**
* The last SynthStyleFactory that was asked for from AppContext
* <code>lastContext</code>.
* The last SynthStyleFactory that was set.
*/
private static SynthStyleFactory lastFactory;
/**
* AppContext lastLAF came from.
*/
private static AppContext lastContext;
/**
* SynthStyleFactory for the this SynthLookAndFeel.
@ -141,7 +122,7 @@ public class SynthLookAndFeel extends BasicLookAndFeel {
private Handler _handler;
static ComponentUI getSelectedUI() {
return (ComponentUI) AppContext.getAppContext().get(SELECTED_UI_KEY);
return selectedUI;
}
/**
@ -182,23 +163,20 @@ public class SynthLookAndFeel extends BasicLookAndFeel {
}
}
AppContext context = AppContext.getAppContext();
context.put(SELECTED_UI_KEY, uix);
context.put(SELECTED_UI_STATE_KEY, Integer.valueOf(selectedUIState));
selectedUI = uix;
selectedUIStateValue = selectedUIState;
}
static int getSelectedUIState() {
Integer result = (Integer) AppContext.getAppContext().get(SELECTED_UI_STATE_KEY);
return result == null ? 0 : result.intValue();
return selectedUIStateValue;
}
/**
* Clears out the selected UI that was last set in setSelectedUI.
*/
static void resetSelectedUI() {
AppContext.getAppContext().remove(SELECTED_UI_KEY);
selectedUI = null;
selectedUIStateValue = 0;
}
@ -210,12 +188,8 @@ public class SynthLookAndFeel extends BasicLookAndFeel {
*/
public static void setStyleFactory(SynthStyleFactory cache) {
// We assume the setter is called BEFORE the getter has been invoked
// for a particular AppContext.
synchronized(SynthLookAndFeel.class) {
AppContext context = AppContext.getAppContext();
lastFactory = cache;
lastContext = context;
context.put(STYLE_FACTORY_KEY, cache);
}
}
@ -226,13 +200,6 @@ public class SynthLookAndFeel extends BasicLookAndFeel {
*/
public static SynthStyleFactory getStyleFactory() {
synchronized(SynthLookAndFeel.class) {
AppContext context = AppContext.getAppContext();
if (lastContext == context) {
return lastFactory;
}
lastContext = context;
lastFactory = (SynthStyleFactory) context.get(STYLE_FACTORY_KEY);
return lastFactory;
}
}

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) 2012, 2015, 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.
*/
/*
* @test
* @bug 7143614
* @summary Issues with Synth Look&Feel
* @author Pavel Porvatov
* @modules java.desktop/javax.swing.plaf.synth:open
* @modules java.desktop/sun.awt
*/
import sun.awt.SunToolkit;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthLookAndFeel;
import java.lang.reflect.Method;
public class bug7143614 {
private static Method setSelectedUIMethod;
private static ComponentUI componentUI = new BasicButtonUI();
public static void main(String[] args) throws Exception {
setSelectedUIMethod = SynthLookAndFeel.class.getDeclaredMethod("setSelectedUI", ComponentUI.class,
boolean.class, boolean.class, boolean.class, boolean.class);
setSelectedUIMethod.setAccessible(true);
setSelectedUIMethod.invoke(null, componentUI, true, true, true, true);
validate();
Thread thread = new ThreadInAnotherAppContext();
thread.start();
thread.join();
validate();
System.out.println("Test bug7143614 passed.");
}
private static void validate() throws Exception {
Method getSelectedUIMethod = SynthLookAndFeel.class.getDeclaredMethod("getSelectedUI");
getSelectedUIMethod.setAccessible(true);
Method getSelectedUIStateMethod = SynthLookAndFeel.class.getDeclaredMethod("getSelectedUIState");
getSelectedUIStateMethod.setAccessible(true);
if (getSelectedUIMethod.invoke(null) != componentUI) {
throw new RuntimeException("getSelectedUI returns invalid value");
}
if (((Integer) getSelectedUIStateMethod.invoke(null)).intValue() !=
(SynthConstants.SELECTED | SynthConstants.FOCUSED)) {
throw new RuntimeException("getSelectedUIState returns invalid value");
}
}
private static class ThreadInAnotherAppContext extends Thread {
public ThreadInAnotherAppContext() {
super(new ThreadGroup("7143614"), "ThreadInAnotherAppContext");
}
public void run() {
SunToolkit.createNewAppContext();
try {
setSelectedUIMethod.invoke(null, null, false, false, false, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2009, 2016, 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.
*/
/*
* @test
* @key headful
* @bug 6660049 6849518
* @summary Tests the Region initialization
* @author Sergey Malenkov
* @modules java.desktop/sun.awt
*/
import sun.awt.SunToolkit;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthLookAndFeel;
public class Test6660049 implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Test6660049(
javax.swing.JButton.class,
javax.swing.JCheckBox.class,
javax.swing.JCheckBoxMenuItem.class,
javax.swing.JColorChooser.class,
javax.swing.JComboBox.class,
javax.swing.JDesktopPane.class,
javax.swing.JEditorPane.class,
javax.swing.JFileChooser.class,
javax.swing.JFormattedTextField.class,
javax.swing.JInternalFrame.class,
javax.swing.JLabel.class,
javax.swing.JList.class,
javax.swing.JMenu.class,
javax.swing.JMenuBar.class,
javax.swing.JMenuItem.class,
javax.swing.JOptionPane.class,
javax.swing.JPanel.class,
javax.swing.JPasswordField.class,
javax.swing.JPopupMenu.class,
javax.swing.JProgressBar.class,
javax.swing.JRadioButton.class,
javax.swing.JRadioButtonMenuItem.class,
javax.swing.JRootPane.class,
javax.swing.JScrollBar.class,
javax.swing.JScrollPane.class,
javax.swing.JSeparator.class,
javax.swing.JSlider.class,
javax.swing.JSpinner.class,
javax.swing.JSplitPane.class,
javax.swing.JTabbedPane.class,
javax.swing.JTable.class,
javax.swing.JTextArea.class,
javax.swing.JTextField.class,
javax.swing.JTextPane.class,
javax.swing.JToggleButton.class,
javax.swing.JToolBar.class,
javax.swing.JToolTip.class,
javax.swing.JTree.class,
javax.swing.JViewport.class,
javax.swing.table.JTableHeader.class));
}
private final Class<? extends JComponent>[] types;
private final Region region;
private Test6660049(Class<? extends JComponent>... types) {
this.types = types;
run();
this.region = new Region("Button", "ButtonUI", true) {
@Override
public String getName() {
throw new Error("6660049: exploit is available");
}
};
}
public void run() {
if (this.region != null) {
SunToolkit.createNewAppContext();
}
for (Class<? extends JComponent> type : this.types) {
Region region = getRegion(type);
if (region == null) {
throw new Error("6849518: region is not initialized");
}
}
getRegion(JButton.class).getName();
}
private static Region getRegion(Class<? extends JComponent> type) {
try {
return SynthLookAndFeel.getRegion(type.newInstance());
}
catch (IllegalAccessException exception) {
throw new Error("unexpected exception", exception);
}
catch (InstantiationException exception) {
throw new Error("unexpected exception", exception);
}
}
}