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

Change to java.awt.Toolkit breaks existing subclasses

XMLWordPrintable

    • x86
    • linux

      It is currently impossible to have a subclass of java.awt.Toolkit that compiles both under JDK 1.4/1.5 and under JDK 1.6. For example, the following class:

      ---%<---
      import java.awt.Button;
      import java.awt.Canvas;
      import java.awt.Checkbox;
      import java.awt.CheckboxMenuItem;
      import java.awt.Choice;
      import java.awt.Dialog;
      import java.awt.Dimension;
      import java.awt.EventQueue;
      import java.awt.FileDialog;
      import java.awt.Font;
      import java.awt.FontMetrics;
      import java.awt.Frame;
      import java.awt.HeadlessException;
      import java.awt.Image;
      import java.awt.Label;
      import java.awt.List;
      import java.awt.Menu;
      import java.awt.MenuBar;
      import java.awt.MenuItem;
      import java.awt.Panel;
      import java.awt.PopupMenu;
      import java.awt.PrintJob;
      import java.awt.ScrollPane;
      import java.awt.Scrollbar;
      import java.awt.TextArea;
      import java.awt.TextField;
      import java.awt.Toolkit;
      import java.awt.Window;
      import java.awt.datatransfer.Clipboard;
      import java.awt.dnd.DragGestureEvent;
      import java.awt.dnd.InvalidDnDOperationException;
      import java.awt.dnd.peer.DragSourceContextPeer;
      import java.awt.im.InputMethodHighlight;
      import java.awt.image.ColorModel;
      import java.awt.image.ImageObserver;
      import java.awt.image.ImageProducer;
      import java.awt.peer.ButtonPeer;
      import java.awt.peer.CanvasPeer;
      import java.awt.peer.CheckboxMenuItemPeer;
      import java.awt.peer.CheckboxPeer;
      import java.awt.peer.ChoicePeer;
      import java.awt.peer.DialogPeer;
      import java.awt.peer.FileDialogPeer;
      import java.awt.peer.FontPeer;
      import java.awt.peer.FramePeer;
      import java.awt.peer.LabelPeer;
      import java.awt.peer.ListPeer;
      import java.awt.peer.MenuBarPeer;
      import java.awt.peer.MenuItemPeer;
      import java.awt.peer.MenuPeer;
      import java.awt.peer.PanelPeer;
      import java.awt.peer.PopupMenuPeer;
      import java.awt.peer.ScrollPanePeer;
      import java.awt.peer.ScrollbarPeer;
      import java.awt.peer.TextAreaPeer;
      import java.awt.peer.TextFieldPeer;
      import java.awt.peer.WindowPeer;
      import java.net.URL;
      import java.util.Map;
      import java.util.Properties;
      public class TestToolkitSubclassing {
          public static void main(String[] args) {
              new TK();
              System.out.println("OK");
          }
          private static final class TK extends Toolkit {
              public TK() {}
              protected ButtonPeer createButton(Button target) throws HeadlessException {return null;}
              protected TextFieldPeer createTextField(TextField target) throws HeadlessException {return null;}
              protected LabelPeer createLabel(Label target) throws HeadlessException {return null;}
              protected ListPeer createList(List target) throws HeadlessException {return null;}
              protected CheckboxPeer createCheckbox(Checkbox target) throws HeadlessException {return null;}
              protected ScrollbarPeer createScrollbar(Scrollbar target) throws HeadlessException {return null;}
              protected ScrollPanePeer createScrollPane(ScrollPane target) throws HeadlessException {return null;}
              protected TextAreaPeer createTextArea(TextArea target) throws HeadlessException {return null;}
              protected ChoicePeer createChoice(Choice target) throws HeadlessException {return null;}
              protected FramePeer createFrame(Frame target) throws HeadlessException {return null;}
              protected CanvasPeer createCanvas(Canvas target) {return null;}
              protected PanelPeer createPanel(Panel target) {return null;}
              protected WindowPeer createWindow(Window target) throws HeadlessException {return null;}
              protected DialogPeer createDialog(Dialog target) throws HeadlessException {return null;}
              protected MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException {return null;}
              protected MenuPeer createMenu(Menu target) throws HeadlessException {return null;}
              protected PopupMenuPeer createPopupMenu(PopupMenu target) throws HeadlessException {return null;}
              protected MenuItemPeer createMenuItem(MenuItem target) throws HeadlessException {return null;}
              protected FileDialogPeer createFileDialog(FileDialog target) throws HeadlessException {return null;}
              protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) throws HeadlessException {return null;}
              protected FontPeer getFontPeer(String name, int style) {return null;}
              public Dimension getScreenSize() throws HeadlessException {return null;}
              public int getScreenResolution() throws HeadlessException {return 0;}
              public ColorModel getColorModel() throws HeadlessException {return null;}
              public String[] getFontList() {return null;}
              public FontMetrics getFontMetrics(Font font) {return null;}
              public void sync() {}
              public Image getImage(String filename) {return null;}
              public Image getImage(URL url) {return null;}
              public Image createImage(String filename) {return null;}
              public Image createImage(URL url) {return null;}
              public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {return false;}
              public int checkImage(Image image, int width, int height, ImageObserver observer) {return 0;}
              public Image createImage(ImageProducer producer) {return null;}
              public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {return null;}
              public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {return null;}
              public void beep() {}
              public Clipboard getSystemClipboard() throws HeadlessException {return null;}
              protected EventQueue getSystemEventQueueImpl() {return null;}
              public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {return null;}
              public Map mapInputMethodHighlight(InputMethodHighlight highlight) throws HeadlessException {return null;}
          }
      }
      ---%<---

      is OK in 1.4/1.5:

      ---%<---
      $ /space/jdk1.4.2_08/bin/javac TestToolkitSubclassing.java
      Note: TestToolkitSubclassing.java uses or overrides a deprecated API.
      Note: Recompile with -deprecation for details.
      $ /space/jdk1.4.2_08/bin/java TestToolkitSubclassing
      OK
      ---%<---

      but does not compile under JDK 1.6:

      ---%<---
      $ /space/jdk1.6.0-b46/bin/javac TestToolkitSubclassing.java
      TestToolkitSubclassing.java:66: TestToolkitSubclassing.TK is not abstract and does not override abstract method isModalExclusionTypeSupported(java.awt.Dialog.ModalExclusionType) in java.awt.Toolkit
          private static final class TK extends Toolkit {
                               ^
      Note: TestToolkitSubclassing.java uses or overrides a deprecated API.
      Note: Recompile with -Xlint:deprecation for details.
      Note: TestToolkitSubclassing.java uses unchecked or unsafe operations.
      Note: Recompile with -Xlint:unchecked for details.
      1 error
      ---%<---

      If you try to fix it, you find that you have to introduce the method isModalExclusionTypeSupported. But since the new method signature uses the newly introduced Dialog.ModalExclusionType, the fixed class will not compile under JDK 1.4/1.5. So you are stuck. You can make your class only work with JDK 1.6+. Or you can make it compile only under JDK 1.4/1.5 - it will probably still run OK under 1.6, assuming no one calls the new method, but it will not compile.

      Adding a new abstract method to a nonfinal class with an accessible constructor is an incompatible change. Is there any documented exception that says certain classes in the Java Platform, such as java.awt.Toolkit, are only permitted to be subclassed by classes inside the platform implementation?
      Unfortunately, there is nothing we can do regarding this. Toolkit class and other classes get changed during major releases. We add new interfaces, we *modify* existing ones (such as java.awt.peer). We add abstract methods and so on. Toolkit and peer implementations are *not* supposed to work across releases, since the amount of changes is too big and the changes are spread across various packages, so if some change to shared code (java.awt) happened - peer and Toolkit implementation needs to be updated.

            art Artem Ananiev (Inactive)
            jglick Jesse Glick (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: