From 8c26397da5a366b6c2b6bb6e46ce4411dfb74fd9 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 8 May 2015 15:37:38 +0300 Subject: [PATCH 001/117] 6980209: Make tracking SecondaryLoop.enter/exit methods easier Reviewed-by: serb, ant --- .../classes/java/awt/WaitDispatchSupport.java | 210 +++++++-------- .../awt/EventQueue/6980209/bug6980209.java | 241 ++++++++++++++++++ 2 files changed, 350 insertions(+), 101 deletions(-) create mode 100644 jdk/test/java/awt/EventQueue/6980209/bug6980209.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java b/jdk/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java index 15129a457ea..d3a692ab5a8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java +++ b/jdk/src/java.desktop/share/classes/java/awt/WaitDispatchSupport.java @@ -65,6 +65,7 @@ class WaitDispatchSupport implements SecondaryLoop { private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false); private AtomicBoolean keepBlockingCT = new AtomicBoolean(false); + private AtomicBoolean afterExit = new AtomicBoolean(false); private static synchronized void initializeTimer() { if (timer == null) { @@ -114,7 +115,7 @@ class WaitDispatchSupport implements SecondaryLoop { } boolean extEvaluate = (extCondition != null) ? extCondition.evaluate() : true; - if (!keepBlockingEDT.get() || !extEvaluate) { + if (!keepBlockingEDT.get() || !extEvaluate || afterExit.get()) { if (timerTask != null) { timerTask.cancel(); timerTask = null; @@ -174,110 +175,116 @@ class WaitDispatchSupport implements SecondaryLoop { log.fine("The secondary loop is already running, aborting"); return false; } + try { + if (afterExit.get()) { + log.fine("Exit was called already, aborting"); + return false; + } - final Runnable run = new Runnable() { - public void run() { - log.fine("Starting a new event pump"); - if (filter == null) { - dispatchThread.pumpEvents(condition); - } else { - dispatchThread.pumpEventsForFilter(condition, filter); - } - } - }; - - // We have two mechanisms for blocking: if we're on the - // dispatch thread, start a new event pump; if we're - // on any other thread, call wait() on the treelock - - Thread currentThread = Thread.currentThread(); - if (currentThread == dispatchThread) { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("On dispatch thread: " + dispatchThread); - } - if (interval != 0) { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("scheduling the timer for " + interval + " ms"); - } - timer.schedule(timerTask = new TimerTask() { - @Override - public void run() { - if (keepBlockingEDT.compareAndSet(true, false)) { - wakeupEDT(); - } - } - }, interval); - } - // Dispose SequencedEvent we are dispatching on the current - // AppContext, to prevent us from hang - see 4531693 for details - SequencedEvent currentSE = KeyboardFocusManager. - getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); - if (currentSE != null) { - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("Dispose current SequencedEvent: " + currentSE); - } - currentSE.dispose(); - } - // In case the exit() method is called before starting - // new event pump it will post the waking event to EDT. - // The event will be handled after the new event pump - // starts. Thus, the enter() method will not hang. - // - // Event pump should be privileged. See 6300270. - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - run.run(); - return null; - } - }); - } else { - if (log.isLoggable(PlatformLogger.Level.FINEST)) { - log.finest("On non-dispatch thread: " + currentThread); - } - synchronized (getTreeLock()) { - if (filter != null) { - dispatchThread.addEventFilter(filter); - } - try { - EventQueue eq = dispatchThread.getEventQueue(); - eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT)); - keepBlockingCT.set(true); - if (interval > 0) { - long currTime = System.currentTimeMillis(); - while (keepBlockingCT.get() && - ((extCondition != null) ? extCondition.evaluate() : true) && - (currTime + interval > System.currentTimeMillis())) - { - getTreeLock().wait(interval); - } + final Runnable run = new Runnable() { + public void run() { + log.fine("Starting a new event pump"); + if (filter == null) { + dispatchThread.pumpEvents(condition); } else { - while (keepBlockingCT.get() && - ((extCondition != null) ? extCondition.evaluate() : true)) - { - getTreeLock().wait(); - } - } - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get()); - } - } catch (InterruptedException e) { - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("Exception caught while waiting: " + e); - } - } finally { - if (filter != null) { - dispatchThread.removeEventFilter(filter); + dispatchThread.pumpEventsForFilter(condition, filter); } } - // If the waiting process has been stopped because of the - // time interval passed or an exception occurred, the state - // should be changed - keepBlockingEDT.set(false); - keepBlockingCT.set(false); - } - } + }; - return true; + // We have two mechanisms for blocking: if we're on the + // dispatch thread, start a new event pump; if we're + // on any other thread, call wait() on the treelock + + Thread currentThread = Thread.currentThread(); + if (currentThread == dispatchThread) { + if (log.isLoggable(PlatformLogger.Level.FINEST)) { + log.finest("On dispatch thread: " + dispatchThread); + } + if (interval != 0) { + if (log.isLoggable(PlatformLogger.Level.FINEST)) { + log.finest("scheduling the timer for " + interval + " ms"); + } + timer.schedule(timerTask = new TimerTask() { + @Override + public void run() { + if (keepBlockingEDT.compareAndSet(true, false)) { + wakeupEDT(); + } + } + }, interval); + } + // Dispose SequencedEvent we are dispatching on the current + // AppContext, to prevent us from hang - see 4531693 for details + SequencedEvent currentSE = KeyboardFocusManager. + getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); + if (currentSE != null) { + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("Dispose current SequencedEvent: " + currentSE); + } + currentSE.dispose(); + } + // In case the exit() method is called before starting + // new event pump it will post the waking event to EDT. + // The event will be handled after the new event pump + // starts. Thus, the enter() method will not hang. + // + // Event pump should be privileged. See 6300270. + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + run.run(); + return null; + } + }); + } else { + if (log.isLoggable(PlatformLogger.Level.FINEST)) { + log.finest("On non-dispatch thread: " + currentThread); + } + keepBlockingCT.set(true); + synchronized (getTreeLock()) { + if (afterExit.get()) return false; + if (filter != null) { + dispatchThread.addEventFilter(filter); + } + try { + EventQueue eq = dispatchThread.getEventQueue(); + eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT)); + if (interval > 0) { + long currTime = System.currentTimeMillis(); + while (keepBlockingCT.get() && + ((extCondition != null) ? extCondition.evaluate() : true) && + (currTime + interval > System.currentTimeMillis())) + { + getTreeLock().wait(interval); + } + } else { + while (keepBlockingCT.get() && + ((extCondition != null) ? extCondition.evaluate() : true)) + { + getTreeLock().wait(); + } + } + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get()); + } + } catch (InterruptedException e) { + if (log.isLoggable(PlatformLogger.Level.FINE)) { + log.fine("Exception caught while waiting: " + e); + } + } finally { + if (filter != null) { + dispatchThread.removeEventFilter(filter); + } + } + } + } + return true; + } + finally { + keepBlockingEDT.set(false); + keepBlockingCT.set(false); + afterExit.set(false); + } } /** @@ -288,7 +295,8 @@ class WaitDispatchSupport implements SecondaryLoop { log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() + ", blockingCT=" + keepBlockingCT.get()); } - if (keepBlockingEDT.compareAndSet(true, false)) { + afterExit.set(true); + if (keepBlockingEDT.getAndSet(false)) { wakeupEDT(); return true; } diff --git a/jdk/test/java/awt/EventQueue/6980209/bug6980209.java b/jdk/test/java/awt/EventQueue/6980209/bug6980209.java new file mode 100644 index 00000000000..d39235ae44c --- /dev/null +++ b/jdk/test/java/awt/EventQueue/6980209/bug6980209.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 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 6980209 + @summary Make tracking SecondaryLoop.enter/exit methods easier + @author Semyon Sadetsky + */ + +import sun.util.logging.PlatformLogger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +public class bug6980209 implements ActionListener { + private final static PlatformLogger log = + PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport"); + public static final int ATTEMPTS = 100; + public static final int EVENTS = 5; + + private static boolean runInEDT; + private static JFrame frame; + private static int disorderCounter = 0; + private static Boolean enterReturn; + private static Boolean exitReturn; + private static int dispatchedEvents; + + public static void main(String[] args) throws Exception { + System.out.println( + "PLEASE DO NOT TOUCH KEYBOARD AND MOUSE DURING THE TEST RUN!"); + // log.setLevel(PlatformLogger.Level.FINE); + // log.setLevel(PlatformLogger.Level.FINEST); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + frame.setUndecorated(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setup(frame); + } + }); + testExitBeforeEnter(); + System.out.println("Run random test in EDT"); + runInEDT = true; + testRandomly(); + System.out.println("Run random test in another thread"); + runInEDT = false; + testRandomly(); + System.out.println("ok"); + + } finally { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + } + + private static void testExitBeforeEnter() throws Exception { + final SecondaryLoop loop = + Toolkit.getDefaultToolkit().getSystemEventQueue() + .createSecondaryLoop(); + loop.exit(); + Robot robot = new Robot(); + robot.mouseWheel(1); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if(loop.enter()) { + throw new RuntimeException("Wrong enter() return value"); + } + } + }); + } + + private static void testRandomly() throws AWTException { + disorderCounter = 0; + final Robot robot = new Robot(); + for (int i = 0; i < ATTEMPTS; i++) { + enterReturn = null; + exitReturn = null; + dispatchedEvents = 0; + synchronized (bug6980209.class) { + try { + for (int j = 0; j < EVENTS; j++) { + robot.keyPress(KeyEvent.VK_1); + robot.keyRelease(KeyEvent.VK_1); + } + + // trigger the button action that starts secondary loop + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + + for (int j = 0; j < EVENTS; j++) { + robot.keyPress(KeyEvent.VK_1); + robot.keyRelease(KeyEvent.VK_1); + } + long time = System.nanoTime(); + // wait for enter() returns + bug6980209.class.wait(1000); + if (enterReturn == null) { + System.out.println("wait time=" + + ((System.nanoTime() - time) / 1E9) + + " seconds"); + throw new RuntimeException( + "It seems the secondary loop will never end"); + } + if (!enterReturn) disorderCounter++; + + robot.waitForIdle(); + if (dispatchedEvents < + 2 * EVENTS) { //check that all events are dispatched + throw new RuntimeException( + "KeyEvent.VK_1 has been lost!"); + } + + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted!"); + } + } + } + if (disorderCounter == 0) { + System.out.println( + "Zero disordered enter/exit caught. It is recommended to run scenario again"); + } else { + System.out.println( + "Disordered calls is " + disorderCounter + " from " + + ATTEMPTS); + } + } + + private static void setup(final JFrame frame) { + JButton jButton = new JButton("Button"); + frame.getContentPane().add(jButton); + jButton.addActionListener(new bug6980209()); + frame.pack(); + frame.setVisible(true); + jButton.setFocusable(true); + jButton.requestFocus(); + jButton.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == '1') dispatchedEvents++; + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() == '1') dispatchedEvents++; + } + }); + } + + + @Override + public void actionPerformed(ActionEvent e) { + if (runInEDT) { + runSecondaryLoop(); + return; + } + new Thread("Secondary loop run thread") { + @Override + public void run() { + runSecondaryLoop(); + } + }.start(); + } + + private static void runSecondaryLoop() { + log.fine("\n---TEST START---"); + + final SecondaryLoop loop = + Toolkit.getDefaultToolkit().getSystemEventQueue() + .createSecondaryLoop(); + + final Object LOCK = new Object(); //lock to start simultaneously + Thread exitThread = new Thread("Exit thread") { + @Override + public void run() { + synchronized (LOCK) { + LOCK.notify(); + } + Thread.yield(); + exitReturn = loop.exit(); + log.fine("exit() returns " + exitReturn); + } + }; + + synchronized (LOCK) { + try { + exitThread.start(); + LOCK.wait(); + } catch (InterruptedException e1) { + throw new RuntimeException("What?"); + } + } + + enterReturn = loop.enter(); + log.fine("enter() returns " + enterReturn); + + try { + exitThread.join(); + } catch (InterruptedException e) { + throw new RuntimeException("What?"); + } + synchronized (bug6980209.class) { + bug6980209.class.notifyAll(); + } + log.fine("\n---TEST END---"); + } +} From 25b0a009bc27acbd91e907aa947799ab1ed13782 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 8 May 2015 16:46:24 +0300 Subject: [PATCH 002/117] 7072653: JComboBox popup mispositioned if its height exceeds the screen height Reviewed-by: alexsch, azvegint --- .../com/apple/laf/AquaComboBoxPopup.java | 20 ++- .../swing/plaf/basic/BasicComboPopup.java | 25 +++- .../BasicComboPopup/7072653/bug7072653.java | 127 ++++++++++++++++++ 3 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java index 0f466e188e6..ecc6d20690e 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -204,7 +204,8 @@ class AquaComboBoxPopup extends BasicComboPopup { if ((p.x + comboBoxBounds.width < 0) || (p.y + comboBoxBounds.height < 0) || (p.x > scrSize.width) || (p.y > scrSize.height)) { return null; } - return new Rectangle(0, 22, scrSize.width, scrSize.height - 22); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(comboBox.getGraphicsConfiguration()); + return new Rectangle(0, insets.top, scrSize.width, scrSize.height - insets.top - insets.bottom); } for (final GraphicsDevice gd : gs) { @@ -314,10 +315,17 @@ class AquaComboBoxPopup extends BasicComboPopup { } final Rectangle r = new Rectangle(px, py, pw, ph); - // Check whether it goes below the bottom of the screen, if so flip it - if (r.y + r.height < top.y + scrBounds.y + scrBounds.height) return r; - - return new Rectangle(px, -r.height + comboBoxInsets.top, r.width, r.height); + if (py + ph > scrBounds.y + scrBounds.height) { + if (ph <= -scrBounds.y ) { + // popup goes above + r.y = -ph ; + } else { + // a full screen height popup + r.y = scrBounds.y + Math.max(0, (scrBounds.height - ph) / 2 ); + r.height = Math.min(scrBounds.height, ph); + } + } + return r; } // The one to use when itemCount <= maxRowCount. Size never adjusts for arrows diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index 47b5f73ec47..c70c06cad89 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -1287,11 +1287,24 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { else { screenBounds = new Rectangle(p, toolkit.getScreenSize()); } - - Rectangle rect = new Rectangle(px,py,pw,ph); - if (py+ph > screenBounds.y+screenBounds.height - && ph < screenBounds.height) { - rect.y = -rect.height; + int borderHeight = 0; + Border popupBorder = getBorder(); + if (popupBorder != null) { + Insets borderInsets = popupBorder.getBorderInsets(this); + borderHeight = borderInsets.top + borderInsets.bottom; + screenBounds.width -= (borderInsets.left + borderInsets.right); + screenBounds.height -= borderHeight; + } + Rectangle rect = new Rectangle(px, py, pw, ph); + if (py + ph > screenBounds.y + screenBounds.height) { + if (ph <= -screenBounds.y - borderHeight) { + // popup goes above + rect.y = -ph - borderHeight; + } else { + // a full screen height popup + rect.y = screenBounds.y + Math.max(0, (screenBounds.height - ph) / 2 ); + rect.height = Math.min(screenBounds.height, ph); + } } return rect; } diff --git a/jdk/test/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java b/jdk/test/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java new file mode 100644 index 00000000000..ccecdc2c311 --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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 7072653 + @summary JComboBox popup mispositioned if its height exceeds the screen height + @author Semyon Sadetsky + */ + + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.*; +import java.awt.Toolkit; + +public class bug7072653 { + + private static JComboBox combobox; + private static JFrame frame; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame("JComboBox Test"); + setup(frame); + } + }); + test(); + } + finally { + frame.dispose(); + } + + } + + static void setup(JFrame frame) { + + + frame.setUndecorated(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setSize(320, 200); + + frame.getContentPane().setLayout(new FlowLayout()); + + combobox = new JComboBox(new DefaultComboBoxModel() { + public Object getElementAt(int index) { return "Element " + index; } + public int getSize() { + return 1000; + } + }); + + + combobox.setMaximumRowCount(100); + frame.getContentPane().add(combobox); + + frame.setVisible(true); + + } + + static void test() throws Exception{ + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + combobox.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + int height = 0; + for (Window window : JFrame.getWindows()) { + if (Window.Type.POPUP == window.getType()) { + height = window.getSize().height; + break; + } + } + GraphicsConfiguration gc = + combobox.getGraphicsConfiguration(); + Insets screenInsets = Toolkit.getDefaultToolkit() + .getScreenInsets(gc); + + if (height == gc.getBounds().height - screenInsets.top - + screenInsets.bottom ) { + System.out.println("ok"); + return; + } + throw new RuntimeException( + "Popup window height is wrong " + height); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + combobox.setPopupVisible(true); + combobox.setPopupVisible(false); + } + }); + } + + +} From 3a2ff1374b9ab1af79ef93a39a8236da86fd2747 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 8 May 2015 17:35:15 +0300 Subject: [PATCH 003/117] 7155957: closed/java/awt/MenuBar/MenuBarStress1/MenuBarStress1.java hangs on win 64 bit with jdk8 Reviewed-by: serb, ant --- .../java.desktop/share/classes/java/awt/Menu.java | 2 +- .../share/classes/java/awt/MenuBar.java | 4 ++-- .../share/classes/java/awt/MenuComponent.java | 14 ++++++++------ .../classes/sun/awt/windows/WObjectPeer.java | 4 ++-- .../windows/native/libawt/windows/awt_Menu.cpp | 8 +++++--- .../windows/native/libawt/windows/awt_MenuBar.cpp | 5 ++++- .../windows/native/libawt/windows/awt_MenuItem.cpp | 1 + .../windows/native/libawt/windows/awt_new.cpp | 3 +++ 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/java/awt/Menu.java b/jdk/src/java.desktop/share/classes/java/awt/Menu.java index 4f4a2099c55..af7d4c6b734 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Menu.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Menu.java @@ -413,9 +413,9 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { items.removeElementAt(index); MenuPeer peer = (MenuPeer)this.peer; if (peer != null) { + peer.delItem(index); mi.removeNotify(); mi.parent = null; - peer.delItem(index); } } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java index 648441e68ef..5ba87f646b9 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java @@ -222,7 +222,6 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible if (m.parent != null) { m.parent.remove(m); } - menus.addElement(m); m.parent = this; MenuBarPeer peer = (MenuBarPeer)this.peer; @@ -232,6 +231,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible } peer.addMenu(m); } + menus.addElement(m); return m; } } @@ -248,9 +248,9 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible menus.removeElementAt(index); MenuBarPeer peer = (MenuBarPeer)this.peer; if (peer != null) { + peer.delMenu(index); m.removeNotify(); m.parent = null; - peer.delMenu(index); } if (helpMenu == m) { helpMenu = null; diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java index 6c1bbf200d6..b99e1c3eb7f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -77,7 +77,7 @@ public abstract class MenuComponent implements java.io.Serializable { * @see #setFont(Font) * @see #getFont() */ - Font font; + volatile Font font; /** * The menu component's name, which defaults to null. @@ -302,11 +302,13 @@ public abstract class MenuComponent implements java.io.Serializable { * @see java.awt.font.TextAttribute */ public void setFont(Font f) { - font = f; - //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) - MenuComponentPeer peer = this.peer; - if (peer != null) { - peer.setFont(f); + synchronized (getTreeLock()) { + font = f; + //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) + MenuComponentPeer peer = this.peer; + if (peer != null) { + peer.setFont(f); + } } } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java index 843b15f83d1..83f7c586f2a 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WObjectPeer.java @@ -31,9 +31,9 @@ abstract class WObjectPeer { } // The Windows handle for the native widget. - long pData; + volatile long pData; // if the native peer has been destroyed - boolean destroyed = false; + volatile boolean destroyed = false; // The associated AWT object. Object target; diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Menu.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Menu.cpp index 8bea41c88e3..d452f148012 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Menu.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Menu.cpp @@ -239,6 +239,7 @@ AwtMenuItem* AwtMenu::GetItem(jobject target, jint index) } jobject menuItem = env->CallObjectMethod(target, AwtMenu::getItemMID, index); + if (!menuItem) return NULL; // menu item was removed concurrently DASSERT(!safe_ExceptionOccurred(env)); jobject wMenuItemPeer = GetPeerForTarget(env, menuItem); @@ -264,9 +265,9 @@ void AwtMenu::DrawItems(DRAWITEMSTRUCT& drawInfo) } /* target is a java.awt.Menu */ jobject target = GetTarget(env); - + if(!target || env->ExceptionCheck()) return; int nCount = CountItem(target); - for (int i = 0; i < nCount; i++) { + for (int i = 0; i < nCount && !env->ExceptionCheck(); i++) { AwtMenuItem* awtMenuItem = GetItem(target, i); if (awtMenuItem != NULL) { SendDrawItem(awtMenuItem, drawInfo); @@ -294,8 +295,9 @@ void AwtMenu::MeasureItems(HDC hDC, MEASUREITEMSTRUCT& measureInfo) } /* target is a java.awt.Menu */ jobject target = GetTarget(env); + if(!target || env->ExceptionCheck()) return; int nCount = CountItem(target); - for (int i = 0; i < nCount; i++) { + for (int i = 0; i < nCount && !env->ExceptionCheck(); i++) { AwtMenuItem* awtMenuItem = GetItem(target, i); if (awtMenuItem != NULL) { SendMeasureItem(awtMenuItem, hDC, measureInfo); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp index c600d8d36ac..d15e2809a73 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuBar.cpp @@ -156,13 +156,16 @@ AwtMenuItem* AwtMenuBar::GetItem(jobject target, long index) } jobject menu = env->CallObjectMethod(target, AwtMenuBar::getMenuMID,index); + if (!menu) return NULL; // menu item was removed concurrently DASSERT(!safe_ExceptionOccurred(env)); jobject menuItemPeer = GetPeerForTarget(env, menu); PDATA pData; - JNI_CHECK_PEER_RETURN_NULL(menuItemPeer); + JNI_CHECK_PEER_GOTO(menuItemPeer, done); + AwtMenuItem* awtMenuItem = (AwtMenuItem*)pData; +done: env->DeleteLocalRef(menu); env->DeleteLocalRef(menuItemPeer); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp index c0a0120c79e..ba0488187c5 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp @@ -112,6 +112,7 @@ void AwtMenuItem::Dispose() JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (m_peerObject != NULL) { + JNI_SET_DESTROYED(m_peerObject); JNI_SET_PDATA(m_peerObject, NULL); env->DeleteGlobalRef(m_peerObject); m_peerObject = NULL; diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_new.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_new.cpp index e5adec25b56..b2d133f2350 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_new.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_new.cpp @@ -172,6 +172,9 @@ safe_ExceptionOccurred(JNIEnv *env) throw (std::bad_alloc) { env->ExceptionClear(); // rethrow exception env->Throw(xcp); + // temp solution to reveal all concurrency issues in jtreg and JCK + // we will switch it back to silent mode before the release + env->ExceptionDescribe(); return xcp; } } From 443304485b870390f9cdd019c3e2b06d5a2b46ad Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 8 May 2015 17:40:43 +0300 Subject: [PATCH 004/117] 7190544: Nimbus LaF: regression UnitTest failure Reviewed-by: alexsch, azvegint, serb --- .../share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java index f82ccb37fab..667d6ded258 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -134,6 +134,7 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI value = Integer.valueOf(6); } LookAndFeel.installProperty(splitPane, "dividerSize", value); + dividerSize = ((Number)value).intValue(); value = style.get(context, "SplitPane.oneTouchExpandable"); if (value != null) { From ee650b24f55daf92f35322653d566a28305dc7b0 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 8 May 2015 19:14:16 +0300 Subject: [PATCH 005/117] 8078149: [macosx] The text of the TextArea is not wrapped at word boundaries Reviewed-by: azvegint, alexsch --- .../macosx/classes/sun/lwawt/LWTextAreaPeer.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWTextAreaPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWTextAreaPeer.java index 5db1b6ca296..f313c466643 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWTextAreaPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWTextAreaPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -23,7 +23,6 @@ * questions. */ - package sun.lwawt; import java.awt.Component; @@ -40,7 +39,6 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ScrollPaneConstants; import javax.swing.text.Document; -import javax.swing.text.JTextComponent; /** * Lightweight implementation of {@link TextAreaPeer}. Delegates most of the @@ -75,12 +73,13 @@ final class LWTextAreaPeer super.initializeImpl(); final int visibility = getTarget().getScrollbarVisibility(); synchronized (getDelegateLock()) { + getTextComponent().setWrapStyleWord(true); setScrollBarVisibility(visibility); } } @Override - JTextComponent getTextComponent() { + JTextArea getTextComponent() { return getDelegate().getView(); } @@ -165,7 +164,7 @@ final class LWTextAreaPeer // JTextArea.replaceRange() is called. final Document document = getTextComponent().getDocument(); document.removeDocumentListener(this); - getDelegate().getView().replaceRange(text, start, end); + getTextComponent().replaceRange(text, start, end); revalidate(); postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); document.addDocumentListener(this); From 2e5926125a4394bae934832d7eac243f94724dd8 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 8 May 2015 19:31:09 +0300 Subject: [PATCH 006/117] 5036022: JSpinner does not reflect new font on subsequent calls to setFont Reviewed-by: azvegint, alexsch --- .../classes/com/apple/laf/AquaSpinnerUI.java | 10 +- .../swing/plaf/basic/BasicSpinnerUI.java | 8 +- .../WrongEditorTextFieldFont.java | 114 ++++++++++++++++++ 3 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 jdk/test/javax/swing/JSpinner/WrongEditorTextFieldFont/WrongEditorTextFieldFont.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java index 1f9cc03dadc..9b07d8645a1 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -232,12 +232,12 @@ public class AquaSpinnerUI extends SpinnerUI { editor.setInheritsPopupMenu(true); if (editor.getFont() instanceof UIResource) { - editor.setFont(spinner.getFont()); + editor.setFont(new FontUIResource(spinner.getFont())); } final JFormattedTextField editorTextField = ((DefaultEditor)editor).getTextField(); if (editorTextField.getFont() instanceof UIResource) { - editorTextField.setFont(spinner.getFont()); + editorTextField.setFont(new FontUIResource(spinner.getFont())); } final InputMap spinnerInputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); final InputMap editorInputMap = editorTextField.getInputMap(); @@ -648,12 +648,12 @@ public class AquaSpinnerUI extends SpinnerUI { ui.updateToolTipTextForChildren(spinner); } else if ("font".equals(propertyName)) { JComponent editor = spinner.getEditor(); - if (editor != null && editor instanceof JSpinner.DefaultEditor) { + if (editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor) editor).getTextField(); if (tf != null) { if (tf.getFont() instanceof UIResource) { - tf.setFont(spinner.getFont()); + tf.setFont(new FontUIResource(spinner.getFont())); } } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java index ee9cdefbe90..f6d211f5f9f 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -989,7 +989,7 @@ public class BasicSpinnerUI extends SpinnerUI ((JSpinner.DefaultEditor)newEditor).getTextField(); if (tf != null) { if (tf.getFont() instanceof UIResource) { - tf.setFont(spinner.getFont()); + tf.setFont(new FontUIResource(spinner.getFont())); } tf.addFocusListener(nextButtonHandler); tf.addFocusListener(previousButtonHandler); @@ -1002,12 +1002,12 @@ public class BasicSpinnerUI extends SpinnerUI } else if ("font".equals(propertyName)) { JComponent editor = spinner.getEditor(); - if (editor!=null && editor instanceof JSpinner.DefaultEditor) { + if (editor instanceof JSpinner.DefaultEditor) { JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); if (tf != null) { if (tf.getFont() instanceof UIResource) { - tf.setFont(spinner.getFont()); + tf.setFont(new FontUIResource(spinner.getFont())); } } } diff --git a/jdk/test/javax/swing/JSpinner/WrongEditorTextFieldFont/WrongEditorTextFieldFont.java b/jdk/test/javax/swing/JSpinner/WrongEditorTextFieldFont/WrongEditorTextFieldFont.java new file mode 100644 index 00000000000..0236298c1e6 --- /dev/null +++ b/jdk/test/javax/swing/JSpinner/WrongEditorTextFieldFont/WrongEditorTextFieldFont.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.FlowLayout; +import java.awt.Font; + +import javax.swing.JFrame; +import javax.swing.JSpinner; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.UIResource; + +import static javax.swing.JSpinner.*; +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/** + * @test + * @bug 5036022 + * @author Sergey Bylokhov + */ +public class WrongEditorTextFieldFont implements Runnable { + + private static final Font USERS_FONT = new Font("dialog", Font.BOLD, 41); + + public static void main(final String[] args) throws Exception { + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(new WrongEditorTextFieldFont()); + } + } + + @Override + public void run() { + final JFrame frame1 = new JFrame(); + try { + testDefaultFont(frame1); + } finally { + frame1.dispose(); + } + } + + private static void testDefaultFont(final JFrame frame) { + final JSpinner spinner = new JSpinner(); + final JSpinner spinner_u = new JSpinner(); + frame.setLayout(new FlowLayout(FlowLayout.CENTER, 50, 50)); + frame.getContentPane().add(spinner); + frame.getContentPane().add(spinner_u); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + final DefaultEditor ed = (DefaultEditor) spinner.getEditor(); + final DefaultEditor ed_u = (DefaultEditor) spinner_u.getEditor(); + ed_u.getTextField().setFont(USERS_FONT); + + for (int i = 5; i < 40; i += 5) { + /* + * Validate that the font of the text field is changed to the + * font of JSpinner if the font of text field was not set by the + * user. + */ + final Font tff = ed.getTextField().getFont(); + if (!(tff instanceof UIResource)) { + throw new RuntimeException("Font must be UIResource"); + } + if (spinner.getFont().getSize() != tff.getSize()) { + throw new RuntimeException("Rrong size"); + } + spinner.setFont(new Font("dialog", Font.BOLD, i)); + /* + * Validate that the font of the text field is NOT changed to the + * font of JSpinner if the font of text field was set by the user. + */ + final Font tff_u = ed_u.getTextField().getFont(); + if (tff_u instanceof UIResource || !tff_u.equals(USERS_FONT)) { + throw new RuntimeException("Font must NOT be UIResource"); + } + if (spinner_u.getFont().getSize() == tff_u.getSize()) { + throw new RuntimeException("Wrong size"); + } + spinner_u.setFont(new Font("dialog", Font.BOLD, i)); + } + } + + private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + System.out.println("LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + UnsupportedLookAndFeelException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} From f00ee27f3c0238138b6d966b269c9247735daff0 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 8 May 2015 20:06:08 +0300 Subject: [PATCH 007/117] 8013820: JavaDoc for JSpinner contains errors Reviewed-by: azvegint, alexsch --- .../share/classes/javax/swing/JSpinner.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java b/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java index 81ef955dee4..064e6e47638 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,8 +42,6 @@ import java.text.spi.NumberFormatProvider; import javax.accessibility.*; import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.locale.provider.LocaleResources; -import sun.util.locale.provider.LocaleServiceProviderPool; - /** * A single line input field that lets the user select a @@ -77,12 +75,12 @@ import sun.util.locale.provider.LocaleServiceProviderPool; * try { * spinner.commitEdit(); * } - * catch (ParseException pe) {{ + * catch (ParseException pe) { * // Edited value is invalid, spinner.getValue() will return * // the last valid value, you could revert the spinner to show that: - * JComponent editor = spinner.getEditor() + * JComponent editor = spinner.getEditor(); * if (editor instanceof DefaultEditor) { - * ((DefaultEditor)editor).getTextField().setValue(spinner.getValue(); + * ((DefaultEditor)editor).getTextField().setValue(spinner.getValue()); * } * // reset the value to some known value: * spinner.setValue(fallbackValue); From ad5afe4557b84dfba7f10e2d40dc197c7abe27f8 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 8 May 2015 20:43:46 +0300 Subject: [PATCH 008/117] 8015900: [TEST_BUG] ScrollbarMouseWheelTest failed on ubuntu 12 with unity and unity 2D Reviewed-by: azvegint, yan --- .../ScrollbarMouseWheelTest.java | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 jdk/test/java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java diff --git a/jdk/test/java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java b/jdk/test/java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java new file mode 100644 index 00000000000..8ae91678a36 --- /dev/null +++ b/jdk/test/java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1998, 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. + */ + +import java.awt.*; +import java.awt.event.*; + +/** + * @test + * @bug 4449139 + * @summary test MouseWheelEvent generation by Scrollbar component + */ +public final class ScrollbarMouseWheelTest + implements MouseWheelListener, WindowListener { + + final static String tk = Toolkit.getDefaultToolkit().getClass().getName(); + final static int REPS = 5; + // There is a bug on Windows: 4616935. + // Wheel events comes to every component in the hierarchy so we should + // check a platform. + // There are two scrollbars within one Panel and both accept 5 clicks, so + // Panel would accept 5*2 clicks on Windows. + final static int PANEL_REPS = tk.equals("sun.awt.windows.WToolkit")? REPS * 2: REPS; + + Scrollbar sb1; + Scrollbar sb2; + Panel pnl; + class Sema { + boolean flag; + boolean getVal() { return flag;} + void setVal(boolean b) { flag = b;} + } + Sema sema = new Sema(); + + Robot robot; + + int sb1upevents, sb2upevents, pnlupevents; + int sb1downevents, sb2downevents, pnldownevents; + + public static void main(final String[] args) { + new ScrollbarMouseWheelTest().test(); + } + + public void test() { + // Move mouse to upper-right area + try { + robot = new Robot(); + } catch (AWTException e) { + System.out.println("Problem creating Robot. FAIL."); + throw new RuntimeException("Problem creating Robot. FAIL."); + + } + + robot.setAutoDelay(500); + robot.setAutoWaitForIdle(true); + + // Show test Frame + Frame frame = new Frame("ScrollbarMouseWheelTest"); + frame.addWindowListener(this); + pnl = new Panel(); + pnl.setLayout(new GridLayout(1, 2)); + pnl.addMouseWheelListener(this); + sb1 = new Scrollbar(); + sb1.addMouseWheelListener(this); + pnl.add(sb1); + sb2 = new Scrollbar(); + pnl.add(sb2); + frame.add(pnl); + frame.setSize(200, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + + // When Frame is active, start testing (handled in windowActivated()) + while (true) { + synchronized (sema) { + if (sema.getVal()) { + break; + } + } + } + // up on sb1 + testComp(sb1, true); + // down on sb1 + testComp(sb1, false); + // up on sb2 + testComp(sb2, true); + // down on sb2 + testComp(sb2, false); + frame.dispose(); + System.out.println("Test done."); + if (sb1upevents == REPS && + sb2upevents == 0 && + pnlupevents == PANEL_REPS && + sb1downevents == REPS && + sb2downevents == 0 && + pnldownevents == PANEL_REPS) { + System.out.println("PASSED."); + } else { + System.out.println("Test Failed:" + + "\n\tsb1upevents =" + sb1upevents + + "\n\tsb2upevents = " + sb2upevents + + "\n\tpnlupevents = " + pnlupevents + + "\n\tsb1downevents =" + sb1downevents + + "\n\tsb2downevents = " + sb2downevents + + "\n\tpnldownevents = " + pnldownevents); + throw new RuntimeException("Test FAILED."); + } + } + + public void testComp(Component comp, boolean up) { + Point loc = comp.getLocationOnScreen(); + robot.mouseMove(loc.x + comp.getWidth() / 2, + loc.y + comp.getHeight() / 2); + for (int loop = 0; loop < REPS; loop++) { + System.out.println("Robot.mouseWheel() on " + comp.getName()); + robot.mouseWheel(up ? -1 : 1); + } + } + + public void mouseWheelMoved(MouseWheelEvent mwe) { + Component src = mwe.getComponent(); + System.out.println("mouseWheelMoved() on " + src.getName()); + if (mwe.getWheelRotation() == -1) { + if (src == sb1) { + sb1upevents++; + } else if (src == sb2) { + sb2upevents++; + } else if (src == pnl) { + pnlupevents++; + } else { + System.out.println("weird source component"); + } + } else if (mwe.getWheelRotation() == 1) { + if (src == sb1) { + sb1downevents++; + } else if (src == sb2) { + sb2downevents++; + } else if (src == pnl) { + pnldownevents++; + } else { + System.out.println("weird source component"); + } + } else { + System.out.println("weird wheel rotation"); + } + } + + public void windowActivated(WindowEvent we) { + synchronized (sema) { + sema.setVal(true); + } + } + + public void windowClosed(WindowEvent we) {} + public void windowClosing(WindowEvent we) {} + public void windowDeactivated(WindowEvent we) {} + public void windowDeiconified(WindowEvent we) {} + public void windowIconified(WindowEvent we) {} + public void windowOpened(WindowEvent we) {} +}// class ScrollbarMouseWheelTest From eea06f70fc6154be12d066df6669e7c6d8c0bc09 Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Sat, 9 May 2015 02:08:15 +0300 Subject: [PATCH 009/117] 8035568: [macosx] Cursor management unification Reviewed-by: anthony, serb --- .../classes/sun/lwawt/LWMouseInfoPeer.java | 10 ++- .../macosx/classes/sun/lwawt/LWToolkit.java | 4 +- .../classes/sun/lwawt/LWWindowPeer.java | 10 +-- .../classes/sun/lwawt/PlatformWindow.java | 4 +- .../lwawt/macosx/CPlatformEmbeddedFrame.java | 7 +- .../sun/lwawt/macosx/CPlatformLWWindow.java | 7 +- .../sun/lwawt/macosx/CPlatformWindow.java | 6 +- .../classes/sun/lwawt/macosx/CRobot.java | 35 +++++++- .../macosx/CViewPlatformEmbeddedFrame.java | 7 +- .../classes/sun/lwawt/macosx/LWCToolkit.java | 5 ++ .../native/libawt_lwawt/awt/AWTWindow.m | 15 ++-- .../native/libawt_lwawt/awt/CCursorManager.m | 14 ++- .../macosx/native/libawt_lwawt/awt/CRobot.m | 41 +-------- .../awt/MouseInfo/GetPointerInfoTest.java | 73 +++++++++++++++ .../awt/MouseInfo/MultiscreenPointerInfo.java | 90 +++++++++++++++++++ 15 files changed, 235 insertions(+), 93 deletions(-) create mode 100644 jdk/test/java/awt/MouseInfo/GetPointerInfoTest.java create mode 100644 jdk/test/java/awt/MouseInfo/MultiscreenPointerInfo.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java index 1920a73d3b0..a507b75a904 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWMouseInfoPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -51,8 +51,12 @@ public class LWMouseInfoPeer implements MouseInfoPeer { return false; } - final Object windowPeer = AWTAccessor.getComponentAccessor().getPeer(w); - return LWWindowPeer.getWindowUnderCursor() == windowPeer; + LWWindowPeer windowPeer = AWTAccessor.getComponentAccessor().getPeer(w); + if (windowPeer == null) { + return false; + } + + return LWToolkit.getLWToolkit().getPlatformWindowUnderMouse() == windowPeer.getPlatformWindow(); } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java index 9aea94cdc6c..4ab5c410830 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -396,6 +396,8 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { return new LWMouseInfoPeer(); } + protected abstract PlatformWindow getPlatformWindowUnderMouse(); + @Override public final PrintJob getPrintJob(Frame frame, String doctitle, Properties props) { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 1db30c021fa..fa6be35ad96 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -749,11 +749,10 @@ public class LWWindowPeer lastMouseEventPeer = targetPeer; } } else { - PlatformWindow topmostPlatforWindow = - platformWindow.getTopmostPlatformWindowUnderMouse(); + PlatformWindow topmostPlatformWindow = LWToolkit.getLWToolkit().getPlatformWindowUnderMouse(); LWWindowPeer topmostWindowPeer = - topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null; + topmostPlatformWindow != null ? topmostPlatformWindow.getPeer() : null; // topmostWindowPeer == null condition is added for the backward // compatibility with applets. It can be removed when the @@ -764,8 +763,7 @@ public class LWWindowPeer screenX, screenY, modifiers, clickCount, popupTrigger, targetPeer); } else { - LWComponentPeer topmostTargetPeer = - topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null; + LWComponentPeer topmostTargetPeer = topmostWindowPeer.findPeerAt(r.x + x, r.y + y); topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, screenX, screenY, modifiers, clickCount, popupTrigger, topmostTargetPeer); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java index 3142aa0c402..93bd1928dbb 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -107,8 +107,6 @@ public interface PlatformWindow { public void setAlwaysOnTop(boolean value); - public PlatformWindow getTopmostPlatformWindowUnderMouse(); - public void updateFocusableWindowState(); public boolean rejectFocusRequest(CausedFocusEvent.Cause cause); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index 0e8b0b0d2ec..f6ab6bbb4ad 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -129,11 +129,6 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { @Override public void setAlwaysOnTop(boolean value) {} - // This method should be properly implemented for applets. - // It returns null just as a stub. - @Override - public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; } - @Override public void updateFocusableWindowState() {} diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java index 9c2edf22742..0d9f9744c41 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -161,11 +161,6 @@ public class CPlatformLWWindow extends CPlatformWindow { public void setAlwaysOnTop(boolean isAlwaysOnTop) { } - @Override - public PlatformWindow getTopmostPlatformWindowUnderMouse(){ - return null; - } - @Override public void setOpacity(float opacity) { } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 949a9a168d9..043c08d5273 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -61,9 +61,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled); private static native void nativeSynthesizeMouseEnteredExitedEvents(); private static native void nativeDispose(long nsWindowPtr); - private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse(); private static native void nativeEnterFullScreenMode(long nsWindowPtr); private static native void nativeExitFullScreenMode(long nsWindowPtr); + static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse(); // Loger to report issues happened during execution but that do not affect functionality private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow"); @@ -750,10 +750,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop); } - public PlatformWindow getTopmostPlatformWindowUnderMouse(){ - return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse(); - } - @Override public void setOpacity(float opacity) { CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java index 0ff5f67955f..e8bdb1fe6c8 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -78,7 +78,7 @@ class CRobot implements RobotPeer { @Override public void mousePress(int buttons) { mouseButtonsState |= buttons; - + checkMousePos(); mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, true, false); } @@ -92,11 +92,40 @@ class CRobot implements RobotPeer { @Override public void mouseRelease(int buttons) { mouseButtonsState &= ~buttons; - + checkMousePos(); mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, false, false); } + /** + * Set unknown mouse location, if needed. + */ + private void checkMousePos() { + if (mouseLastX == MOUSE_LOCATION_UNKNOWN || + mouseLastY == MOUSE_LOCATION_UNKNOWN) { + + Rectangle deviceBounds = fDevice.getDefaultConfiguration().getBounds(); + Point mousePos = CCursorManager.getInstance().getCursorPosition(); + + if (mousePos.x < deviceBounds.x) { + mousePos.x = deviceBounds.x; + } + else if (mousePos.x > deviceBounds.x + deviceBounds.width) { + mousePos.x = deviceBounds.x + deviceBounds.width; + } + + if (mousePos.y < deviceBounds.y) { + mousePos.y = deviceBounds.y; + } + else if (mousePos.y > deviceBounds.y + deviceBounds.height) { + mousePos.y = deviceBounds.y + deviceBounds.height; + } + + mouseLastX = mousePos.x; + mouseLastY = mousePos.y; + } + } + @Override public native void mouseWheel(int wheelAmt); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java index 6c194c75bbd..1c11789713f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -143,11 +143,6 @@ public class CViewPlatformEmbeddedFrame implements PlatformWindow { public void setAlwaysOnTop(boolean value) { } - @Override - public PlatformWindow getTopmostPlatformWindowUnderMouse() { - return null; - } - @Override public void updateFocusableWindowState() { } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 1f9b30ae18f..e2dcd71733b 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -929,4 +929,9 @@ public final class LWCToolkit extends LWToolkit { !path.endsWith("/") && !path.endsWith("."); } + + @Override + protected PlatformWindow getPlatformWindowUnderMouse() { + return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse(); + } } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index 8a7083e0dac..47442027e02 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -1131,15 +1131,16 @@ JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse (JNIEnv *env, jclass clazz) { - jobject topmostWindowUnderMouse = nil; + __block jobject topmostWindowUnderMouse = nil; JNF_COCOA_ENTER(env); - AWT_ASSERT_APPKIT_THREAD; - AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse]; - if (awtWindow != nil) { - topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject]; - } + [ThreadUtilities performOnMainThreadWaiting:YES block:^{ + AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse]; + if (awtWindow != nil) { + topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject]; + } + }]; JNF_COCOA_EXIT(env); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m index e3b9e803980..eaff0e8a671 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -118,13 +118,11 @@ Java_sun_lwawt_macosx_CCursorManager_nativeGetCursorPosition JNF_COCOA_ENTER(env); - __block NSPoint pt = NSZeroPoint; - - [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - pt = ConvertNSScreenPoint(env, [NSEvent mouseLocation]); - }]; - - jpt = NSToJavaPoint(env, pt); + CGEventRef event = CGEventCreate(NULL); + CGPoint globalPos = CGEventGetLocation(event); + CFRelease(event); + + jpt = NSToJavaPoint(env, globalPos); JNF_COCOA_EXIT(env); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m index 8d4f2a052be..7fc6f62ec55 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -146,47 +146,10 @@ Java_sun_lwawt_macosx_CRobot_mouseEvent // This is the native method called when Robot mouse events occur. // The CRobot tracks the mouse position, and which button was - // pressed. If the mouse position is unknown it is obtained from - // CGEvents. The peer also tracks the mouse button desired state, + // pressed. The peer also tracks the mouse button desired state, // the appropriate key modifier state, and whether the mouse action // is simply a mouse move with no mouse button state changes. - CGError err = kCGErrorSuccess; - - CGRect globalDeviceBounds = CGDisplayBounds(displayID); - - // Set unknown mouse location, if needed. - if ((mouseLastX == sun_lwawt_macosx_CRobot_MOUSE_LOCATION_UNKNOWN) || - (mouseLastY == sun_lwawt_macosx_CRobot_MOUSE_LOCATION_UNKNOWN)) - { - CGEventRef event = CGEventCreate(NULL); - if (event == NULL) { - return; - } - - CGPoint globalPos = CGEventGetLocation(event); - CFRelease(event); - - // Normalize the coords within this display device, as - // per Robot rules. - if (globalPos.x < CGRectGetMinX(globalDeviceBounds)) { - globalPos.x = CGRectGetMinX(globalDeviceBounds); - } - else if (globalPos.x > CGRectGetMaxX(globalDeviceBounds)) { - globalPos.x = CGRectGetMaxX(globalDeviceBounds); - } - - if (globalPos.y < CGRectGetMinY(globalDeviceBounds)) { - globalPos.y = CGRectGetMinY(globalDeviceBounds); - } - else if (globalPos.y > CGRectGetMaxY(globalDeviceBounds)) { - globalPos.y = CGRectGetMaxY(globalDeviceBounds); - } - - mouseLastX = (jint)globalPos.x; - mouseLastY = (jint)globalPos.y; - } - // volatile, otherwise it warns that it might be clobbered by 'longjmp' volatile CGPoint point; diff --git a/jdk/test/java/awt/MouseInfo/GetPointerInfoTest.java b/jdk/test/java/awt/MouseInfo/GetPointerInfoTest.java new file mode 100644 index 00000000000..c812cce16eb --- /dev/null +++ b/jdk/test/java/awt/MouseInfo/GetPointerInfoTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 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 + @summary unit test for getPointerInfo() from MouseInfo class + @author dav@sparc.spb.su: area= + @bug 4009555 + @run main GetPointerInfoTest +*/ + +import java.awt.*; + +/** + * Simply check the result on non-null and results are correct. + */ +public class GetPointerInfoTest { + private static final String successStage = "Test stage completed.Passed."; + + public static void main(String[] args) throws Exception { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gds = ge.getScreenDevices(); + int gdslen = gds.length; + System.out.println("There are " + gdslen + " Graphics Devices"); + if (gdslen == 0) { + System.out.println("Nothing to be done."); + return; + } + Robot robot = new Robot(gds[0]); + robot.setAutoDelay(0); + robot.setAutoWaitForIdle(true); + robot.delay(10); + robot.waitForIdle(); + Point p = new Point(101, 99); + robot.mouseMove(p.x, p.y); + + PointerInfo pi = MouseInfo.getPointerInfo(); + if (pi == null) { + throw new RuntimeException("Test failed. getPointerInfo() returned null value."); + } else { + System.out.println(successStage); + } + Point piLocation = pi.getLocation(); + + if (piLocation.x != p.x || piLocation.y != p.y) { + throw new RuntimeException("Test failed.getPointerInfo() returned incorrect result."); + } else { + System.out.println(successStage); + } + + System.out.println("Test PASSED."); + } +} diff --git a/jdk/test/java/awt/MouseInfo/MultiscreenPointerInfo.java b/jdk/test/java/awt/MouseInfo/MultiscreenPointerInfo.java new file mode 100644 index 00000000000..288ab4b0315 --- /dev/null +++ b/jdk/test/java/awt/MouseInfo/MultiscreenPointerInfo.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, 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 + @summary unit test for getPointerInfo() from MouseInfo class + @author prs@sparc.spb.su: area= + @bug 4009555 + @run main MultiscreenPointerInfo +*/ + +import java.awt.*; + +/** + * Simply check the result on non-null and results are correct. + */ +public class MultiscreenPointerInfo +{ + private static final String successStage = "Test stage completed.Passed."; + + public static void main(String[] args) throws Exception { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gds = ge.getScreenDevices(); + int gdslen = gds.length; + System.out.println("There are " + gdslen + " Graphics Devices"); + if (gdslen < 2) { + System.out.println("Nothing to be done. PASSED automatically."); + return; + } + Rectangle rx = gds[1].getDefaultConfiguration().getBounds(); + Robot robot; + + if (rx.x == 0 && rx.y == 0) { + // Assuming independent graphics devices + robot = new Robot(gds[1]); + } else { + // Means we have a virtual device + robot = new Robot(gds[0]); + } + robot.setAutoDelay(0); + robot.setAutoWaitForIdle(true); + robot.delay(10); + robot.waitForIdle(); + Point p = new Point(rx.x + 101, rx.y + 99); + robot.mouseMove(p.x, p.y); + PointerInfo pi = MouseInfo.getPointerInfo(); + if (pi == null) { + throw new RuntimeException("Test failed. getPointerInfo() returned null value."); + } else { + System.out.println(successStage); + } + + Point piLocation = pi.getLocation(); + + if (piLocation.x != p.x || piLocation.y != p.y) { + throw new RuntimeException("Test failed.getPointerInfo() returned incorrect location."); + } else { + System.out.println(successStage); + } + + GraphicsDevice dev = pi.getDevice(); + + if (dev != gds[1]) { + throw new RuntimeException("Test failed.getPointerInfo() returned incorrect device."); + } else { + System.out.println(successStage); + } + System.out.println("Test PASSED."); + } +} From 1c0f1c478fb6731eb1ca94683a0e9e432750c357 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 12 May 2015 09:18:31 +0300 Subject: [PATCH 010/117] 8001470: JTextField's size is computed incorrectly when it contains Indic or Thai characters Reviewed-by: serb, alexsch --- .../javax/swing/plaf/basic/BasicTextUI.java | 4 +- .../basic/BasicTextUI/8001470/bug8001470.java | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 0a04b314218..3b38e77d94d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -939,7 +939,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) { rootView.setSize(d.width - i.left - i.right, d.height - i.top - i.bottom); } - else if (d.width == 0 && d.height == 0) { + else if (d.width == 0 || d.height == 0) { // Probably haven't been layed out yet, force some sort of // initial sizing. rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); diff --git a/jdk/test/javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java b/jdk/test/javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java new file mode 100644 index 00000000000..a63a769a9cb --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 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 8001470 + @summary JTextField's size is computed incorrectly when it contains Indic or Thai characters + @author Semyon Sadetsky + */ + +import javax.swing.*; +import java.awt.*; + +public class bug8001470 { + + private static JFrame frame; + private static JTextField textField1; + private static JTextField textField2; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame("JTextField Test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JPanel container = (JPanel) frame.getContentPane(); + container.setLayout(new GridLayout(2,1)); + + textField1 = new JTextField("\u0e01"); + textField2 = new JTextField("\u0c01"); + + container.add(textField1); + container.add(textField2); + frame.setVisible(true); + frame.pack(); + } + }); + if( textField1.getHeight() < 10 || textField2.getHeight() < 10 ) + throw new Exception("Wrong field height"); + System.out.println("ok"); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } +} From 11215eaec0ee3b14be940f0bfb80983ac495999f Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 12 May 2015 09:22:53 +0300 Subject: [PATCH 011/117] 8078483: Apparent endless loop running JEditorPanePaintTest Reviewed-by: serb, alexsch --- .../share/classes/javax/swing/plaf/basic/BasicTextUI.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 3b38e77d94d..1567a76c4c4 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -936,8 +936,9 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { ((AbstractDocument)doc).readLock(); } try { - if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) { - rootView.setSize(d.width - i.left - i.right, d.height - i.top - i.bottom); + if ((d.width > (i.left + i.right + caretMargin)) && (d.height > (i.top + i.bottom))) { + rootView.setSize(d.width - i.left - i.right - + caretMargin, d.height - i.top - i.bottom); } else if (d.width == 0 || d.height == 0) { // Probably haven't been layed out yet, force some sort of From 93d1573c5ed2dd9307253688eb2ab2a8b28d31cc Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 3 Jun 2015 15:02:10 -0700 Subject: [PATCH 012/117] 8081778: Use Intel x64 CPU instructions for RSA acceleration Add intrinsics for BigInteger squareToLen and mulAdd methods. Reviewed-by: kvn, jrose --- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 20 + hotspot/src/cpu/x86/vm/assembler_x86.hpp | 3 + hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 497 ++++++++++++++++++ hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 19 + .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 107 ++++ .../src/cpu/x86/vm/stubRoutines_x86_64.hpp | 2 +- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 18 + hotspot/src/share/vm/classfile/vmSymbols.hpp | 8 + hotspot/src/share/vm/opto/c2_globals.hpp | 6 + hotspot/src/share/vm/opto/escape.cpp | 4 +- hotspot/src/share/vm/opto/library_call.cpp | 110 ++++ hotspot/src/share/vm/opto/runtime.cpp | 42 ++ hotspot/src/share/vm/opto/runtime.hpp | 4 + hotspot/src/share/vm/runtime/stubRoutines.cpp | 2 + hotspot/src/share/vm/runtime/stubRoutines.hpp | 4 + hotspot/src/share/vm/runtime/vmStructs.cpp | 2 + .../intrinsics/muladd/TestMulAdd.java | 117 +++++ .../squaretolen/TestSquareToLen.java | 114 ++++ 18 files changed, 1077 insertions(+), 2 deletions(-) create mode 100644 hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java create mode 100644 hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index b6f92e8730e..7844b15a778 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -2813,6 +2813,13 @@ void Assembler::orl(Register dst, Register src) { emit_arith(0x0B, 0xC0, dst, src); } +void Assembler::orl(Address dst, Register src) { + InstructionMark im(this); + prefix(dst, src); + emit_int8(0x09); + emit_operand(src, dst); +} + void Assembler::packuswb(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); @@ -6907,6 +6914,19 @@ void Assembler::rclq(Register dst, int imm8) { } } +void Assembler::rcrq(Register dst, int imm8) { + assert(isShiftCount(imm8 >> 1), "illegal shift count"); + int encode = prefixq_and_encode(dst->encoding()); + if (imm8 == 1) { + emit_int8((unsigned char)0xD1); + emit_int8((unsigned char)(0xD8 | encode)); + } else { + emit_int8((unsigned char)0xC1); + emit_int8((unsigned char)(0xD8 | encode)); + emit_int8(imm8); + } +} + void Assembler::rorq(Register dst, int imm8) { assert(isShiftCount(imm8 >> 1), "illegal shift count"); int encode = prefixq_and_encode(dst->encoding()); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 32619735400..f3d8410c200 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1594,6 +1594,7 @@ private: void orl(Register dst, int32_t imm32); void orl(Register dst, Address src); void orl(Register dst, Register src); + void orl(Address dst, Register src); void orq(Address dst, int32_t imm32); void orq(Register dst, int32_t imm32); @@ -1694,6 +1695,8 @@ private: void rclq(Register dst, int imm8); + void rcrq(Register dst, int imm8); + void rdtsc(); void ret(int imm16); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index d172a467f3c..599d905648f 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -7750,6 +7750,503 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi pop(tmp2); pop(tmp1); } + +//Helper functions for square_to_len() + +/** + * Store the squares of x[], right shifted one bit (divided by 2) into z[] + * Preserves x and z and modifies rest of the registers. + */ + +void MacroAssembler::square_rshift(Register x, Register xlen, Register z, Register tmp1, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + // Perform square and right shift by 1 + // Handle odd xlen case first, then for even xlen do the following + // jlong carry = 0; + // for (int j=0, i=0; j < xlen; j+=2, i+=4) { + // huge_128 product = x[j:j+1] * x[j:j+1]; + // z[i:i+1] = (carry << 63) | (jlong)(product >>> 65); + // z[i+2:i+3] = (jlong)(product >>> 1); + // carry = (jlong)product; + // } + + xorq(tmp5, tmp5); // carry + xorq(rdxReg, rdxReg); + xorl(tmp1, tmp1); // index for x + xorl(tmp4, tmp4); // index for z + + Label L_first_loop, L_first_loop_exit; + + testl(xlen, 1); + jccb(Assembler::zero, L_first_loop); //jump if xlen is even + + // Square and right shift by 1 the odd element using 32 bit multiply + movl(raxReg, Address(x, tmp1, Address::times_4, 0)); + imulq(raxReg, raxReg); + shrq(raxReg, 1); + adcq(tmp5, 0); + movq(Address(z, tmp4, Address::times_4, 0), raxReg); + incrementl(tmp1); + addl(tmp4, 2); + + // Square and right shift by 1 the rest using 64 bit multiply + bind(L_first_loop); + cmpptr(tmp1, xlen); + jccb(Assembler::equal, L_first_loop_exit); + + // Square + movq(raxReg, Address(x, tmp1, Address::times_4, 0)); + rorq(raxReg, 32); // convert big-endian to little-endian + mulq(raxReg); // 64-bit multiply rax * rax -> rdx:rax + + // Right shift by 1 and save carry + shrq(tmp5, 1); // rdx:rax:tmp5 = (tmp5:rdx:rax) >>> 1 + rcrq(rdxReg, 1); + rcrq(raxReg, 1); + adcq(tmp5, 0); + + // Store result in z + movq(Address(z, tmp4, Address::times_4, 0), rdxReg); + movq(Address(z, tmp4, Address::times_4, 8), raxReg); + + // Update indices for x and z + addl(tmp1, 2); + addl(tmp4, 4); + jmp(L_first_loop); + + bind(L_first_loop_exit); +} + + +/** + * Perform the following multiply add operation using BMI2 instructions + * carry:sum = sum + op1*op2 + carry + * op2 should be in rdx + * op2 is preserved, all other registers are modified + */ +void MacroAssembler::multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, Register tmp2) { + // assert op2 is rdx + mulxq(tmp2, op1, op1); // op1 * op2 -> tmp2:op1 + addq(sum, carry); + adcq(tmp2, 0); + addq(sum, op1); + adcq(tmp2, 0); + movq(carry, tmp2); +} + +/** + * Perform the following multiply add operation: + * carry:sum = sum + op1*op2 + carry + * Preserves op1, op2 and modifies rest of registers + */ +void MacroAssembler::multiply_add_64(Register sum, Register op1, Register op2, Register carry, Register rdxReg, Register raxReg) { + // rdx:rax = op1 * op2 + movq(raxReg, op2); + mulq(op1); + + // rdx:rax = sum + carry + rdx:rax + addq(sum, carry); + adcq(rdxReg, 0); + addq(sum, raxReg); + adcq(rdxReg, 0); + + // carry:sum = rdx:sum + movq(carry, rdxReg); +} + +/** + * Add 64 bit long carry into z[] with carry propogation. + * Preserves z and carry register values and modifies rest of registers. + * + */ +void MacroAssembler::add_one_64(Register z, Register zlen, Register carry, Register tmp1) { + Label L_fourth_loop, L_fourth_loop_exit; + + movl(tmp1, 1); + subl(zlen, 2); + addq(Address(z, zlen, Address::times_4, 0), carry); + + bind(L_fourth_loop); + jccb(Assembler::carryClear, L_fourth_loop_exit); + subl(zlen, 2); + jccb(Assembler::negative, L_fourth_loop_exit); + addq(Address(z, zlen, Address::times_4, 0), tmp1); + jmp(L_fourth_loop); + bind(L_fourth_loop_exit); +} + +/** + * Shift z[] left by 1 bit. + * Preserves x, len, z and zlen registers and modifies rest of the registers. + * + */ +void MacroAssembler::lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4) { + + Label L_fifth_loop, L_fifth_loop_exit; + + // Fifth loop + // Perform primitiveLeftShift(z, zlen, 1) + + const Register prev_carry = tmp1; + const Register new_carry = tmp4; + const Register value = tmp2; + const Register zidx = tmp3; + + // int zidx, carry; + // long value; + // carry = 0; + // for (zidx = zlen-2; zidx >=0; zidx -= 2) { + // (carry:value) = (z[i] << 1) | carry ; + // z[i] = value; + // } + + movl(zidx, zlen); + xorl(prev_carry, prev_carry); // clear carry flag and prev_carry register + + bind(L_fifth_loop); + decl(zidx); // Use decl to preserve carry flag + decl(zidx); + jccb(Assembler::negative, L_fifth_loop_exit); + + if (UseBMI2Instructions) { + movq(value, Address(z, zidx, Address::times_4, 0)); + rclq(value, 1); + rorxq(value, value, 32); + movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form + } + else { + // clear new_carry + xorl(new_carry, new_carry); + + // Shift z[i] by 1, or in previous carry and save new carry + movq(value, Address(z, zidx, Address::times_4, 0)); + shlq(value, 1); + adcl(new_carry, 0); + + orq(value, prev_carry); + rorq(value, 0x20); + movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form + + // Set previous carry = new carry + movl(prev_carry, new_carry); + } + jmp(L_fifth_loop); + + bind(L_fifth_loop_exit); +} + + +/** + * Code for BigInteger::squareToLen() intrinsic + * + * rdi: x + * rsi: len + * r8: z + * rcx: zlen + * r12: tmp1 + * r13: tmp2 + * r14: tmp3 + * r15: tmp4 + * rbx: tmp5 + * + */ +void MacroAssembler::square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_second_loop, L_second_loop_exit, L_third_loop, L_third_loop_exit, fifth_loop, fifth_loop_exit, L_last_x, L_multiply; + push(tmp1); + push(tmp2); + push(tmp3); + push(tmp4); + push(tmp5); + + // First loop + // Store the squares, right shifted one bit (i.e., divided by 2). + square_rshift(x, len, z, tmp1, tmp3, tmp4, tmp5, rdxReg, raxReg); + + // Add in off-diagonal sums. + // + // Second, third (nested) and fourth loops. + // zlen +=2; + // for (int xidx=len-2,zidx=zlen-4; xidx > 0; xidx-=2,zidx-=4) { + // carry = 0; + // long op2 = x[xidx:xidx+1]; + // for (int j=xidx-2,k=zidx; j >= 0; j-=2) { + // k -= 2; + // long op1 = x[j:j+1]; + // long sum = z[k:k+1]; + // carry:sum = multiply_add_64(sum, op1, op2, carry, tmp_regs); + // z[k:k+1] = sum; + // } + // add_one_64(z, k, carry, tmp_regs); + // } + + const Register carry = tmp5; + const Register sum = tmp3; + const Register op1 = tmp4; + Register op2 = tmp2; + + push(zlen); + push(len); + addl(zlen,2); + bind(L_second_loop); + xorq(carry, carry); + subl(zlen, 4); + subl(len, 2); + push(zlen); + push(len); + cmpl(len, 0); + jccb(Assembler::lessEqual, L_second_loop_exit); + + // Multiply an array by one 64 bit long. + if (UseBMI2Instructions) { + op2 = rdxReg; + movq(op2, Address(x, len, Address::times_4, 0)); + rorxq(op2, op2, 32); + } + else { + movq(op2, Address(x, len, Address::times_4, 0)); + rorq(op2, 32); + } + + bind(L_third_loop); + decrementl(len); + jccb(Assembler::negative, L_third_loop_exit); + decrementl(len); + jccb(Assembler::negative, L_last_x); + + movq(op1, Address(x, len, Address::times_4, 0)); + rorq(op1, 32); + + bind(L_multiply); + subl(zlen, 2); + movq(sum, Address(z, zlen, Address::times_4, 0)); + + // Multiply 64 bit by 64 bit and add 64 bits lower half and upper 64 bits as carry. + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, tmp2); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + + movq(Address(z, zlen, Address::times_4, 0), sum); + + jmp(L_third_loop); + bind(L_third_loop_exit); + + // Fourth loop + // Add 64 bit long carry into z with carry propogation. + // Uses offsetted zlen. + add_one_64(z, zlen, carry, tmp1); + + pop(len); + pop(zlen); + jmp(L_second_loop); + + // Next infrequent code is moved outside loops. + bind(L_last_x); + movl(op1, Address(x, 0)); + jmp(L_multiply); + + bind(L_second_loop_exit); + pop(len); + pop(zlen); + pop(len); + pop(zlen); + + // Fifth loop + // Shift z left 1 bit. + lshift_by_1(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4); + + // z[zlen-1] |= x[len-1] & 1; + movl(tmp3, Address(x, len, Address::times_4, -4)); + andl(tmp3, 1); + orl(Address(z, zlen, Address::times_4, -4), tmp3); + + pop(tmp5); + pop(tmp4); + pop(tmp3); + pop(tmp2); + pop(tmp1); +} + +/** + * Helper function for mul_add() + * Multiply the in[] by int k and add to out[] starting at offset offs using + * 128 bit by 32 bit multiply and return the carry in tmp5. + * Only quad int aligned length of in[] is operated on in this function. + * k is in rdxReg for BMI2Instructions, for others it is in tmp2. + * This function preserves out, in and k registers. + * len and offset point to the appropriate index in "in" & "out" correspondingly + * tmp5 has the carry. + * other registers are temporary and are modified. + * + */ +void MacroAssembler::mul_add_128_x_32_loop(Register out, Register in, + Register offset, Register len, Register tmp1, Register tmp2, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_first_loop, L_first_loop_exit; + + movl(tmp1, len); + shrl(tmp1, 2); + + bind(L_first_loop); + subl(tmp1, 1); + jccb(Assembler::negative, L_first_loop_exit); + + subl(len, 4); + subl(offset, 4); + + Register op2 = tmp2; + const Register sum = tmp3; + const Register op1 = tmp4; + const Register carry = tmp5; + + if (UseBMI2Instructions) { + op2 = rdxReg; + } + + movq(op1, Address(in, len, Address::times_4, 8)); + rorq(op1, 32); + movq(sum, Address(out, offset, Address::times_4, 8)); + rorq(sum, 32); + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offset, Address::times_4, 8), sum); + + movq(op1, Address(in, len, Address::times_4, 0)); + rorq(op1, 32); + movq(sum, Address(out, offset, Address::times_4, 0)); + rorq(sum, 32); + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offset, Address::times_4, 0), sum); + + jmp(L_first_loop); + bind(L_first_loop_exit); +} + +/** + * Code for BigInteger::mulAdd() intrinsic + * + * rdi: out + * rsi: in + * r11: offs (out.length - offset) + * rcx: len + * r8: k + * r12: tmp1 + * r13: tmp2 + * r14: tmp3 + * r15: tmp4 + * rbx: tmp5 + * Multiply the in[] by word k and add to out[], return the carry in rax + */ +void MacroAssembler::mul_add(Register out, Register in, Register offs, + Register len, Register k, Register tmp1, Register tmp2, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_carry, L_last_in, L_done; + +// carry = 0; +// for (int j=len-1; j >= 0; j--) { +// long product = (in[j] & LONG_MASK) * kLong + +// (out[offs] & LONG_MASK) + carry; +// out[offs--] = (int)product; +// carry = product >>> 32; +// } +// + push(tmp1); + push(tmp2); + push(tmp3); + push(tmp4); + push(tmp5); + + Register op2 = tmp2; + const Register sum = tmp3; + const Register op1 = tmp4; + const Register carry = tmp5; + + if (UseBMI2Instructions) { + op2 = rdxReg; + movl(op2, k); + } + else { + movl(op2, k); + } + + xorq(carry, carry); + + //First loop + + //Multiply in[] by k in a 4 way unrolled loop using 128 bit by 32 bit multiply + //The carry is in tmp5 + mul_add_128_x_32_loop(out, in, offs, len, tmp1, tmp2, tmp3, tmp4, tmp5, rdxReg, raxReg); + + //Multiply the trailing in[] entry using 64 bit by 32 bit, if any + decrementl(len); + jccb(Assembler::negative, L_carry); + decrementl(len); + jccb(Assembler::negative, L_last_in); + + movq(op1, Address(in, len, Address::times_4, 0)); + rorq(op1, 32); + + subl(offs, 2); + movq(sum, Address(out, offs, Address::times_4, 0)); + rorq(sum, 32); + + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offs, Address::times_4, 0), sum); + + testl(len, len); + jccb(Assembler::zero, L_carry); + + //Multiply the last in[] entry, if any + bind(L_last_in); + movl(op1, Address(in, 0)); + movl(sum, Address(out, offs, Address::times_4, -4)); + + movl(raxReg, k); + mull(op1); //tmp4 * eax -> edx:eax + addl(sum, carry); + adcl(rdxReg, 0); + addl(sum, raxReg); + adcl(rdxReg, 0); + movl(carry, rdxReg); + + movl(Address(out, offs, Address::times_4, -4), sum); + + bind(L_carry); + //return tmp5/carry as carry in rax + movl(rax, carry); + + bind(L_done); + pop(tmp5); + pop(tmp4); + pop(tmp3); + pop(tmp2); + pop(tmp1); +} #endif /** diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index ad75e27ddd9..025456eeaf5 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1241,6 +1241,25 @@ public: Register carry2); void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5); + + void square_rshift(Register x, Register len, Register z, Register tmp1, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg); + void multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, + Register tmp2); + void multiply_add_64(Register sum, Register op1, Register op2, Register carry, + Register rdxReg, Register raxReg); + void add_one_64(Register z, Register zlen, Register carry, Register tmp1); + void lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, + Register tmp3, Register tmp4); + void square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, + Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg); + + void mul_add_128_x_32_loop(Register out, Register in, Register offset, Register len, Register tmp1, + Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, + Register raxReg); + void mul_add(Register out, Register in, Register offset, Register len, Register k, Register tmp1, + Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, + Register raxReg); #endif // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic. diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index e52da3ec6b6..ffcb7696114 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3785,6 +3785,107 @@ class StubGenerator: public StubCodeGenerator { return start; } +/** + * Arguments: + * + // Input: + // c_rarg0 - x address + // c_rarg1 - x length + // c_rarg2 - z address + // c_rarg3 - z lenth + * + */ + address generate_squareToLen() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "squareToLen"); + + address start = __ pc(); + // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) + // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...) + const Register x = rdi; + const Register len = rsi; + const Register z = r8; + const Register zlen = rcx; + + const Register tmp1 = r12; + const Register tmp2 = r13; + const Register tmp3 = r14; + const Register tmp4 = r15; + const Register tmp5 = rbx; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + setup_arg_regs(4); // x => rdi, len => rsi, z => rdx + // zlen => rcx + // r9 and r10 may be used to save non-volatile registers + __ movptr(r8, rdx); + __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax); + + restore_arg_regs(); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + } + + /** + * Arguments: + * + * Input: + * c_rarg0 - out address + * c_rarg1 - in address + * c_rarg2 - offset + * c_rarg3 - len + * not Win64 + * c_rarg4 - k + * Win64 + * rsp+40 - k + */ + address generate_mulAdd() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "mulAdd"); + + address start = __ pc(); + // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) + // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...) + const Register out = rdi; + const Register in = rsi; + const Register offset = r11; + const Register len = rcx; + const Register k = r8; + + // Next registers will be saved on stack in mul_add(). + const Register tmp1 = r12; + const Register tmp2 = r13; + const Register tmp3 = r14; + const Register tmp4 = r15; + const Register tmp5 = rbx; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx + // len => rcx, k => r8 + // r9 and r10 may be used to save non-volatile registers +#ifdef _WIN64 + // last argument is on stack on Win64 + __ movl(k, Address(rsp, 6 * wordSize)); +#endif + __ movptr(r11, rdx); // move offset in rdx to offset(r11) + __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax); + + restore_arg_regs(); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + } + + #undef __ #define __ masm-> @@ -4030,6 +4131,12 @@ class StubGenerator: public StubCodeGenerator { if (UseMultiplyToLenIntrinsic) { StubRoutines::_multiplyToLen = generate_multiplyToLen(); } + if (UseSquareToLenIntrinsic) { + StubRoutines::_squareToLen = generate_squareToLen(); + } + if (UseMulAddIntrinsic) { + StubRoutines::_mulAdd = generate_mulAdd(); + } #endif } diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp index 205bce4eb76..15922b8aedc 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp @@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _ enum platform_dependent_constants { code_size1 = 19000, // simply increase if too small (assembler will crash if too small) - code_size2 = 22000 // simply increase if too small (assembler will crash if too small) + code_size2 = 23000 // simply increase if too small (assembler will crash if too small) }; class x86 { diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index e09a13af3b7..7a8f6c11969 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -790,6 +790,12 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } + if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + UseSquareToLenIntrinsic = true; + } + if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + UseMulAddIntrinsic = true; + } #else if (UseMultiplyToLenIntrinsic) { if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { @@ -797,6 +803,18 @@ void VM_Version::get_processor_features() { } FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); } + if (UseSquareToLenIntrinsic) { + if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + warning("squareToLen intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false); + } + if (UseMulAddIntrinsic) { + if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + warning("mulAdd intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseMulAddIntrinsic, false); + } #endif #endif // COMPILER2 diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index c2548215b6f..d2a85e84492 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -799,6 +799,14 @@ do_name( multiplyToLen_name, "multiplyToLen") \ do_signature(multiplyToLen_signature, "([II[II[I)[I") \ \ + do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ + do_name( squareToLen_name, "implSquareToLen") \ + do_signature(squareToLen_signature, "([II[II)[I") \ + \ + do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \ + do_name( mulAdd_name, "implMulAdd") \ + do_signature(mulAdd_signature, "([I[IIII)I") \ + \ /* java/lang/ref/Reference */ \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ \ diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 2acc7911ca4..bee4830f9b3 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -665,6 +665,12 @@ product(bool, UseMultiplyToLenIntrinsic, false, \ "Enables intrinsification of BigInteger.multiplyToLen()") \ \ + product(bool, UseSquareToLenIntrinsic, false, \ + "Enables intrinsification of BigInteger.squareToLen()") \ + \ + product(bool, UseMulAddIntrinsic, false, \ + "Enables intrinsification of BigInteger.mulAdd()") \ + \ product(bool, UseTypeSpeculation, true, \ "Speculatively propagate types from profiles") \ \ diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 67b49117aaf..9496776a5c6 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -972,7 +972,9 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 || - strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0) + strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 || + strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 || + strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0) ))) { call->dump(); fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name)); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 9d838252f3b..83a1673aa74 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -291,6 +291,8 @@ class LibraryCallKit : public GraphKit { bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); bool inline_multiplyToLen(); + bool inline_squareToLen(); + bool inline_mulAdd(); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -494,6 +496,14 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { if (!UseMultiplyToLenIntrinsic) return NULL; break; + case vmIntrinsics::_squareToLen: + if (!UseSquareToLenIntrinsic) return NULL; + break; + + case vmIntrinsics::_mulAdd: + if (!UseMulAddIntrinsic) return NULL; + break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: if (!UseAESIntrinsics) return NULL; @@ -913,6 +923,12 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_multiplyToLen: return inline_multiplyToLen(); + case vmIntrinsics::_squareToLen: + return inline_squareToLen(); + + case vmIntrinsics::_mulAdd: + return inline_mulAdd(); + case vmIntrinsics::_encodeISOArray: return inline_encodeISOArray(); @@ -5306,6 +5322,100 @@ bool LibraryCallKit::inline_multiplyToLen() { return true; } +//-------------inline_squareToLen------------------------------------ +bool LibraryCallKit::inline_squareToLen() { + assert(UseSquareToLenIntrinsic, "not implementated on this platform"); + + address stubAddr = StubRoutines::squareToLen(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + const char* stubName = "squareToLen"; + + assert(callee()->signature()->size() == 4, "implSquareToLen has 4 parameters"); + + Node* x = argument(0); + Node* len = argument(1); + Node* z = argument(2); + Node* zlen = argument(3); + + const Type* x_type = x->Value(&_gvn); + const Type* z_type = z->Value(&_gvn); + const TypeAryPtr* top_x = x_type->isa_aryptr(); + const TypeAryPtr* top_z = z_type->isa_aryptr(); + if (top_x == NULL || top_x->klass() == NULL || + top_z == NULL || top_z->klass() == NULL) { + // failed array check + return false; + } + + BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (x_elem != T_INT || z_elem != T_INT) { + return false; + } + + + Node* x_start = array_element_address(x, intcon(0), x_elem); + Node* z_start = array_element_address(z, intcon(0), z_elem); + + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::squareToLen_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + x_start, len, z_start, zlen); + + set_result(z); + return true; +} + +//-------------inline_mulAdd------------------------------------------ +bool LibraryCallKit::inline_mulAdd() { + assert(UseMulAddIntrinsic, "not implementated on this platform"); + + address stubAddr = StubRoutines::mulAdd(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + const char* stubName = "mulAdd"; + + assert(callee()->signature()->size() == 5, "mulAdd has 5 parameters"); + + Node* out = argument(0); + Node* in = argument(1); + Node* offset = argument(2); + Node* len = argument(3); + Node* k = argument(4); + + const Type* out_type = out->Value(&_gvn); + const Type* in_type = in->Value(&_gvn); + const TypeAryPtr* top_out = out_type->isa_aryptr(); + const TypeAryPtr* top_in = in_type->isa_aryptr(); + if (top_out == NULL || top_out->klass() == NULL || + top_in == NULL || top_in->klass() == NULL) { + // failed array check + return false; + } + + BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (out_elem != T_INT || in_elem != T_INT) { + return false; + } + + Node* outlen = load_array_length(out); + Node* new_offset = _gvn.transform(new SubINode(outlen, offset)); + Node* out_start = array_element_address(out, intcon(0), out_elem); + Node* in_start = array_element_address(in, intcon(0), in_elem); + + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::mulAdd_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + out_start,in_start, new_offset, len, k); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + /** * Calculate CRC32 for byte. diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index ca5e5af7833..9806ad62483 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -945,6 +945,48 @@ const TypeFunc* OptoRuntime::multiplyToLen_Type() { return TypeFunc::make(domain, range); } +const TypeFunc* OptoRuntime::squareToLen_Type() { + // create input type (domain) + int num_args = 4; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // x + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypePtr::NOTNULL; // z + fields[argp++] = TypeInt::INT; // zlen + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // no result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = NULL; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + +// for mulAdd calls, 2 pointers and 3 ints, returning int +const TypeFunc* OptoRuntime::mulAdd_Type() { + // create input type (domain) + int num_args = 5; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // out + fields[argp++] = TypePtr::NOTNULL; // in + fields[argp++] = TypeInt::INT; // offset + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypeInt::INT; // k + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // returning carry (int) + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields); + return TypeFunc::make(domain, range); +} + //------------- Interpreter state access for on stack replacement diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp index aa08b657e05..3f2a73039c8 100644 --- a/hotspot/src/share/vm/opto/runtime.hpp +++ b/hotspot/src/share/vm/opto/runtime.hpp @@ -312,6 +312,10 @@ private: static const TypeFunc* multiplyToLen_Type(); + static const TypeFunc* squareToLen_Type(); + + static const TypeFunc* mulAdd_Type(); + static const TypeFunc* updateBytesCRC32_Type(); // leaf on stack replacement interpreter accessor types diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index aac4353837d..66ec5e99566 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -137,6 +137,8 @@ address StubRoutines::_updateBytesCRC32 = NULL; address StubRoutines::_crc_table_adr = NULL; address StubRoutines::_multiplyToLen = NULL; +address StubRoutines::_squareToLen = NULL; +address StubRoutines::_mulAdd = NULL; double (* StubRoutines::_intrinsic_log )(double) = NULL; double (* StubRoutines::_intrinsic_log10 )(double) = NULL; diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 619b3b45b42..56376b6cedd 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -197,6 +197,8 @@ class StubRoutines: AllStatic { static address _crc_table_adr; static address _multiplyToLen; + static address _squareToLen; + static address _mulAdd; // These are versions of the java.lang.Math methods which perform // the same operations as the intrinsic version. They are used for @@ -356,6 +358,8 @@ class StubRoutines: AllStatic { static address crc_table_addr() { return _crc_table_adr; } static address multiplyToLen() {return _multiplyToLen; } + static address squareToLen() {return _squareToLen; } + static address mulAdd() {return _mulAdd; } static address select_fill_function(BasicType t, bool aligned, const char* &name); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index bd7ad14dab9..3f8c7ea8f7b 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -831,6 +831,8 @@ typedef CompactHashtable SymbolCompactHashTable; static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _multiplyToLen, address) \ + static_field(StubRoutines, _squareToLen, address) \ + static_field(StubRoutines, _mulAdd, address) \ \ /*****************/ \ /* SharedRuntime */ \ diff --git a/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java new file mode 100644 index 00000000000..4d7b274c284 --- /dev/null +++ b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 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 8081778 + * @summary Add C2 x86 intrinsic for BigInteger::mulAdd() method + * + * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch + * -XX:+IgnoreUnrecognizedVMOptions -XX:-UseSquareToLenIntrinsic -XX:-UseMultiplyToLenIntrinsic + * -XX:CompileCommand=dontinline,TestMulAdd::main + * -XX:CompileCommand=option,TestMulAdd::base_multiply,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::mulAdd,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=inline,java.math.BigInteger::multiply + * -XX:CompileCommand=inline,java.math.BigInteger::square + * -XX:CompileCommand=inline,java.math.BigInteger::squareToLen + * -XX:CompileCommand=inline,java.math.BigInteger::mulAdd TestMulAdd + */ + +import java.util.Random; +import java.math.*; + +public class TestMulAdd { + + // Avoid intrinsic by preventing inlining multiply() and mulAdd(). + public static BigInteger base_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + // Generate mulAdd() intrinsic by inlining multiply(). + public static BigInteger new_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + public static boolean bytecompare(BigInteger b1, BigInteger b2) { + byte[] data1 = b1.toByteArray(); + byte[] data2 = b2.toByteArray(); + if (data1.length != data2.length) + return false; + for (int i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) + return false; + } + return true; + } + + public static String stringify(BigInteger b) { + String strout= ""; + byte [] data = b.toByteArray(); + for (int i = 0; i < data.length; i++) { + strout += (String.format("%02x",data[i]) + " "); + } + return strout; + } + + public static void main(String args[]) throws Exception { + + BigInteger oldsum = new BigInteger("0"); + BigInteger newsum = new BigInteger("0"); + + BigInteger b1, b2, oldres, newres; + + Random rand = new Random(); + long seed = System.nanoTime(); + Random rand1 = new Random(); + long seed1 = System.nanoTime(); + rand.setSeed(seed); + rand1.setSeed(seed1); + + for (int j = 0; j < 100000; j++) { + int rand_int = rand1.nextInt(3136)+32; + b1 = new BigInteger(rand_int, rand); + + oldres = base_multiply(b1); + newres = new_multiply(b1); + + oldsum = oldsum.add(oldres); + newsum = newsum.add(newres); + + if (!bytecompare(oldres,newres)) { + System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres)); + System.out.println(b1); + throw new Exception("Failed"); + } + } + if (!bytecompare(oldsum,newsum)) { + System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum)); + throw new Exception("Failed"); + } else { + System.out.println("Success"); + } + } +} diff --git a/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java new file mode 100644 index 00000000000..79ebbe3af2a --- /dev/null +++ b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 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 8081778 + * @summary Add C2 x86 intrinsic for BigInteger::squareToLen() method + * + * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch + * -XX:CompileCommand=exclude,TestSquareToLen::main + * -XX:CompileCommand=option,TestSquareToLen::base_multiply,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=inline,java.math.BigInteger::multiply + * -XX:CompileCommand=inline,java.math.BigInteger::square + * -XX:CompileCommand=inline,java.math.BigInteger::squareToLen TestSquareToLen + */ + +import java.util.Random; +import java.math.*; + +public class TestSquareToLen { + + // Avoid intrinsic by preventing inlining multiply() and squareToLen(). + public static BigInteger base_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + // Generate squareToLen() intrinsic by inlining multiply(). + public static BigInteger new_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + public static boolean bytecompare(BigInteger b1, BigInteger b2) { + byte[] data1 = b1.toByteArray(); + byte[] data2 = b2.toByteArray(); + if (data1.length != data2.length) + return false; + for (int i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) + return false; + } + return true; + } + + public static String stringify(BigInteger b) { + String strout= ""; + byte [] data = b.toByteArray(); + for (int i = 0; i < data.length; i++) { + strout += (String.format("%02x",data[i]) + " "); + } + return strout; + } + + public static void main(String args[]) throws Exception { + + BigInteger oldsum = new BigInteger("0"); + BigInteger newsum = new BigInteger("0"); + + BigInteger b1, b2, oldres, newres; + + Random rand = new Random(); + long seed = System.nanoTime(); + Random rand1 = new Random(); + long seed1 = System.nanoTime(); + rand.setSeed(seed); + rand1.setSeed(seed1); + + for (int j = 0; j < 100000; j++) { + int rand_int = rand1.nextInt(3136)+32; + b1 = new BigInteger(rand_int, rand); + + oldres = base_multiply(b1); + newres = new_multiply(b1); + + oldsum = oldsum.add(oldres); + newsum = newsum.add(newres); + + if (!bytecompare(oldres,newres)) { + System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres)); + System.out.println(b1); + throw new Exception("Failed"); + } + } + if (!bytecompare(oldsum,newsum)) { + System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum)); + throw new Exception("Failed"); + } else { + System.out.println("Success"); + } + } +} From 0fb315714c4fb4425b881743ae69ed47f9f704e2 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 4 Jun 2015 16:19:22 +0200 Subject: [PATCH 013/117] 8078866: compiler/eliminateAutobox/6934604/TestIntBoxing.java assert(p_f->Opcode() == Op_IfFalse) failed Bail out from range check elimination if pre loop is not found Reviewed-by: kvn --- hotspot/src/share/vm/opto/loopTransform.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index c9c033868fc..b2d0f6ba420 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1914,7 +1914,10 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { // Find the pre-loop limit; we will expand it's iterations to // not ever trip low tests. Node *p_f = iffm->in(0); - assert(p_f->Opcode() == Op_IfFalse, ""); + // pre loop may have been optimized out + if (p_f->Opcode() != Op_IfFalse) { + return; + } CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); assert(pre_end->loopnode()->is_pre_loop(), ""); Node *pre_opaq1 = pre_end->limit(); From 197ecf9bc10ae9907e84db855452dd2356d6cff9 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 8 Jun 2015 18:35:17 +0200 Subject: [PATCH 014/117] 8081823: C2 performs unsigned comparison against -1 X <= 0 || x > 0 wrongly folded as (x-1) >u -1 Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/opto/ifnode.cpp | 73 +++++++++++++- .../rangechecks/TestBadFoldCompare.java | 94 +++++++++++++++++++ 2 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/compiler/rangechecks/TestBadFoldCompare.java diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index aad3039d0ef..bc107f4b7d5 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -817,19 +817,78 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f BoolTest::mask hi_test = this_bool->_test._test; BoolTest::mask cond = hi_test; + // convert: + // + // dom_bool = x {<,<=,>,>=} a + // / \ + // proj = {True,False} / \ otherproj = {False,True} + // / + // this_bool = x {<,<=} b + // / \ + // fail = {True,False} / \ success = {False,True} + // / + // + // (Second test guaranteed canonicalized, first one may not have + // been canonicalized yet) + // + // into: + // + // cond = (x - lo) {u,>=u} adjusted_lim + // / \ + // fail / \ success + // / + // + // Figure out which of the two tests sets the upper bound and which // sets the lower bound if any. + Node* adjusted_lim = NULL; if (hi_type->_lo > lo_type->_hi && hi_type->_hi == max_jint && lo_type->_lo == min_jint) { - assert((dom_bool->_test.is_less() && !proj->_con) || (dom_bool->_test.is_greater() && proj->_con), "incorrect test"); // this test was canonicalized assert(this_bool->_test.is_less() && fail->_con, "incorrect test"); + // this_bool = < + // dom_bool = >= (proj = True) or dom_bool = < (proj = False) + // x in [a, b[ on the fail (= True) projection, b > a-1 (because of hi_type->_lo > lo_type->_hi test above): + // lo = a, hi = b, adjusted_lim = b-a, cond = (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b[ on the fail (= True) projection, b > a: + // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = = (proj = True) or dom_bool = < (proj = False) + // x in [a, b] on the fail (= True) projection, b+1 > a-1: + // lo = a, hi = b, adjusted_lim = b-a, cond = <=u + // dom_bool = > (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b] on the fail (= True) projection b+1 > a: + // lo = a+1, hi = b, adjusted_lim = b-a, cond = transform(new SubINode(hi, lo)); + cond = BoolTest::lt; + } lo = igvn->transform(new AddINode(lo, igvn->intcon(1))); } } else if (lo_type->_lo > hi_type->_hi && lo_type->_hi == max_jint && hi_type->_lo == min_jint) { + + // this_bool = < + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in [b, a[ on the fail (= False) projection, a > b-1 (because of lo_type->_lo > hi_type->_hi above): + // lo = b, hi = a, adjusted_lim = a-b, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in [b, a] on the fail (= False) projection, a+1 > b-1: + // lo = b, hi = a, adjusted_lim = a-b, cond = >u + // this_bool = <= + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in ]b, a[ on the fail (= False) projection, a > b: + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in ]b, a] on the fail (= False) projection, a+1 > b: + // lo = b+1, hi = a, adjusted_lim = a-b, cond = >=u + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then hi-lo = -1 + swap(lo, hi); swap(lo_type, hi_type); swap(lo_test, hi_test); @@ -842,6 +901,10 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge; if (lo_test == BoolTest::le) { + if (cond == BoolTest::gt) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + cond = BoolTest::ge; + } lo = igvn->transform(new AddINode(lo, igvn->intcon(1))); } @@ -860,7 +923,6 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f } } } - lo = NULL; hi = NULL; } @@ -868,12 +930,13 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f if (lo && hi) { // Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo)) Node* adjusted_val = igvn->transform(new SubINode(n, lo)); - Node* adjusted_lim = igvn->transform(new SubINode(hi, lo)); + if (adjusted_lim == NULL) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + } Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim)); Node* newbool = igvn->transform(new BoolNode(newcmp, cond)); - igvn->is_IterGVN()->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); - igvn->hash_delete(this); + igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); set_req(1, newbool); return true; diff --git a/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java b/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java new file mode 100644 index 00000000000..328807a6560 --- /dev/null +++ b/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 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 8085832 + * @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1 + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBadFoldCompare + */ + +public class TestBadFoldCompare { + + static boolean test1_taken; + + static void helper1(int i, int a, int b, boolean flag) { + if (flag) { + if (i <= a || i > b) { + test1_taken = true; + } + } + } + + static void test1(int i, boolean flag) { + helper1(i, 0, 0, flag); + } + + static boolean test2_taken; + + static void helper2(int i, int a, int b, boolean flag) { + if (flag) { + if (i > b || i <= a) { + test2_taken = true; + } + } + } + + static void test2(int i, boolean flag) { + helper2(i, 0, 0, flag); + } + + static public void main(String[] args) { + boolean success = true; + + for (int i = 0; i < 20000; i++) { + helper1(5, 0, 10, (i%2)==0); + helper1(-1, 0, 10, (i%2)==0); + helper1(15, 0, 10, (i%2)==0); + test1(0, false); + } + test1_taken = false; + test1(0, true); + if (!test1_taken) { + System.out.println("Test1 failed"); + success = false; + } + + for (int i = 0; i < 20000; i++) { + helper2(5, 0, 10, (i%2)==0); + helper2(-1, 0, 10, (i%2)==0); + helper2(15, 0, 10, (i%2)==0); + test2(0, false); + } + test2_taken = false; + test2(0, true); + + if (!test2_taken) { + System.out.println("Test2 failed"); + success = false; + } + if (!success) { + throw new RuntimeException("Some tests failed"); + } + } +} From 513d9a5edea37bf3c580a4a29c323e6602e2056e Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Tue, 12 May 2015 14:26:31 +0200 Subject: [PATCH 015/117] 8085832: Optimize main and post loop out when pre loop is found empty Eliminate main loop and post loop if pre loop becomes empty Reviewed-by: kvn, mcberg --- hotspot/src/share/vm/opto/loopTransform.cpp | 60 ++++++++++++++++++++- hotspot/src/share/vm/opto/loopnode.hpp | 2 + 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index b2d0f6ba420..a0b48ea9aea 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -475,7 +475,7 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { C->set_major_progress(); // Peeling a 'main' loop in a pre/main/post situation obfuscates the - // 'pre' loop from the main and the 'pre' can no longer have it's + // 'pre' loop from the main and the 'pre' can no longer have its // iterations adjusted. Therefore, we need to declare this loop as // no longer a 'main' loop; it will need new pre and post loops before // we can do further RCE. @@ -1911,7 +1911,7 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { return; assert(opqzm->in(1) == main_limit, "do not understand situation"); - // Find the pre-loop limit; we will expand it's iterations to + // Find the pre-loop limit; we will expand its iterations to // not ever trip low tests. Node *p_f = iffm->in(0); // pre loop may have been optimized out @@ -2218,6 +2218,56 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) { } } +#ifdef ASSERT +static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) { + Node *ctrl = cl->in(LoopNode::EntryControl); + assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, ""); + Node *iffm = ctrl->in(0); + assert(iffm->Opcode() == Op_If, ""); + Node *p_f = iffm->in(0); + assert(p_f->Opcode() == Op_IfFalse, ""); + CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); + assert(pre_end->loopnode()->is_pre_loop(), ""); + return pre_end->loopnode(); +} +#endif + +// Remove the main and post loops and make the pre loop execute all +// iterations. Useful when the pre loop is found empty. +void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase) { + CountedLoopEndNode* pre_end = cl->loopexit(); + Node* pre_cmp = pre_end->cmp_node(); + if (pre_cmp->in(2)->Opcode() != Op_Opaque1) { + // Only safe to remove the main loop if the compiler optimized it + // out based on an unknown number of iterations + return; + } + + // Can we find the main loop? + if (_next == NULL) { + return; + } + + Node* next_head = _next->_head; + if (!next_head->is_CountedLoop()) { + return; + } + + CountedLoopNode* main_head = next_head->as_CountedLoop(); + if (!main_head->is_main_loop()) { + return; + } + + assert(locate_pre_from_main(main_head) == cl, "bad main loop"); + Node* main_iff = main_head->in(LoopNode::EntryControl)->in(0); + + // Remove the Opaque1Node of the pre loop and make it execute all iterations + phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2)); + // Remove the Opaque1Node of the main loop so it can be optimized out + Node* main_cmp = main_iff->in(1)->in(1); + assert(main_cmp->in(2)->Opcode() == Op_Opaque1, "main loop has no opaque node?"); + phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1)); +} //------------------------------policy_do_remove_empty_loop-------------------- // Micro-benchmark spamming. Policy is to always remove empty loops. @@ -2236,6 +2286,12 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) return false; // Infinite loop + if (cl->is_pre_loop()) { + // If the loop we are removing is a pre-loop then the main and + // post loop can be removed as well + remove_main_post_loops(cl, phase); + } + #ifdef ASSERT // Ensure only one phi which is the iv. Node* iv = NULL; diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index a2063232763..3f0cb512a08 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -485,6 +485,8 @@ public: bool is_inner() { return is_loop() && _child == NULL; } bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); } + void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); + #ifndef PRODUCT void dump_head( ) const; // Dump loop head only void dump() const; // Dump this loop recursively From e52bc6a831807006a20720f849e975428353cd17 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Tue, 12 May 2015 16:43:32 +0400 Subject: [PATCH 016/117] 8079255: [macosx] Test closed/java/awt/Robot/RobotWheelTest/RobotWheelTest fails for Mac only Reviewed-by: serb --- .../Robot/RobotWheelTest/RobotWheelTest.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java diff --git a/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java b/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java new file mode 100644 index 00000000000..928648fc7a3 --- /dev/null +++ b/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1998, 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. + */ +import java.awt.Button; +import java.awt.Frame; +import java.awt.Rectangle; +import java.awt.Robot; +import jdk.testlibrary.OSInfo; + +/* + * @test 1.2 98/08/05 + * @bug 4373478 8079255 + * @summary Test mouse wheel functionality of Robot + * @author bchristi: area=Robot + * @library ../../../../lib/testlibrary + * @build jdk.testlibrary.OSInfo + * @run main RobotWheelTest + */ +public class RobotWheelTest { + + private static final int NUMTESTS = 20; + private static volatile int wheelRotation; + + public static void main(String[] args) throws Exception { + + Frame frame = null; + try { + int wheelSign = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -1 : 1; + + frame = new Frame(); + frame.setSize(200, 200); + Button button = new Button("WheelButton"); + button.addMouseWheelListener(e -> wheelRotation = e.getWheelRotation()); + frame.add(button); + frame.setVisible(true); + + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.waitForIdle(); + + Rectangle bounds = frame.getBounds(); + int centerX = bounds.x + bounds.width / 2; + int centerY = bounds.y + bounds.height / 2; + robot.mouseMove(centerX, centerY); + robot.waitForIdle(); + + for (int i = -NUMTESTS; i <= NUMTESTS; i++) { + if (i == 0) { + continue; + } + robot.mouseWheel(i); + robot.waitForIdle(); + if (i != wheelSign * wheelRotation) { + throw new RuntimeException("wheelRotation = " + wheelRotation + + ", expected value = " + i); + } + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + } +} \ No newline at end of file From 5c80a9e763298586dae65e97743bacf422f3d6d5 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 12 May 2015 20:30:48 +0300 Subject: [PATCH 017/117] 8077584: Value of java.awt.font.OpenType.TAG_OPBD is incorrect Reviewed-by: serb, prr --- .../share/classes/java/awt/font/OpenType.java | 2 +- .../font/OpenType/OpticalBoundsTagTest.java | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/font/OpenType/OpticalBoundsTagTest.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/font/OpenType.java b/jdk/src/java.desktop/share/classes/java/awt/font/OpenType.java index e32503ab5ed..ebe6cb39adf 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/font/OpenType.java +++ b/jdk/src/java.desktop/share/classes/java/awt/font/OpenType.java @@ -331,7 +331,7 @@ public interface OpenType { * Optical bounds. Table tag "opbd" in the Open * Type Specification. */ - public final static int TAG_OPBD = 0x6d6f7274; + public final static int TAG_OPBD = 0x6F706264; /** * Glyph properties. Table tag "prop" in the Open diff --git a/jdk/test/java/awt/font/OpenType/OpticalBoundsTagTest.java b/jdk/test/java/awt/font/OpenType/OpticalBoundsTagTest.java new file mode 100644 index 00000000000..7d36506889c --- /dev/null +++ b/jdk/test/java/awt/font/OpenType/OpticalBoundsTagTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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. + */ +import java.awt.font.OpenType; +import java.io.IOException; + +/** + * @test + * @bug 8077584 + * @summary Test for TAG_OPBD tag. Should be unique and not same as TAG_MORT. + * @run main OpticalBoundsTagTest + */ + +public class OpticalBoundsTagTest { + + public static void main(String[] a) throws Exception { + + int tag_opbd = java.awt.font.OpenType.TAG_OPBD; + if (tag_opbd == java.awt.font.OpenType.TAG_MORT) { + System.out.println("Test failed: TAG_OPBD:" + tag_opbd); + throw new RuntimeException("TAG_OPBD same as TAG_MORT"); + } else { + System.out.println("Test passed: TAG_OPBD: " + tag_opbd); + } + } +} From a7bea0d0c4fc835e2921b0584566ace434669b11 Mon Sep 17 00:00:00 2001 From: Vivi An Date: Tue, 12 May 2015 13:45:49 -0700 Subject: [PATCH 018/117] 8075609: java.lang.IllegalArgumentException: aContainer is not a focus cycle root of aComponent Reviewed-by: alexsch, ant --- .../swing/plaf/basic/BasicRadioButtonUI.java | 2 +- .../JRadioButton/8075609/bug8075609.java | 115 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/swing/JRadioButton/8075609/bug8075609.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java index 89066d20695..9c73734b72a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java @@ -438,7 +438,7 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI // to the button group or not Component getFocusTransferBaseComponent(boolean next){ Component focusBaseComp = activeBtn; - Window container = SwingUtilities.getWindowAncestor(activeBtn); + Container container = focusBaseComp.getFocusCycleRootAncestor(); if (container != null) { FocusTraversalPolicy policy = container.getFocusTraversalPolicy(); Component comp = next ? policy.getComponentAfter(container, activeBtn) diff --git a/jdk/test/javax/swing/JRadioButton/8075609/bug8075609.java b/jdk/test/javax/swing/JRadioButton/8075609/bug8075609.java new file mode 100644 index 00000000000..9bffc80ce88 --- /dev/null +++ b/jdk/test/javax/swing/JRadioButton/8075609/bug8075609.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 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 + * @library ../../regtesthelpers + * @build Util + * @bug 8075609 + * @summary IllegalArgumentException when transferring focus from JRadioButton using tab + * @author Vivi An + * @run main bug8075609 + */ + +import javax.swing.*; +import javax.swing.event.*; +import java.awt.event.*; +import java.awt.*; +import sun.awt.SunToolkit; + +public class bug8075609 { + private static Robot robot; + private static SunToolkit toolkit; + private static JTextField textField; + + public static void main(String args[]) throws Throwable { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + robot = new Robot(); + Thread.sleep(100); + + robot.setAutoDelay(100); + toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + // Radio button group tab key test + runTest1(); + } + + private static void createAndShowGUI() { + JFrame mainFrame = new JFrame("Bug 8075609 - 1 test"); + + JPanel rootPanel = new JPanel(); + rootPanel.setLayout(new BorderLayout()); + + JPanel formPanel = new JPanel(); + formPanel.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); + formPanel.setFocusCycleRoot(true); + + JRadioButton option1 = new JRadioButton("Option 1", true); + JRadioButton option2 = new JRadioButton("Option 2"); + + ButtonGroup radioButtonGroup = new ButtonGroup(); + radioButtonGroup.add(option1); + radioButtonGroup.add(option2); + + formPanel.add(option1); + formPanel.add(option2); + textField = new JTextField("Another focusable component"); + formPanel.add(textField); + + rootPanel.add(formPanel, BorderLayout.CENTER); + + JButton okButton = new JButton("OK"); + rootPanel.add(okButton, BorderLayout.SOUTH); + + mainFrame.add(rootPanel); + mainFrame.pack(); + mainFrame.setVisible(true); + mainFrame.toFront(); + } + + // Radio button Group as a single component when traversing through tab key + private static void runTest1() throws Exception{ + hitKey(robot, KeyEvent.VK_TAB); + + robot.setAutoDelay(1000 ); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if (textField.hasFocus()) { + System.out.println("Radio Button Group Go To Next Component through Tab Key failed"); + throw new RuntimeException("Focus is not on textField as Expected"); + } + } + }); + } + + private static void hitKey(Robot robot, int keycode) { + robot.keyPress(keycode); + robot.keyRelease(keycode); + toolkit.realSync(); + } +} From 619677d0dc21f949807c86bea80c69475ff7a914 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 13 May 2015 18:06:19 +0300 Subject: [PATCH 019/117] 8072775: Tremendous memory usage by JTextArea Reviewed-by: vadim, prr --- .../classes/sun/font/StandardTextSource.java | 107 +++++++----------- .../classes/sun/font/TextLabelFactory.java | 12 +- .../JTextArea/TextViewOOM/TextViewOOM.java | 95 ++++++++++++++++ 3 files changed, 140 insertions(+), 74 deletions(-) create mode 100644 jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java diff --git a/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java b/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java index 38389ec1e0d..afda090946e 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java +++ b/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -33,42 +33,43 @@ import java.awt.Font; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; -public class StandardTextSource extends TextSource { - char[] chars; - int start; - int len; - int cstart; - int clen; - int level; // assumed all uniform - int flags; // see GlyphVector.java - Font font; - FontRenderContext frc; - CoreMetrics cm; +final class StandardTextSource extends TextSource { - /** - * Create a simple implementation of a TextSource. - * - * Chars is an array containing clen chars in the context, in - * logical order, contiguously starting at cstart. Start and len - * represent that portion of the context representing the true - * source; start, like cstart, is relative to the start of the - * character array. - * - * Level is the bidi level (0-63 for the entire context. Flags is - * the layout flags. Font is the font, frc is the render context, - * and lm is the line metrics for the entire source text, but not - * necessarily the context. - */ - public StandardTextSource(char[] chars, - int start, - int len, - int cstart, - int clen, - int level, - int flags, - Font font, - FontRenderContext frc, - CoreMetrics cm) { + private final char[] chars; + private final int start; + private final int len; + private final int cstart; + private final int clen; + private final int level; // assumed all uniform + private final int flags; // see GlyphVector.java + private final Font font; + private final FontRenderContext frc; + private final CoreMetrics cm; + + /** + * Create a simple implementation of a TextSource. + * + * Chars is an array containing clen chars in the context, in + * logical order, contiguously starting at cstart. Start and len + * represent that portion of the context representing the true + * source; start, like cstart, is relative to the start of the + * character array. + * + * Level is the bidi level (0-63 for the entire context. Flags is + * the layout flags. Font is the font, frc is the render context, + * and lm is the line metrics for the entire source text, but not + * necessarily the context. + */ + StandardTextSource(char[] chars, + int start, + int len, + int cstart, + int clen, + int level, + int flags, + Font font, + FontRenderContext frc, + CoreMetrics cm) { if (chars == null) { throw new IllegalArgumentException("bad chars: null"); } @@ -97,7 +98,7 @@ public class StandardTextSource extends TextSource { throw new IllegalArgumentException("bad frc: null"); } - this.chars = chars.clone(); + this.chars = chars; this.start = start; this.len = len; this.cstart = cstart; @@ -115,40 +116,10 @@ public class StandardTextSource extends TextSource { } } - /** Create a StandardTextSource whose context is coextensive with the source. */ - public StandardTextSource(char[] chars, - int start, - int len, - int level, - int flags, - Font font, - FontRenderContext frc, - CoreMetrics cm) { - this(chars, start, len, start, len, level, flags, font, frc, cm); - } - - /** Create a StandardTextSource whose context and source are coextensive with the entire char array. */ - public StandardTextSource(char[] chars, - int level, - int flags, - Font font, - FontRenderContext frc) { - this(chars, 0, chars.length, 0, chars.length, level, flags, font, frc, null); - } - - /** Create a StandardTextSource whose context and source are all the text in the String. */ - public StandardTextSource(String str, - int level, - int flags, - Font font, - FontRenderContext frc) { - this(str.toCharArray(), 0, str.length(), 0, str.length(), level, flags, font, frc, null); - } - // TextSource API public char[] getChars() { - return chars.clone(); + return chars; } public int getStart() { diff --git a/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java b/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java index a42b396c087..1f9ba94159c 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java +++ b/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -48,12 +48,12 @@ import java.text.Bidi; * @see TextLayout */ -public class TextLabelFactory { - private FontRenderContext frc; - private char[] text; - private Bidi bidi; +public final class TextLabelFactory { + private final FontRenderContext frc; + private final char[] text; + private final Bidi bidi; private Bidi lineBidi; - private int flags; + private final int flags; private int lineStart; private int lineLimit; diff --git a/jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java b/jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java new file mode 100644 index 00000000000..e75c7053d08 --- /dev/null +++ b/jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.EventQueue; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/** + * @test + * @bug 8072775 + * @run main/othervm -Xmx80m TextViewOOM + */ +public class TextViewOOM { + + private static JFrame frame; + private static JTextArea ta; + private static final String STRING = "\uDC00\uD802\uDFFF"; + private static final int N = 5000; + + private static void createAndShowGUI() { + frame = new JFrame(); + final JScrollPane jScrollPane1 = new JScrollPane(); + ta = new JTextArea(); + + ta.setEditable(false); + ta.setColumns(20); + ta.setRows(5); + jScrollPane1.setViewportView(ta); + frame.add(ta); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(final String[] args) throws Exception { + /* Create and display the form */ + EventQueue.invokeAndWait(TextViewOOM::createAndShowGUI); + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + long mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory before creating the text: "+mem); + final StringBuilder sb = new StringBuilder(N * STRING.length()); + for (int i = 0; i < N; i++) { + sb.append(STRING); + } + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory after creating the text: "+mem); + + EventQueue.invokeAndWait(() -> { + ta.setText(sb.toString()); + for (int i = 0; i < 10; i++) { + System.gc(); + try {Thread.sleep(200);} catch (InterruptedException iex) {} + } + long mem1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory after setting the text: " + mem1); + }); + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Final memory after everything: " + mem); + EventQueue.invokeAndWait(frame::dispose); + } +} From acbb57df0f75796467e38464dd8b46065c27f611 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 13 May 2015 19:19:03 +0300 Subject: [PATCH 020/117] 5109918: Wrong documentation for JSpinner.DateEditor constructor Reviewed-by: alexsch, azvegint --- jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java b/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java index 064e6e47638..42b1dc39b3b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JSpinner.java @@ -970,7 +970,7 @@ public class JSpinner extends JComponent implements Accessible * and editing the value of a SpinnerDateModel * with a JFormattedTextField. This * DateEditor becomes both a ChangeListener - * on the spinners model and a PropertyChangeListener + * on the spinner and a PropertyChangeListener * on the new JFormattedTextField. * * @param spinner the spinner whose model this editor will monitor From 88dd747a1a34608c4376c022630f3c6e0cb434ae Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 14 May 2015 02:05:02 +0300 Subject: [PATCH 021/117] 6368321: MetalRootPaneUI calls to deprecated code Reviewed-by: alexsch, azvegint --- .../share/classes/javax/swing/JApplet.java | 28 +++--- .../share/classes/javax/swing/JDialog.java | 11 +-- .../share/classes/javax/swing/JFrame.java | 8 +- .../swing/plaf/metal/MetalRootPaneUI.java | 28 +++--- .../SilenceOfDeprecatedMenuBar.java | 90 +++++++++++++++++++ 5 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 jdk/test/javax/swing/JRootPane/SilenceOfDeprecatedMenuBar/SilenceOfDeprecatedMenuBar.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java b/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java index 4e74e411a61..6a00de486d2 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -24,14 +24,18 @@ */ package javax.swing; -import java.awt.*; -import java.awt.event.*; import java.applet.Applet; -import java.beans.PropertyChangeListener; -import java.util.Locale; -import java.util.Vector; -import java.io.Serializable; -import javax.accessibility.*; +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.HeadlessException; +import java.awt.LayoutManager; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; /** * An extended version of java.applet.Applet that adds support for @@ -243,9 +247,8 @@ public class JApplet extends Applet implements Accessible, * hidden: true * description: The menubar for accessing pulldown menus from this applet. */ - @SuppressWarnings("deprecation") - public void setJMenuBar(JMenuBar menuBar) { - getRootPane().setMenuBar(menuBar); + public void setJMenuBar(final JMenuBar menuBar) { + getRootPane().setJMenuBar(menuBar); } /** @@ -254,9 +257,8 @@ public class JApplet extends Applet implements Accessible, * @return the menubar set on this applet * @see #setJMenuBar */ - @SuppressWarnings("deprecation") public JMenuBar getJMenuBar() { - return getRootPane().getMenuBar(); + return getRootPane().getJMenuBar(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JDialog.java b/jdk/src/java.desktop/share/classes/javax/swing/JDialog.java index b9eb3e55475..b33bb15f30d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JDialog.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -849,9 +849,8 @@ public class JDialog extends Dialog implements WindowConstants, * hidden: true * description: The menubar for accessing pulldown menus from this dialog. */ - @SuppressWarnings("deprecation") - public void setJMenuBar(JMenuBar menu) { - getRootPane().setMenuBar(menu); + public void setJMenuBar(final JMenuBar menu) { + getRootPane().setJMenuBar(menu); } /** @@ -860,12 +859,10 @@ public class JDialog extends Dialog implements WindowConstants, * @return the menubar set on this dialog * @see #setJMenuBar */ - @SuppressWarnings("deprecation") public JMenuBar getJMenuBar() { - return getRootPane().getMenuBar(); + return getRootPane().getJMenuBar(); } - /** * Returns whether calls to {@code add} and * {@code setLayout} are forwarded to the {@code contentPane}. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java b/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java index be6b5ba96ba..c8415e70f58 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java @@ -486,9 +486,8 @@ public class JFrame extends Frame implements WindowConstants, * hidden: true * description: The menubar for accessing pulldown menus from this frame. */ - @SuppressWarnings("deprecation") - public void setJMenuBar(JMenuBar menubar) { - getRootPane().setMenuBar(menubar); + public void setJMenuBar(final JMenuBar menubar) { + getRootPane().setJMenuBar(menubar); } /** @@ -497,9 +496,8 @@ public class JFrame extends Frame implements WindowConstants, * * @see #setJMenuBar */ - @SuppressWarnings("deprecation") public JMenuBar getJMenuBar() { - return getRootPane().getMenuBar(); + return getRootPane().getJMenuBar(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java index bd5f203f434..1d163f22bfa 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -27,15 +27,11 @@ package javax.swing.plaf.metal; import java.awt.event.*; import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import javax.swing.*; -import javax.swing.border.*; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import java.awt.*; -import java.io.*; -import java.security.*; /** * Provides the metal look and feel implementation of RootPaneUI. @@ -441,7 +437,6 @@ public class MetalRootPaneUI extends BasicRootPaneUI * @param the Container for which this layout manager is being used * @return a Dimension object containing the layout's preferred size */ - @SuppressWarnings("deprecation") public Dimension preferredLayoutSize(Container parent) { Dimension cpd, mbd, tpd; int cpWidth = 0; @@ -463,8 +458,8 @@ public class MetalRootPaneUI extends BasicRootPaneUI cpHeight = cpd.height; } - if(root.getMenuBar() != null) { - mbd = root.getMenuBar().getPreferredSize(); + if(root.getJMenuBar() != null) { + mbd = root.getJMenuBar().getPreferredSize(); if (mbd != null) { mbWidth = mbd.width; mbHeight = mbd.height; @@ -494,7 +489,6 @@ public class MetalRootPaneUI extends BasicRootPaneUI * @param the Container for which this layout manager is being used * @return a Dimension object containing the layout's minimum size */ - @SuppressWarnings("deprecation") public Dimension minimumLayoutSize(Container parent) { Dimension cpd, mbd, tpd; int cpWidth = 0; @@ -516,8 +510,8 @@ public class MetalRootPaneUI extends BasicRootPaneUI cpHeight = cpd.height; } - if(root.getMenuBar() != null) { - mbd = root.getMenuBar().getMinimumSize(); + if(root.getJMenuBar() != null) { + mbd = root.getJMenuBar().getMinimumSize(); if (mbd != null) { mbWidth = mbd.width; mbHeight = mbd.height; @@ -546,7 +540,6 @@ public class MetalRootPaneUI extends BasicRootPaneUI * @param the Container for which this layout manager is being used * @return a Dimension object containing the layout's maximum size */ - @SuppressWarnings("deprecation") public Dimension maximumLayoutSize(Container target) { Dimension cpd, mbd, tpd; int cpWidth = Integer.MAX_VALUE; @@ -566,8 +559,8 @@ public class MetalRootPaneUI extends BasicRootPaneUI } } - if(root.getMenuBar() != null) { - mbd = root.getMenuBar().getMaximumSize(); + if(root.getJMenuBar() != null) { + mbd = root.getJMenuBar().getMaximumSize(); if (mbd != null) { mbWidth = mbd.width; mbHeight = mbd.height; @@ -610,7 +603,6 @@ public class MetalRootPaneUI extends BasicRootPaneUI * * @param the Container for which this layout manager is being used */ - @SuppressWarnings("deprecation") public void layoutContainer(Container parent) { JRootPane root = (JRootPane) parent; Rectangle b = root.getBounds(); @@ -640,9 +632,9 @@ public class MetalRootPaneUI extends BasicRootPaneUI } } } - if(root.getMenuBar() != null) { - Dimension mbd = root.getMenuBar().getPreferredSize(); - root.getMenuBar().setBounds(0, nextY, w, mbd.height); + if(root.getJMenuBar() != null) { + Dimension mbd = root.getJMenuBar().getPreferredSize(); + root.getJMenuBar().setBounds(0, nextY, w, mbd.height); nextY += mbd.height; } if(root.getContentPane() != null) { diff --git a/jdk/test/javax/swing/JRootPane/SilenceOfDeprecatedMenuBar/SilenceOfDeprecatedMenuBar.java b/jdk/test/javax/swing/JRootPane/SilenceOfDeprecatedMenuBar/SilenceOfDeprecatedMenuBar.java new file mode 100644 index 00000000000..a59ac067f30 --- /dev/null +++ b/jdk/test/javax/swing/JRootPane/SilenceOfDeprecatedMenuBar/SilenceOfDeprecatedMenuBar.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 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. + */ + +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JRootPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/** + * @test + * @bug 6368321 + * @author Sergey Bylokhov + */ +public final class SilenceOfDeprecatedMenuBar implements Runnable { + + public static void main(final String[] args) throws Exception { + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(new SilenceOfDeprecatedMenuBar()); + } + } + + @Override + public void run() { + final JFrame frame = new DeprecatedFrame(); + try { + final JMenuBar bar = new JMenuBar(); + frame.setJMenuBar(bar); + frame.setBounds(100, 100, 100, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + if (bar != frame.getJMenuBar()) { + throw new RuntimeException("Wrong JMenuBar"); + } + } finally { + frame.dispose(); + } + } + + private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + System.out.println("LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + UnsupportedLookAndFeelException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static class DeprecatedFrame extends JFrame { + + @Override + protected JRootPane createRootPane() { + return new JRootPane() { + @Override + public JMenuBar getMenuBar() { + throw new RuntimeException("Should not be here"); + } + @Override + public void setMenuBar(final JMenuBar menu) { + throw new RuntimeException("Should not be here"); + } + }; + } + } +} From 26076d63aca5cddabcb910a96171b7a7a64f7d11 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Thu, 14 May 2015 18:23:39 +0300 Subject: [PATCH 022/117] 8033069: mouse wheel scroll closes combobox popup Reviewed-by: serb, alexsch --- .../swing/plaf/basic/BasicComboBoxUI.java | 44 +++-- .../swing/plaf/basic/BasicComboPopup.java | 29 ++- .../swing/plaf/basic/BasicPopupMenuUI.java | 4 +- .../8033069/bug8033069NoScrollBar.java | 182 ++++++++++++++++++ .../8033069/bug8033069ScrollBar.java | 52 +++++ 5 files changed, 295 insertions(+), 16 deletions(-) create mode 100644 jdk/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java create mode 100644 jdk/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index 33f1540feae..5a3f67da230 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -150,6 +150,8 @@ public class BasicComboBoxUI extends ComboBoxUI { */ protected KeyListener popupKeyListener; + private MouseWheelListener mouseWheelListener; + // This is used for knowing when to cache the minimum preferred size. // If the data in the list changes, the cached value get marked for recalc. // Added to the current JComboBox model @@ -413,6 +415,10 @@ public class BasicComboBoxUI extends ComboBoxUI { comboBox.getModel().addListDataListener( listDataListener ); } } + + if ((mouseWheelListener = createMouseWheelListener()) != null) { + comboBox.addMouseWheelListener(mouseWheelListener); + } } /** @@ -459,6 +465,9 @@ public class BasicComboBoxUI extends ComboBoxUI { comboBox.getModel().removeListDataListener( listDataListener ); } } + if (mouseWheelListener != null) { + comboBox.removeMouseWheelListener(mouseWheelListener); + } } /** @@ -572,6 +581,10 @@ public class BasicComboBoxUI extends ComboBoxUI { return handler; } + private MouseWheelListener createMouseWheelListener() { + return getHandler(); + } + // // end UI Initialization //====================== @@ -1723,7 +1736,8 @@ public class BasicComboBoxUI extends ComboBoxUI { // private class Handler implements ActionListener, FocusListener, KeyListener, LayoutManager, - ListDataListener, PropertyChangeListener { + ListDataListener, PropertyChangeListener, + MouseWheelListener { // // PropertyChangeListener // @@ -1997,21 +2011,25 @@ public class BasicComboBoxUI extends ComboBoxUI { public void actionPerformed(ActionEvent evt) { Object item = comboBox.getEditor().getItem(); if (item != null) { - if(!comboBox.isPopupVisible() && !item.equals(comboBox.getSelectedItem())) { - comboBox.setSelectedItem(comboBox.getEditor().getItem()); - } - ActionMap am = comboBox.getActionMap(); - if (am != null) { - Action action = am.get("enterPressed"); - if (action != null) { - action.actionPerformed(new ActionEvent(comboBox, evt.getID(), - evt.getActionCommand(), - evt.getModifiers())); + if (!comboBox.isPopupVisible() && !item.equals(comboBox.getSelectedItem())) { + comboBox.setSelectedItem(comboBox.getEditor().getItem()); + } + ActionMap am = comboBox.getActionMap(); + if (am != null) { + Action action = am.get("enterPressed"); + if (action != null) { + action.actionPerformed(new ActionEvent(comboBox, evt.getID(), + evt.getActionCommand(), + evt.getModifiers())); + } } } - } + } + + public void mouseWheelMoved(MouseWheelEvent e) { + e.consume(); + } } - } class DefaultKeySelectionManager implements JComboBox.KeySelectionManager, UIResource { private String prefix = ""; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index c70c06cad89..3b3d33cc9d7 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -184,6 +184,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { */ protected ItemListener itemListener; + private MouseWheelListener scrollerMouseWheelListener; + /** * This protected field is implementation specific. Do not access directly * or override. @@ -311,6 +313,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { uninstallComboBoxModelListeners(comboBox.getModel()); uninstallKeyboardActions(); uninstallListListeners(); + uninstallScrollerListeners(); // We do this, otherwise the listener the ui installs on // the model (the combobox model in this case) will keep a // reference to the list, causing the list (and us) to never get gced. @@ -608,6 +611,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { scroller.setFocusable( false ); scroller.getVerticalScrollBar().setFocusable( false ); scroller.setBorder( null ); + installScrollerListeners(); } /** @@ -624,6 +628,20 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { setFocusable( false ); } + private void installScrollerListeners() { + scrollerMouseWheelListener = getHandler(); + if (scrollerMouseWheelListener != null) { + scroller.addMouseWheelListener(scrollerMouseWheelListener); + } + } + + private void uninstallScrollerListeners() { + if (scrollerMouseWheelListener != null) { + scroller.removeMouseWheelListener(scrollerMouseWheelListener); + scrollerMouseWheelListener = null; + } + } + /** * This method adds the necessary listeners to the JComboBox. */ @@ -835,8 +853,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { private class Handler implements ItemListener, MouseListener, - MouseMotionListener, PropertyChangeListener, - Serializable { + MouseMotionListener, MouseWheelListener, + PropertyChangeListener, Serializable { // // MouseListener // NOTE: this is added to both the JList and JComboBox @@ -1024,6 +1042,13 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { setListSelection(comboBox.getSelectedIndex()); } } + + // + // MouseWheelListener + // + public void mouseWheelMoved(MouseWheelEvent e) { + e.consume(); + } } // diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index e9d878a2ca2..4a4d0baf32b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -914,7 +914,9 @@ public class BasicPopupMenuUI extends PopupMenuUI { processMouseEvent(me); break; case MouseEvent.MOUSE_WHEEL: - if (isInPopup(src)) { + if (isInPopup(src) + || ((src instanceof JComboBox) && ((JComboBox) src).isPopupVisible())) { + return; } cancelPopupMenu(); diff --git a/jdk/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java b/jdk/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java new file mode 100644 index 00000000000..9850aa2ba5c --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.AWTException; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; + +/* @test + * @bug 8033069 + * @summary Checks that JComboBox popup does not close when mouse wheel is + * rotated over combo box and over its popup. The case where popup + * has no scroll bar. + * @library ../../regtesthelpers + * @build Util + * @run main bug8033069NoScrollBar + * @author Alexey Ivanov + */ +public class bug8033069NoScrollBar implements Runnable { + + private static final String[] NO_SCROLL_ITEMS = new String[] { + "A", "B", "C", "D", "E", "F" + }; + + private final Robot robot; + + private final String[] items; + + private JFrame frame; + private JComboBox cb1; + private JComboBox cb2; + + public static void main(String[] args) throws Exception { + iterateLookAndFeels(new bug8033069NoScrollBar(NO_SCROLL_ITEMS)); + } + + protected static void iterateLookAndFeels(final bug8033069NoScrollBar test) throws Exception { + LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels(); + for (LookAndFeelInfo info : lafInfo) { + try { + UIManager.setLookAndFeel(info.getClassName()); + System.out.println("Look and Feel: " + info.getClassName()); + test.runTest(); + } catch (UnsupportedLookAndFeelException e) { + System.out.println("Skipping unsupported LaF: " + info); + } + } + } + + public bug8033069NoScrollBar(String[] items) throws AWTException { + this.items = items; + + robot = new Robot(); + robot.setAutoDelay(200); + } + + private void setupUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + cb1 = new JComboBox<>(items); + cb2 = new JComboBox<>(items); + JPanel panel = new JPanel(new GridLayout(1, 2)); + panel.add(cb1); + panel.add(cb2); + + frame.add(panel); + + frame.pack(); + frame.setVisible(true); + } + + public void runTest() throws Exception { + try { + SwingUtilities.invokeAndWait(this); + + robot.waitForIdle(); + assertFalse("cb1 popup is visible", + Util.invokeOnEDT(cb1::isPopupVisible)); + + // Move mouse pointer to the center of the fist combo box + Point p = cb1.getLocationOnScreen(); + Dimension d = cb1.getSize(); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + // Click it to open popup + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + robot.waitForIdle(); + assertTrue("cb1 popup is not visible", + Util.invokeOnEDT(cb1::isPopupVisible)); + + robot.mouseWheel(1); + robot.waitForIdle(); + assertTrue("cb1 popup is not visible after mouse wheel up on combo box", + Util.invokeOnEDT(cb1::isPopupVisible)); + + robot.mouseWheel(-1); + robot.waitForIdle(); + assertTrue("cb1 popup is not visible after mouse wheel down on combo box", + Util.invokeOnEDT(cb1::isPopupVisible)); + + // Move mouse down on the popup + robot.mouseMove(p.x + d.width / 2, p.y + d.height * 3); + + robot.mouseWheel(1); + robot.waitForIdle(); + assertTrue("cb1 popup is not visible after mouse wheel up on popup", + Util.invokeOnEDT(cb1::isPopupVisible)); + + robot.mouseWheel(-1); + robot.waitForIdle(); + assertTrue("cb1 popup is not visible after mouse wheel down on popup", + Util.invokeOnEDT(cb1::isPopupVisible)); + + + // Move mouse pointer to the center of the second combo box + p = cb2.getLocationOnScreen(); + d = cb2.getSize(); + robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); + + robot.mouseWheel(1); + robot.waitForIdle(); + assertFalse("cb1 popup is visible after mouse wheel up on cb2", + Util.invokeOnEDT(cb1::isPopupVisible)); + } finally { + if (frame != null) { + frame.dispose(); + } + } + + System.out.println("Test passed"); + } + + @Override + public void run() { + setupUI(); + } + + private static void assertTrue(String message, boolean value) { + assertEquals(message, true, value); + } + + private static void assertFalse(String message, boolean value) { + assertEquals(message, false, value); + } + + private static void assertEquals(String message, boolean expected, boolean actual) { + if (expected != actual) { + throw new RuntimeException(message); + } + } +} diff --git a/jdk/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java b/jdk/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java new file mode 100644 index 00000000000..fed71e654b1 --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.AWTException; + +/* @test + * @bug 8033069 + * @summary Checks that JComboBox popup does not close when mouse wheel is + * rotated over combo box and over its popup. The case where + * popup has scroll bar. + * @library ../../regtesthelpers + * @build Util + * @run main bug8033069ScrollBar + * @author Alexey Ivanov + */ +public class bug8033069ScrollBar extends bug8033069NoScrollBar { + + private static final String[] SCROLL_ITEMS = new String[] { + "A", "B", "C", "D", "E", "F", + "G", "H", "I", "J", "K", "L", + "M", "N", "O", "P", "Q", "R" + }; + + public static void main(String[] args) throws Exception { + iterateLookAndFeels(new bug8033069ScrollBar(SCROLL_ITEMS)); + } + + public bug8033069ScrollBar(String[] items) throws AWTException { + super(items); + } + +} From ae5cc01781a1200bd101934559d10708420d4bc2 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 15 May 2015 14:18:20 +0300 Subject: [PATCH 023/117] 8072448: Can not input Japanese in JTextField on RedHat Linux Reviewed-by: alexsch, serb --- .../unix/native/libawt_xawt/awt/awt_InputMethod.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c index 93a69ad7940..07588c80f5e 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -904,7 +904,6 @@ static void adjustStatusWindow(Window shell){ static Bool createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) { - XIC active_ic, passive_ic; XVaNestedList preedit = NULL; XVaNestedList status = NULL; XIMStyle on_the_spot_styles = XIMPreeditCallbacks, @@ -974,6 +973,12 @@ createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) } if (active_styles == on_the_spot_styles) { + pX11IMData->ic_passive = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, passive_styles, + NULL); + callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS); if (callbacks == (XIMCallback *)NULL) return False; @@ -1024,12 +1029,6 @@ createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) NULL); XFree((void *)preedit); #endif /* __linux__ || MACOSX */ - pX11IMData->ic_passive = XCreateIC(X11im, - XNClientWindow, w, - XNFocusWindow, w, - XNInputStyle, passive_styles, - NULL); - } else { pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, From 6ff1090e7dc1961cd2107f25f295c099408765ad Mon Sep 17 00:00:00 2001 From: David Dehaven Date: Thu, 14 May 2015 09:12:16 -0700 Subject: [PATCH 024/117] 8080343: Incorrect GPL header causes RE script to miss swap to commercial header for licensee source bundle Reviewed-by: prr, serb --- jdk/src/java.desktop/macosx/native/include/jawt_md.h | 2 +- jdk/src/java.desktop/unix/native/common/awt/utility/rect.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/macosx/native/include/jawt_md.h b/jdk/src/java.desktop/macosx/native/include/jawt_md.h index 1d66461bf42..c6859fdbf90 100644 --- a/jdk/src/java.desktop/macosx/native/include/jawt_md.h +++ b/jdk/src/java.desktop/macosx/native/include/jawt_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 diff --git a/jdk/src/java.desktop/unix/native/common/awt/utility/rect.h b/jdk/src/java.desktop/unix/native/common/awt/utility/rect.h index 063caa3e1d7..ceea38f4349 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/utility/rect.h +++ b/jdk/src/java.desktop/unix/native/common/awt/utility/rect.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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 From 828fc948f2eab523b234484b4d6ac880dc91e77d Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 15 May 2015 22:11:14 +0300 Subject: [PATCH 025/117] 8080341: Incorrect GPL header causes RE script to miss swap to commercial header for licensee source bundle Reviewed-by: alexsch, prr --- .../classes/com/sun/beans/decoder/ArrayElementHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/ArrayElementHandler.java b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/ArrayElementHandler.java index 9a6d2284516..ce0aeb31a7a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/ArrayElementHandler.java +++ b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/ArrayElementHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 From 8be69405fdf1f1f98620abdaf62cd2633b2fa1fe Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 16 May 2015 02:37:16 +0300 Subject: [PATCH 026/117] 8030087: Avoid public native methods in sun.awt packages Reviewed-by: azvegint, prr --- .../classes/sun/awt/DefaultMouseInfoPeer.java | 4 ++-- .../share/classes/sun/awt/HToolkit.java | 3 +-- .../unix/classes/sun/awt/FcFontManager.java | 5 ++--- .../unix/classes/sun/awt/X11FontManager.java | 1 - .../classes/sun/awt/X11GraphicsConfig.java | 7 ++----- .../classes/sun/awt/X11GraphicsDevice.java | 13 +++++------- .../sun/awt/X11GraphicsEnvironment.java | 21 ++++--------------- .../unix/classes/sun/awt/X11InputMethod.java | 11 ++-------- .../classes/sun/awt/Win32FontManager.java | 6 +++--- .../classes/sun/awt/Win32GraphicsDevice.java | 2 +- .../sun/awt/Win32GraphicsEnvironment.java | 19 +++++------------ 11 files changed, 27 insertions(+), 65 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java b/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java index d4b578b9e21..9ac06c4b8bf 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,7 +29,7 @@ import java.awt.Point; import java.awt.Window; import java.awt.peer.MouseInfoPeer; -public class DefaultMouseInfoPeer implements MouseInfoPeer { +public final class DefaultMouseInfoPeer implements MouseInfoPeer { /** * Package-private constructor to prevent instantiation. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/HToolkit.java b/jdk/src/java.desktop/share/classes/sun/awt/HToolkit.java index 4eaf3ed5615..dd93654f573 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/HToolkit.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/HToolkit.java @@ -45,8 +45,7 @@ import java.util.Properties; * with the HeadlessToolkit. It is primarily used * in embedded JRE's that do not have sun/awt/X11 classes. */ -public class HToolkit extends SunToolkit - implements ComponentFactory { +public final class HToolkit extends SunToolkit implements ComponentFactory { private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() { @Override diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/FcFontManager.java b/jdk/src/java.desktop/unix/classes/sun/awt/FcFontManager.java index 5ffa3490db6..f9f3bc8b46a 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/FcFontManager.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/FcFontManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -98,8 +98,7 @@ public class FcFontManager extends SunFontManager { return info; } - protected native String getFontPathNative(boolean noType1Fonts, - boolean isX11GE); + native String getFontPathNative(boolean noType1Fonts, boolean isX11GE); protected synchronized String getFontPath(boolean noType1Fonts) { return getFontPathNative(noType1Fonts, false); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11FontManager.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11FontManager.java index 79581c49c52..f49d4d44f35 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11FontManager.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11FontManager.java @@ -44,7 +44,6 @@ import sun.font.MFontConfiguration; import sun.font.CompositeFont; import sun.font.FontManager; import sun.font.SunFontManager; -import sun.font.FontConfigManager; import sun.font.FcFontConfiguration; import sun.font.FontAccess; import sun.font.FontUtilities; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java index 9055bf0e2d6..7432c8b7159 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,7 +27,6 @@ package sun.awt; import java.awt.AWTException; import java.awt.BufferCapabilities; -import java.awt.BufferCapabilities.FlipContents; import java.awt.Component; import java.awt.Toolkit; import java.awt.GraphicsConfiguration; @@ -35,7 +34,6 @@ import java.awt.GraphicsDevice; import java.awt.Image; import java.awt.ImageCapabilities; import java.awt.Transparency; -import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.color.ColorSpace; import java.awt.image.ComponentColorModel; @@ -55,7 +53,6 @@ import sun.java2d.x11.X11SurfaceData; import sun.awt.image.OffScreenImage; import sun.awt.image.SunVolatileImage; import sun.awt.image.SurfaceManager; -import sun.awt.X11ComponentPeer; /** * This is an implementation of a GraphicsConfiguration object for a @@ -314,7 +311,7 @@ public class X11GraphicsConfig extends GraphicsConfiguration return pGetBounds(screen.getScreen()); } - public native Rectangle pGetBounds(int screenNum); + private native Rectangle pGetBounds(int screenNum); private static class XDBECapabilities extends BufferCapabilities { public XDBECapabilities() { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 98a8d510e98..a80994eef96 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -52,10 +52,8 @@ import sun.misc.InnocuousThread; * @see GraphicsEnvironment * @see GraphicsConfiguration */ -public class X11GraphicsDevice - extends GraphicsDevice - implements DisplayChangedListener -{ +public final class X11GraphicsDevice extends GraphicsDevice + implements DisplayChangedListener { int screen; HashMap x11ProxyKeyMap = new HashMap<>(); @@ -201,16 +199,15 @@ public class X11GraphicsDevice /* * Returns the depth for the given index of graphics configurations. */ - public native int getConfigDepth (int index, int screen); + private native int getConfigDepth(int index, int screen); /* * Returns the colormap for the given index of graphics configurations. */ - public native int getConfigColormap (int index, int screen); - + private native int getConfigColormap(int index, int screen); // Whether or not double-buffering extension is supported - public static native boolean isDBESupported(); + static native boolean isDBESupported(); // Callback for adding a new double buffer visual into our set private void addDoubleBufferVisual(int visNum) { doubleBufferVisuals.add(Integer.valueOf(visNum)); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java index e7cc88d2110..fec7daa620b 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -29,13 +29,6 @@ import java.awt.AWTError; import java.awt.GraphicsDevice; import java.awt.Point; import java.awt.Rectangle; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.IOException; -import java.io.StreamTokenizer; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -43,11 +36,6 @@ import java.net.UnknownHostException; import java.util.*; -import sun.font.MFontConfiguration; -import sun.font.FcFontConfiguration; -import sun.font.Font2D; -import sun.font.FontManager; -import sun.font.NativeFont; import sun.java2d.SunGraphicsEnvironment; import sun.java2d.SurfaceManagerFactory; import sun.java2d.UnixSurfaceManagerFactory; @@ -62,9 +50,8 @@ import sun.java2d.xr.XRSurfaceData; * @see GraphicsDevice * @see GraphicsConfiguration */ -public class X11GraphicsEnvironment - extends SunGraphicsEnvironment -{ +public final class X11GraphicsEnvironment extends SunGraphicsEnvironment { + private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment"); private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment"); @@ -200,7 +187,7 @@ public class X11GraphicsEnvironment return new X11GraphicsDevice(screennum); } - protected native int getDefaultScreenNum(); + private native int getDefaultScreenNum(); /** * Returns the default screen graphics device. */ diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java index 444a2a66aaf..5fc2825306e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -35,16 +35,9 @@ import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.Window; -import java.awt.im.InputContext; import java.awt.im.InputMethodHighlight; import java.awt.im.spi.InputMethodContext; import sun.awt.im.InputMethodAdapter; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.FocusEvent; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowEvent; import java.awt.event.InputMethodEvent; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; @@ -1095,7 +1088,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { /* * Native methods */ - protected native String resetXIC(); + private native String resetXIC(); private native void disposeXIC(); private native boolean setCompositionEnabledNative(boolean enable); private native boolean isCompositionEnabledNative(); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java b/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java index 0be9eb49584..ee50f24a293 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -279,9 +279,9 @@ public final class Win32FontManager extends SunFontManager { }); } - protected static native void registerFontWithPlatform(String fontName); + private static native void registerFontWithPlatform(String fontName); - protected static native void deRegisterFontWithPlatform(String fontName); + private static native void deRegisterFontWithPlatform(String fontName); /** * populate the map with the most common windows fonts. diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java index 7235e4c0e24..85c1453b196 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java @@ -226,7 +226,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements * are disabled. Do not call this function with an index of 0. * @param index a PixelFormat index */ - protected native boolean isPixFmtSupported(int index, int screen); + private native boolean isPixFmtSupported(int index, int screen); /** * Returns the PixelFormatID of the default graphics configuration diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java index a1c57b6e555..ac54216bf2c 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -28,19 +28,11 @@ package sun.awt; import java.awt.AWTError; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Toolkit; import java.awt.peer.ComponentPeer; -import java.io.File; -import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.ListIterator; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; -import sun.awt.DisplayChangedListener; -import sun.awt.SunDisplayChanger; -import sun.awt.windows.WPrinterJob; + import sun.awt.windows.WToolkit; import sun.java2d.SunGraphicsEnvironment; import sun.java2d.SurfaceManagerFactory; @@ -57,9 +49,8 @@ import sun.java2d.windows.WindowsFlags; * @see GraphicsConfiguration */ -public class Win32GraphicsEnvironment - extends SunGraphicsEnvironment -{ +public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { + static { // Ensure awt is loaded already. Also, this forces static init // of WToolkit and Toolkit, which we depend upon @@ -91,7 +82,7 @@ public class Win32GraphicsEnvironment } protected native int getNumScreens(); - protected native int getDefaultScreen(); + private native int getDefaultScreen(); public GraphicsDevice getDefaultScreenDevice() { GraphicsDevice[] screens = getScreenDevices(); From c0d815c3d47f4a0754dc04411ae3925f9324cae6 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 19 May 2015 16:27:33 +0300 Subject: [PATCH 027/117] 7172652: With JDK 1.7 text field does not obtain focus when using mnemonic Alt/Key combin Reviewed-by: alexsch, azvegint --- .../javax/swing/plaf/basic/BasicLabelUI.java | 78 ++++++-- .../plaf/basic/BasicLabelUI/bug7172652.java | 172 ++++++++++++++++++ 2 files changed, 233 insertions(+), 17 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java index e5576c2aca9..8e99c38fa18 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLabelUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -504,7 +504,7 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener doPress(label); } else if (key == RELEASE) { - doRelease(label); + doRelease(label, e.getActionCommand() != null); } } @@ -517,33 +517,77 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener SwingUtilities.replaceUIInputMap(label, JComponent.WHEN_FOCUSED, inputMap); } int dka = label.getDisplayedMnemonic(); - inputMap.put(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), true), RELEASE); + putOnRelease(inputMap, dka, BasicLookAndFeel + .getFocusAcceleratorKeyMask()); // Need this when the sticky keys are enabled - inputMap.put(KeyStroke.getKeyStroke(dka, 0, true), RELEASE); + putOnRelease(inputMap, dka, 0); // Need this if ALT is released before the accelerator - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true), RELEASE); + putOnRelease(inputMap, KeyEvent.VK_ALT, 0); label.requestFocus(); } } - private void doRelease(JLabel label) { + private void doRelease(JLabel label, boolean isCommand) { Component labelFor = label.getLabelFor(); if (labelFor != null && labelFor.isEnabled()) { - InputMap inputMap = SwingUtilities.getUIInputMap(label, JComponent.WHEN_FOCUSED); - if (inputMap != null) { - // inputMap should never be null. + if (label.hasFocus()) { + InputMap inputMap = SwingUtilities.getUIInputMap(label, + JComponent.WHEN_FOCUSED); + if (inputMap != null) { + // inputMap should never be null. + int dka = label.getDisplayedMnemonic(); + removeOnRelease(inputMap, dka, BasicLookAndFeel + .getFocusAcceleratorKeyMask()); + removeOnRelease(inputMap, dka, 0); + removeOnRelease(inputMap, KeyEvent.VK_ALT, 0); + } + inputMap = SwingUtilities.getUIInputMap(label, + JComponent.WHEN_IN_FOCUSED_WINDOW); + if (inputMap == null) { + inputMap = new InputMapUIResource(); + SwingUtilities.replaceUIInputMap(label, + JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap); + } int dka = label.getDisplayedMnemonic(); - inputMap.remove(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), true)); - inputMap.remove(KeyStroke.getKeyStroke(dka, 0, true)); - inputMap.remove(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true)); - } - if (labelFor instanceof Container && - ((Container) labelFor).isFocusCycleRoot()) { - labelFor.requestFocus(); + if (isCommand) { + putOnRelease(inputMap, KeyEvent.VK_ALT, 0); + } else { + putOnRelease(inputMap, dka, BasicLookAndFeel + .getFocusAcceleratorKeyMask()); + // Need this when the sticky keys are enabled + putOnRelease(inputMap, dka, 0); + } + if (labelFor instanceof Container && + ((Container) labelFor).isFocusCycleRoot()) { + labelFor.requestFocus(); + } else { + SwingUtilities2.compositeRequestFocus(labelFor); + } } else { - SwingUtilities2.compositeRequestFocus(labelFor); + InputMap inputMap = SwingUtilities.getUIInputMap(label, + JComponent.WHEN_IN_FOCUSED_WINDOW); + int dka = label.getDisplayedMnemonic(); + if (inputMap != null) { + if (isCommand) { + removeOnRelease(inputMap, dka, BasicLookAndFeel + .getFocusAcceleratorKeyMask()); + removeOnRelease(inputMap, dka, 0); + } else { + removeOnRelease(inputMap, KeyEvent.VK_ALT, 0); + } + } } } } + + private void putOnRelease(InputMap inputMap, int keyCode, int modifiers) { + inputMap.put(KeyStroke.getKeyStroke(keyCode, modifiers, true), + RELEASE); + } + + private void removeOnRelease(InputMap inputMap, int keyCode, int modifiers) { + inputMap.remove(KeyStroke.getKeyStroke(keyCode, modifiers, true)); + } + } } diff --git a/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java b/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java new file mode 100644 index 00000000000..ea9999e86eb --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 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 7172652 + @summary With JDK 1.7 text field does not obtain focus when using mnemonic Alt/Key combin + @author Semyon Sadetsky + @library /lib/testlibrary + @build jdk.testlibrary.OSInfo + @run main bug7172652 + */ + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.KeyEvent; +import jdk.testlibrary.OSInfo; + +public class bug7172652 { + + private static JMenu menu; + private static JFrame frame; + private static Boolean selected; + + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("ok"); + return; + } + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + setup(); + } + }); + + test(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static void test() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + menu.getModel().addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + selected = menu.isSelected(); + } + }); + } + }); + + Robot robot = new Robot(); + robot.setAutoDelay(200); + + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + + robot.waitForIdle(); + if( selected != null ) { + throw new RuntimeException("Menu is notified selected= " + selected); + } + + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + if( selected != null ) { + throw new RuntimeException("Menu is notified selected= " + selected); + } + + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + if( selected != null ) { + throw new RuntimeException("Menu is notified selected= " + selected); + } + + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + if( selected != null ) { + throw new RuntimeException("Menu is notified selected= " + selected); + } + + robot.waitForIdle(); + + System.out.printf("ok"); + } + + private static void setup() { + JLabel firstLbl = new JLabel("First name"); + JLabel lastLbl = new JLabel("Last name"); + JMenuBar menuBar = new JMenuBar(); + + JTextField firstTxtFld = new JTextField(20); + JTextField lastTxtFld = new JTextField(20); + JDesktopPane desktopPane = new JDesktopPane(); + JInternalFrame iframe = new JInternalFrame("A frame", true, true, true, true); + + // Set an initial size + iframe.setSize(200, 220); + + // By default, internal frames are not visible; make it visible + iframe.setVisible(true); + + JPanel pane = new JPanel(); + pane.setLayout(new FlowLayout()); + + pane.add(firstLbl); + pane.add(firstTxtFld); + pane.add(lastLbl); + pane.add(lastTxtFld); + + firstLbl.setLabelFor(firstTxtFld); + firstLbl.setDisplayedMnemonic('F'); + + lastLbl.setLabelFor(lastTxtFld); + lastLbl.setDisplayedMnemonic('L'); + + iframe.getContentPane().add(pane); + iframe.setJMenuBar(menuBar); + menu = new JMenu("FirstMenu"); + //m.setMnemonic('i'); + menuBar.add(menu); + desktopPane.add(iframe); + + frame = new JFrame(); + frame.setUndecorated(true); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(desktopPane); + frame.setSize(300, 300); + frame.setVisible(true); + } + +} \ No newline at end of file From d349244b4574c880ac6df7b3e08822049726011a Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 19 May 2015 19:00:04 +0300 Subject: [PATCH 028/117] 6260348: GTK+ L&F JTextComponent not respecting desktop caret blink rate Reviewed-by: alexsch, azvegint --- .../sun/java/swing/plaf/gtk/GTKEngine.java | 6 ++-- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 14 ++++++++-- .../native/libawt_xawt/awt/gtk2_interface.c | 28 +++++++++---------- .../native/libawt_xawt/awt/gtk2_interface.h | 6 ++-- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 30b08313278..742a9f9ad1e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -93,7 +93,9 @@ class GTKEngine { */ static enum Settings { GTK_FONT_NAME, - GTK_ICON_SIZES + GTK_ICON_SIZES, + GTK_CURSOR_BLINK, + GTK_CURSOR_BLINK_TIME } /* Custom regions are needed for representing regions that don't exist diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index cfdd8672303..912e87e271c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -371,7 +371,17 @@ public class GTKLookAndFeel extends SynthLookAndFeel { int vProgWidth = 22 - (progXThickness * 2); int vProgHeight = 80 - (progYThickness * 2); - Integer caretBlinkRate = Integer.valueOf(500); + Integer caretBlinkRate; + if (Boolean.FALSE.equals(GTKEngine.INSTANCE.getSetting( + GTKEngine.Settings.GTK_CURSOR_BLINK))) { + caretBlinkRate = Integer.valueOf(0); + } else { + caretBlinkRate = (Integer) GTKEngine.INSTANCE.getSetting( + GTKEngine.Settings.GTK_CURSOR_BLINK_TIME); + if (caretBlinkRate == null) { + caretBlinkRate = Integer.valueOf(500); + } + } Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0); Double defaultCaretAspectRatio = new Double(0.025); diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index e8a45cb2059..e5711df06c3 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -1313,9 +1313,6 @@ static GtkWidget *gtk2_get_widget(WidgetType widget_type) { result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = (*fp_gtk_entry_new)(); - - GtkSettings* settings = fp_gtk_widget_get_settings(result); - fp_g_object_set(settings, "gtk-cursor-blink", FALSE, NULL); } result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; break; @@ -1360,10 +1357,6 @@ static GtkWidget *gtk2_get_widget(WidgetType widget_type) { gtk2_widgets[_GTK_ENTRY_TYPE] = (*fp_gtk_entry_new)(); - - GtkSettings* settings = - fp_gtk_widget_get_settings(gtk2_widgets[_GTK_ENTRY_TYPE]); - fp_g_object_set(settings, "gtk-cursor-blink", FALSE, NULL); } result = gtk2_widgets[_GTK_ENTRY_TYPE]; break; @@ -1555,9 +1548,6 @@ static GtkWidget *gtk2_get_widget(WidgetType widget_type) { result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] = (*fp_gtk_spin_button_new)(NULL, 0, 0); - - GtkSettings* settings = fp_gtk_widget_get_settings(result); - fp_g_object_set(settings, "gtk-cursor-blink", FALSE, NULL); } result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]; break; @@ -2507,14 +2497,20 @@ jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key return result; } -/* + jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; - + gint intval = NULL; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Integer(env, intval); -}*/ +} + +jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +{ + gint intval = NULL; + (*fp_g_object_get)(settings, key, &intval, NULL); + return create_Boolean(env, intval); +} jobject gtk2_get_setting(JNIEnv *env, Setting property) { @@ -2526,6 +2522,10 @@ jobject gtk2_get_setting(JNIEnv *env, Setting property) return get_string_property(env, settings, "gtk-font-name"); case GTK_ICON_SIZES: return get_string_property(env, settings, "gtk-icon-sizes"); + case GTK_CURSOR_BLINK: + return get_boolean_property(env, settings, "gtk-cursor-blink"); + case GTK_CURSOR_BLINK_TIME: + return get_integer_property(env, settings, "gtk-cursor-blink-time"); } return NULL; diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h index 3498e380813..5891a66d5ff 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -140,7 +140,9 @@ typedef enum _ColorType typedef enum _Setting { GTK_FONT_NAME, - GTK_ICON_SIZES + GTK_ICON_SIZES, + GTK_CURSOR_BLINK, + GTK_CURSOR_BLINK_TIME } Setting; /* GTK types, here to eliminate need for GTK headers at compile time */ From 36c9dc6b0d6e3a76eff3ab8261aa6c456b88d118 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 19 May 2015 21:58:47 +0300 Subject: [PATCH 029/117] 8080488: JNI exception pending in jdk/src/windows/native/sun/windows/awt_Frame.cpp Reviewed-by: dcherepanov, aivanov --- jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 6ac3c5f603b..2c25e975d39 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -1864,6 +1864,7 @@ Java_sun_awt_windows_WEmbeddedFrame_initIDs(JNIEnv *env, jclass cls) AwtFrame::activateEmbeddingTopLevelMID = env->GetMethodID(cls, "activateEmbeddingTopLevel", "()V"); DASSERT(AwtFrame::activateEmbeddingTopLevelMID != NULL); + CHECK_NULL(AwtFrame::activateEmbeddingTopLevelMID); AwtFrame::isEmbeddedInIEID = env->GetFieldID(cls, "isEmbeddedInIE", "Z"); DASSERT(AwtFrame::isEmbeddedInIEID != NULL); From c3e2e7af685f0d5e18c1c4039b8f45465a14ee39 Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Tue, 19 May 2015 20:40:49 -0500 Subject: [PATCH 030/117] 8078408: Java version applet hangs with Voice over turned on Add null check to fix NPE Reviewed-by: prr, serb, alexsch --- .../macosx/classes/sun/lwawt/macosx/CAccessibility.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 736a1ffbb25..d3ab6a651de 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -630,7 +630,7 @@ class CAccessibility implements PropertyChangeListener { if (!allowIgnored) { final AccessibleRole role = context.getAccessibleRole(); - if (role != null && ignoredRoles.contains(roleKey(role))) { + if (role != null && ignoredRoles != null && ignoredRoles.contains(roleKey(role))) { // Get the child's unignored children. _addChildren(child, whichChildren, false, childrenAndRoles); } else { From fc00fd2ffb4c5be2750376117a4044ed3734613e Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 20 May 2015 17:10:15 +0300 Subject: [PATCH 031/117] 8015368: javax/print/attribute/URLPDFPrinting.java fails on solaris with java.net.ConnectException: Connection timed out Reviewed-by: prr, serb --- .../javax/print/attribute/URLPDFPrinting.java | 117 ++++++++++++++++++ jdk/test/javax/print/attribute/hello.pdf | Bin 0 -> 11242 bytes 2 files changed, 117 insertions(+) create mode 100644 jdk/test/javax/print/attribute/URLPDFPrinting.java create mode 100644 jdk/test/javax/print/attribute/hello.pdf diff --git a/jdk/test/javax/print/attribute/URLPDFPrinting.java b/jdk/test/javax/print/attribute/URLPDFPrinting.java new file mode 100644 index 00000000000..6876bb72498 --- /dev/null +++ b/jdk/test/javax/print/attribute/URLPDFPrinting.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, 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 4899773 + * @summary Test for DocFlavor.URL.PDF support. No exception should be thrown. + * @run main URLPDFPrinting +*/ + +import java.awt.*; +import javax.print.*; +import javax.print.attribute.standard.*; +import javax.print.attribute.*; +import java.io.*; +import java.util.Locale; +import java.net.URL; + +public class URLPDFPrinting { + /** + * Constructor + */ + public URLPDFPrinting() { + super(); + } + /** + * Starts the application. + */ + public static void main(java.lang.String[] args) { + URLPDFPrinting pd = new URLPDFPrinting(); + PrintService service[] = null, defService = null; + + service = PrintServiceLookup.lookupPrintServices(DocFlavor.URL.PDF, null); + if (service.length == 0) { + System.out.println("No PrintService support DocFlavor.URL.PDF"); + return; + } else { + defService = service[0]; + System.out.println("Print Service which supports DocFlavor.URL.PDF: "+defService); + } + + System.out.println("is DocFlavor.URL.PDF supported? "+defService.isDocFlavorSupported(DocFlavor.URL.PDF)); + HashPrintRequestAttributeSet prSet = new HashPrintRequestAttributeSet(); + prSet.add(new Destination(new File("./dest.prn").toURI())); + + DocPrintJob pj = defService.createPrintJob(); + PrintDocument prDoc = new PrintDocument(); + try { + pj.print(prDoc, prSet); + } catch (Exception e) { + e.printStackTrace(); + } + + } +} + +class PrintDocument implements Doc { + InputStream fStream = null; + DocFlavor flavor = null; + HashDocAttributeSet docSet = new HashDocAttributeSet(); + URL url = null; + + public PrintDocument() { + try { + url = PrintDocument.class.getResource("hello.pdf"); + try{ Thread.sleep(6000); }catch(Exception e){ e.printStackTrace();} + fStream = url.openStream(); + System.out.println("URL input stream "+fStream); + } catch(Exception e) { + e.printStackTrace(); + } + docSet.add(OrientationRequested.LANDSCAPE); + } + + public DocAttributeSet getAttributes() { + System.out.println("getAttributes called"); + return docSet; + } + + public DocFlavor getDocFlavor() { + System.out.println("getDocFlavor called"); + return DocFlavor.URL.PDF; + } + + public Object getPrintData(){ + System.out.println("getPrintData called"); + return url; + } + + public Reader getReaderForText() { + return null; + } + + public InputStream getStreamForBytes() { + System.out.println("getStreamForBytes called"); + return fStream; + } +} diff --git a/jdk/test/javax/print/attribute/hello.pdf b/jdk/test/javax/print/attribute/hello.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d25b783a94007b0b477137241a3f1160cacabf08 GIT binary patch literal 11242 zcmeHNX*iVa+eelt*~=DVODbkD3>r(e>^qSx!wijWFoUu0Swr?+WsOiOOOZW0*^(`? zMAniJ;vMQ~dH%isyfIuH27`hXpkT0wC?5CE9q zKNjbVLfBJNU4LU?fuuDzw=j1mp+7Dv6Y!9(NrIey^cb(5QBEAEO#UY$=cxRLqH5G`OijPl0Q<0kL2e{N!5YSIZ|AZ9) z2Kmb&Q4mlUAT0Kqk>=*+D1wz%L?o0~$o1-uHeEQ*PEDd@abK&m?qzFTM;%~Z@9owR zZW^c@mPY;*55J5bF;NhXH0KYd9-#9*gVa$t1QLNm0KkWcX(6mpSinK>b-tk{M_9AN zSpUoy@Gox2VH|KM2OO4=c!wNv&KO5o4Bq&FL=+4Gz{DXYKy^ZvApT>PkWK{7@0xT_ zSd5FaB|$S-^iYrv21m#u0O*?y2S)v3z=5vs*8c&=?>Pa6`~n}ISRv{eRf7zzf@kei z{ME`7BlTDIO!cCm7#c%MF87$3{d&4%MLUy@RmTL63B=}5f?GPPs&41U@ZKxiz^Um~ zs0*+)7_cYB=qAS70)wWdecbLYwYLtY(--p?yxclsV(T@icutr)VCU4%W$EL>Vh*em=>bZvl#{|_M`p!46nP((XpaR3PPuZ$2D0TJ$H=r=qxEo^jg_P=JweH~ld zKoH~C^P4;K4jfmR!e5RIyW%YMHi_Pcbds|@IG38ZG68%TP5oj69VFx2UA396DjOo> z=P{{$TWX8=C6SmD0@_d@v?z*}7h2BEHc&KYy1_h@AZnP}XKZmyV_w&IE^L5BO5IXz zR=czj)TqFyF3%5>sTwR+AFu2{<<@^X8b#AwG%_!EoIS*XH?>Ny`IX~9<30F$@<@hA zRc&0I(W+$1K#Lu1LZDVyrQF*jxN!TP1kyYD~ zY~8Vkb&veoMiKSt{M^$1m~F0(C@bcE!?v3ZC%K;9WY{^&AM<3Y15= zqAgLEoe}PT+6({6OOTk@!LIx>dU)bseRVrFeOeCdp%aA-;YS|ppHJZ5yQ+YGOvy-p z?siFr1e$xOizY^g$$qHkD2WTjh^Ep$j~Io>z4F-DeAm^P_QmRj>VS9e2lz8p+OCUt%#u61pTj-Xa1*zM z`U*lmFk4NcRC6g`L@g@qEqkqas|qBJjdeVi=n);y?SO#pxR7-SQoMs}tMIq4r(|-{ zyKshh&Ew|5K5Sd{BkRZ$Tkr=bM@jnR$lfbWKosg>C*|AR&L?I>x;(;eJbW*V84@?} zaYcM4eR9ufcZ2(#u)Z&je#>ZbQ{56tRY`;II!05*E@84cXe&INS8e-XiZeBAmj7f? zKag0OCa_2u{CfR$Mi`WPNd_Hto_1^9M`$_QXQ=>5-$8du5%`L_FlV zhQ-lkzFXRffiD<4Sj-IXzYDLcRIT!E7rRFChH5u|Rb$O0n)aS?j>+V+Nweio4fGu$ zeyUL>GtXioo?Zw%+ag()6*Tz1*KmL5WtNrk#wSd(1eE+ZM_7?Yn z_Qwr-^egT?-R6De<09*=aat!txd2!|F)%j>&uLuPYkd*2Oj2DkR}Xs=Jd~F|RFD}t zHx{+c(c?LHlW$+YWA|Oxgv5n$*D-8pQI##0WMho?a%=I)#eK#{Tyb6|7k6ei#oNFI7_Y-fr0jZc}W#ZI^Br?s2^AIoj&oqWMGV-GJivD*q`F4!wLQduvisLqss zywUCBFp+zDz||(&#(f#F>|`&yIJkkPcx*occ;zQrxcs86+jZi#lZbnHtfXzPU6a+L zSayA;-R;o6I%`RxOx*}8+6sky9`b;K6DO=D_xszi!Bt8%0dJlRm@N27ob1sy7!Ofq zT}{5nmHD_+=}cBzZ0ow!4dEjxjgfTT*mijxL?!q6nQayR z-2S}5XK#Nce;rXY;6a+m;4)}ivr*`_()rqb{q1s1zsB;kYr^2pgN!H@=S}fTiq~|L zd@DVkFRhM7uRiQq9i8iF)405IM39!kr0&w!(|5`fZkxV3b&nEg#%2@ImPb<{Szi69 zkuEOy0+B;kd-=1W7s&SlL>bE~B5aB+{58b4-Jd_ye^ zUf|71qC=L<7-xp1&mR?Le~{IB{L?_Sq(3hv;A`bF*^cz^N;xObLUhUoN;g_=qo!PB zgP%XhY18j3r7<(QbNb;sVm4|?q*>ayt(o@i5nGSO`@VIiY8#`~9y^iT`QA^LtG!jM z3}s_K*@@feCLCBa!?O-<=kjAt!l+Z zG2pWTSfupn`|al(L!7eR6!i@-uKIZwpS@V=E@|!L-7D{(YMjcLVs|P`=CKOn=oQF| zXp2>bsCieY6qItO@F|o1I;XC@XduA%tO}sI&jlIzV zc)Hle*V0HmF^dyuJq?BzUjxB|KBXB~#7sq)QyO#?L_qP(ofIsb)VAiTHr6RsozRO9 zD;qZD^y6%*bmn$HpcK=_jK^tXHirY&^n$}i0^SsI~|m;*X$p7zDDr5zXm3Mf@zJ6BCTVTt)+NSvfRM)%Y;$UwUqlNMny)a-MX&c z46iaWD$+i@hDYz0dSrkdYUog#D1YoNcte4#~6QE#x*G5IcS9|ca@knDo`7L ztSm_A!J2N}3EHnQ^XYwxiSp8?H2lG3qTABfDD4*z!G<~a8KWArKd`eCQCDktog5?U zsbjgO-m{^@9I)v~qL%k4DFif7SBrpd3*8U8Qs7IG?q}jidmL&dm=oi||1_ITd4qo9 zIL&3VfG{mm4*+%B4Ub*8TIihk;%?>s|BiG3H!dUqD80ZoZPI z@uPIU!@i)r17eqhxe1L>S)Jut%?vS<;jE@Mo0bz}w7==9*rOq2*MHK&dzxIH+RClw-Sdivh zp_ZI&yV{N^vnmKu5gR>!pXYA)k3`?-F za}K9AFKqI!82gmh1xdXXzG=L>sf5kBxR!QZc|C4^6W63NnUf(9B4J3*^>kD;nOr*m z*=x;NqU8}~JVkfGtZt_tVk=XN2zrMp-$F1!;+o%iC#L6qmkZc+y}v~DDuM)6k?0G7 zA`h&}6I~ukmk9}Fq&0QTtxTTK67Q;MF_{wjNRri*{~=)){<^+&)=hV~v9_D$LoHKy z@UU!#W7Y$f%mWTRHPIkzc5m_Oy)BdKSMC!u&Q@}+r$+#Z}OFl zjT3E$oF@plN=B z{LMP-ajv1&!t2hhnP*ZqD+>$P7>Aj-73R+=Fi5tasIu_l9KI8I>=yc(Ch+q$cXdt7 z{d~9k{H&*QwNjH7KRjb!EA*R+tWA76z zY3x2#cON}znV9M5Xl^tOkV{G`VrMsfd7hyI1bZBI!Z5jL{X>UAQV-DhT2tIj?2g>| zneAZWTHyHm;^60U@Bo6Z8W{^pi}v>&#yB$0Aj22PNnl!|1~Lb z`)TWUwP9Dp_M?g-A=oQHS3S-lG5xM2SLo6h1s(_HERa*Eca)PJfjF?Z$bKaJXDO^? z+tF}@6}z@xy;4>5#M*_y|5yac5ra~FNiS3Z&2hu(llrY4l6G&dP31h3PKWVhqWTiW zy3#C{Pwmt8@2^z$rNXjylSdX5EQxLh_}OxN5xAIG6j9ka%$;i^5Rf^m5X4||DQEPW z!d_m)omF{*&xwnh3w0XtSJj3hY zT#_ANP@-kg+&ev=QgOFM`|b5y^Qmzg)f(txMalYEw1*msc~8w2ht0no;UUX}uVeO<)@T^}Lu6z9zCx(2_oS=FSP=YVCB;MI@YeqQO^Fy1^k6$p@&Y)_{qPSTZn(;xRH8;${sM>-ZaTr4~q*r(tR zk2LuVO=L|HHW@#X-=XY4#-x_7tz;H<*2B71szLb0Zr&~7wo#UI4GJ*Iw^MAF@UN)3 zu0h_t7YkBto1-UtYwQaTvW}LkT-rYB*|K|ve=erNlx;pJKi~rqCT^lD6vgnP({`--^n((KL3h1QCWsgYl|JwswoGpt?CtOsC-P1732~0^ zITtaToFlN#EyK&wNMs$xn1Wx)27Qp1sotVvze7h1^+8f!falv=(@9`7b3r&VG{MTPBSHbEIg*<9mzg?mHD=7wauRO*QjNcG+qH z4_9Q-%Sz~sj~8?O%lgXtrUY_%a>>3Zw?l%%gbGc(tzXXyTPtn}HyHDH+YL8YE!DNk zx=6xMvn$!3kH<5P@S&Y*Dla`Vt);G5ljSoI=DgB8q%!-|0iCu2z1W;VuenG~{B_)- z=y{s`Y*&`yp@R`ZLJfCTcmGzfLq!o%h0i)(G zZQWeQg0=b{M;A8rIRc$A(IrICO6?PjY|=r#W?AdW4-1tW3IZ-yug8 zzt~6r-0V&S_6tLjRlfu1YLVUDC0Jc){r; zmR0KyD+8o%H_UrknwqvcNsaT&yVAvsIv*RtQ+yp)(2>MY=S*!xO%gqY0Ka+8-;{ROXO*{vbwv5Fkc^_K$HpC(DuMAg^* zr1;(hI(-x>iqj*}k2RX}7vs^7k2(`{Gk1NSepanLWgYNl=;)@1sO&jJdg@fV9|6hk zWFzM2yNUy}BVmeXMnY=&DUM<&(Mad>X`Hh*cOXeJ|z5bZR=NvtuY?nk-M zhlsk$-J)mGvk9K0kGhf_yk^3?VXdm`ZM&)M>4k|R8G@&a5<`?YADxqQ4hs*B-}fMqFP2{n zcHsStENeM^o3Tu_gt$j}P{8{%u z9Z>u{pZI<*Dl8&SD0;Y9;0{YQ>T2Iky8o(9{5+X}OXD38mbNGyzyf8Bc97&=eOAj2 zKqDo&uZXCF)E(te*U?HI&L~|E4LwT_TT5{yx3m-$94~>lceE$eIskZkI|r-;UXmL@ zD1V_O2;+lkAUEKU1ZOMBed%BUV5qJIki$5m03t%7f|ejcK}-xR1Qvlo#6&ItARsUl z2!;?YK@dm+Dl9=*{{G^YIw<c93_B2H#avSH(?=+vo#Pb zE-nrPL4Xj5Ab~;<>+XO<-~}D9Jl}-;B}X2GwRA>1;?Niez=2$Z1;zy@$<6(fPhaN{4XS+i!NJ}8f4rPB(r~wjO0RD-OfX)v_2dvN`HbRyddmtX+NMHi}k;(BF zuYO}9ED)H4|Hwqpq^|zob=lhke*kcR0n$>!3gc{#z)2w-9qrJThyx^m1SN3b&!wMW z9MD@5ihG30efFo?gV0IXAsnnFx$%NXloi6o4#)jRTYeXEXv?3q9@v9Jpb-HcOkzZ zV~75uB~nT#J3GubFznEO6L<*G?-CEq`nz&CA?y-z2SGu}6W&sU8%RVD1Qmop^uQt# z5SRp5^eP2o?r`#1KeJl!ch+Uvhup{Vw-gGX1ix9cI^KSAjS&A)K{fa0GF{)OwGp!9?0U$}li z@lOW-!u3y3`a$#G;G+8Z$Vce3ljL?IJkb5&k@BDPQ;Gl8P9<{Cg9G{Bx~U-gAT5wC zNL2U1!(O*;VApwV(7n})1nTf=$sbl_N z)h~@ge<;L%>+<^1
    l03J4M9y|m8XOov+WEWL{46}k6%2k52J6alirDx2(zX{%(rO*X}7;K!m8{+%1? zp_7-`&pJQIsE6I_aJgfRvu|hhthy8}G#Vx5U+a(VgLX)f94Cs*l=$=qAb#mc_y<;Q>N8zmw+qj<05xZ3gEdYJ$OYmE5}X}HNFGA9;hf6{4RKcXW< Via^qne?a4xUQsYu^hdYo{{Tv1aaI5T literal 0 HcmV?d00001 From 83dcd6803343db6a37fcc7381a30b011db8c565b Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Fri, 22 May 2015 15:19:05 +0400 Subject: [PATCH 032/117] 8065739: [macosx] Frame warps to lower left of screen when 7124365: [macosx] setMaximizedBounds() should be implemented Reviewed-by: serb, azvegint --- .../classes/sun/lwawt/LWWindowPeer.java | 47 +++++- .../classes/sun/lwawt/PlatformWindow.java | 5 + .../sun/lwawt/macosx/CPlatformWindow.java | 18 ++- .../native/libawt_lwawt/awt/AWTWindow.h | 3 +- .../native/libawt_lwawt/awt/AWTWindow.m | 31 ++++ .../MaximizedToUnmaximized.java | 79 ++++++++++ .../MaximizedMovedWindow.java | 127 ++++++++++++++++ .../SetMaximizedBounds.java | 135 ++++++++++++------ 8 files changed, 387 insertions(+), 58 deletions(-) create mode 100644 jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java create mode 100644 jdk/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index fa6be35ad96..619675890e0 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -61,6 +61,7 @@ public class LWWindowPeer private static final int MINIMUM_HEIGHT = 1; private Insets insets = new Insets(0, 0, 0, 0); + private Rectangle maximizedBounds; private GraphicsDevice graphicsDevice; private GraphicsConfiguration graphicsConfig; @@ -176,8 +177,10 @@ public class LWWindowPeer if (getTarget() instanceof Frame) { - setTitle(((Frame) getTarget()).getTitle()); - setState(((Frame) getTarget()).getExtendedState()); + Frame frame = (Frame) getTarget(); + setTitle(frame.getTitle()); + setState(frame.getExtendedState()); + setMaximizedBounds(frame.getMaximizedBounds()); } else if (getTarget() instanceof Dialog) { setTitle(((Dialog) getTarget()).getTitle()); } @@ -543,9 +546,40 @@ public class LWWindowPeer return windowState; } + private boolean isMaximizedBoundsSet() { + synchronized (getStateLock()) { + return maximizedBounds != null; + } + } + + private Rectangle getDefaultMaximizedBounds() { + GraphicsConfiguration config = getGraphicsConfiguration(); + Insets screenInsets = ((CGraphicsDevice) config.getDevice()) + .getScreenInsets(); + Rectangle gcBounds = config.getBounds(); + return new Rectangle( + gcBounds.x + screenInsets.left, + gcBounds.y + screenInsets.top, + gcBounds.width - screenInsets.left - screenInsets.right, + gcBounds.height - screenInsets.top - screenInsets.bottom); + } + @Override public void setMaximizedBounds(Rectangle bounds) { - // TODO: not implemented + boolean isMaximizedBoundsSet; + synchronized (getStateLock()) { + this.maximizedBounds = (isMaximizedBoundsSet = (bounds != null)) + ? constrainBounds(bounds) : null; + } + + setPlatformMaximizedBounds(isMaximizedBoundsSet ? maximizedBounds + : getDefaultMaximizedBounds()); + } + + private void setPlatformMaximizedBounds(Rectangle bounds) { + platformWindow.setMaximizedBounds( + bounds.x, bounds.y, + bounds.width, bounds.height); } @Override @@ -635,6 +669,10 @@ public class LWWindowPeer // Second, update the graphics config and surface data final boolean isNewDevice = updateGraphicsDevice(); + if (isNewDevice && !isMaximizedBoundsSet()) { + setPlatformMaximizedBounds(getDefaultMaximizedBounds()); + } + if (resized || isNewDevice) { replaceSurfaceData(); updateMinimumSize(); @@ -1055,6 +1093,9 @@ public class LWWindowPeer public final void displayChanged() { if (updateGraphicsDevice()) { updateMinimumSize(); + if (!isMaximizedBoundsSet()) { + setPlatformMaximizedBounds(getDefaultMaximizedBounds()); + } } // Replace surface unconditionally, because internal state of the // GraphicsDevice could be changed. diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java index 93bd1928dbb..06bc5f48a83 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java @@ -66,6 +66,11 @@ public interface PlatformWindow { */ public void setBounds(int x, int y, int w, int h); + /* + * Sets the maximized bounds. + */ + public default void setMaximizedBounds(int x, int y, int w, int h){} + /* * Returns the graphics device where the window is. */ diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 043c08d5273..f89d27a2543 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -51,6 +51,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); private static native Insets nativeGetNSWindowInsets(long nsWindowPtr); private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h); + private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr, + double x, double y, double w, double h); private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH); private static native void nativePushNSWindowToBack(long nsWindowPtr); private static native void nativePushNSWindowToFront(long nsWindowPtr); @@ -474,6 +476,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h); } + public void setMaximizedBounds(int x, int y, int w, int h) { + nativeSetNSWindowStandardFrame(getNSWindowPtr(), x, y, w, h); + } + private boolean isMaximized() { return undecorated ? this.normalBounds != null : CWrapper.NSWindow.isZoomed(getNSWindowPtr()); @@ -979,13 +985,11 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo } private void checkZoom() { - if (target instanceof Frame && isVisible()) { - Frame targetFrame = (Frame)target; - if (targetFrame.getExtendedState() != Frame.MAXIMIZED_BOTH && isMaximized()) { - deliverZoom(true); - } else if (targetFrame.getExtendedState() == Frame.MAXIMIZED_BOTH && !isMaximized()) { - deliverZoom(false); - } + int state = peer.getState(); + if (state != Frame.MAXIMIZED_BOTH && isMaximized()) { + deliverZoom(true); + } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) { + deliverZoom(false); } } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h index 7f7bac777bc..7b8fa5e6477 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h @@ -46,6 +46,7 @@ NSWindow *nsWindow; AWTWindow *ownerWindow; jint preFullScreenLevel; + NSRect standardFrame; } // An instance of either AWTWindow_Normal or AWTWindow_Panel @@ -59,7 +60,7 @@ @property (nonatomic) jint styleBits; @property (nonatomic) BOOL isEnabled; @property (nonatomic) jint preFullScreenLevel; - +@property (nonatomic) NSRect standardFrame; - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)javaPlatformWindow ownerWindow:owner diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index 47442027e02..749c64b54be 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -184,6 +184,7 @@ AWT_NS_WINDOW_IMPLEMENTATION @synthesize isEnabled; @synthesize ownerWindow; @synthesize preFullScreenLevel; +@synthesize standardFrame; - (void) updateMinMaxSize:(BOOL)resizable { if (resizable) { @@ -509,6 +510,12 @@ AWT_ASSERT_APPKIT_THREAD; // window exposing in _setVisible:(BOOL) } +- (NSRect)windowWillUseStandardFrame:(NSWindow *)window + defaultFrame:(NSRect)newFrame { + + return [self standardFrame]; +} + - (void) _deliverIconify:(BOOL)iconify { AWT_ASSERT_APPKIT_THREAD; @@ -951,6 +958,30 @@ JNF_COCOA_ENTER(env); JNF_COCOA_EXIT(env); } +/* + * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeSetNSWindowStandardFrame + * Signature: (JDDDD)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame +(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, + jdouble width, jdouble height) +{ + JNF_COCOA_ENTER(env); + + NSRect jrect = NSMakeRect(originX, originY, width, height); + + NSWindow *nsWindow = OBJC(windowPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + + NSRect rect = ConvertNSScreenRect(NULL, jrect); + AWTWindow *window = (AWTWindow*)[nsWindow delegate]; + window.standardFrame = rect; + }]; + + JNF_COCOA_EXIT(env); +} + /* * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSetNSWindowMinMax diff --git a/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java b/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java new file mode 100644 index 00000000000..b77ff712cd0 --- /dev/null +++ b/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 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. + */ +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; + +/** + * @test + * @bug 8065739 + * @summary [macosx] Frame warps to lower left of screen when displayed + * @author Alexandr Scherbatiy + */ +public class MaximizedToUnmaximized { + + public static void main(String[] args) throws Exception { + testFrame(false); + testFrame(true); + } + + static void testFrame(boolean isUndecorated) throws Exception { + Frame frame = new Frame(); + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + + frame.setUndecorated(isUndecorated); + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + int x = bounds.x + insets.left; + int y = bounds.y + insets.top; + int width = bounds.width - insets.left - insets.right; + int height = bounds.height - insets.top - insets.bottom; + Rectangle rect = new Rectangle(x, y, width, height); + frame.pack(); + frame.setBounds(rect); + frame.setVisible(true); + robot.waitForIdle(); + robot.delay(500); + + if (frame.getWidth() <= width / 2 + || frame.getHeight() <= height / 2) { + throw new RuntimeException("Frame size is small!"); + } + + if (!isUndecorated && frame.getExtendedState() != Frame.MAXIMIZED_BOTH) { + throw new RuntimeException("Frame state does not equal" + + " MAXIMIZED_BOTH!"); + } + } finally { + frame.dispose(); + } + } +} \ No newline at end of file diff --git a/jdk/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java b/jdk/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java new file mode 100644 index 00000000000..8632de10186 --- /dev/null +++ b/jdk/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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. + */ +import java.awt.*; + +/* + * @test + * @bug 8065739 + * @summary Moved window is maximazed to new screen + * @author Alexandr Scherbatiy + * + * @run main MaximizedMovedWindow + */ +public class MaximizedMovedWindow { + + public static void main(String[] args) throws Exception { + + //Supported platforms are Windows and OS X. + String os = System.getProperty("os.name").toLowerCase(); + if (!os.contains("os x")) { + return; + } + + if (!Toolkit.getDefaultToolkit(). + isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { + return; + } + + GraphicsEnvironment ge = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + + if (ge.isHeadlessInstance()) { + return; + } + + GraphicsDevice[] devices = ge.getScreenDevices(); + + if (devices.length < 2) { + return; + } + + Frame frame = null; + try { + + GraphicsConfiguration gc1 = devices[0].getDefaultConfiguration(); + GraphicsConfiguration gc2 = devices[1].getDefaultConfiguration(); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + frame = new Frame(); + Rectangle maxArea1 = getMaximizedScreenArea(gc1); + frame.setBounds(getSmallerRectangle(maxArea1)); + frame.setVisible(true); + robot.waitForIdle(); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle bounds = frame.getBounds(); + if (!bounds.equals(maxArea1)) { + throw new RuntimeException("The bounds of the Frame do not equal" + + " to screen 1 size"); + } + + frame.setExtendedState(Frame.NORMAL); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle maxArea2 = getMaximizedScreenArea(gc2); + frame.setBounds(getSmallerRectangle(maxArea2)); + robot.waitForIdle(); + robot.delay(1000); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + bounds = frame.getBounds(); + if (!bounds.equals(maxArea2)) { + throw new RuntimeException("The bounds of the Frame do not equal" + + " to screen 2 size"); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + } + + static Rectangle getSmallerRectangle(Rectangle rect) { + return new Rectangle( + rect.x + rect.width / 6, + rect.y + rect.height / 6, + rect.width / 3, + rect.height / 3); + } + static Rectangle getMaximizedScreenArea(GraphicsConfiguration gc) { + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + return new Rectangle( + bounds.x + insets.left, + bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); + } +} diff --git a/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java b/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java index da5b3800eae..613e662bcae 100644 --- a/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java +++ b/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -22,67 +22,108 @@ */ import java.awt.*; - /* * @test * @summary When Frame.setExtendedState(Frame.MAXIMIZED_BOTH) * is called for a Frame after been called setMaximizedBounds() with * certain value, Frame bounds must equal to this value. * - * @library ../../../../lib/testlibrary - * @build ExtendedRobot * @run main SetMaximizedBounds */ public class SetMaximizedBounds { - Frame frame; - Rectangle bound; - boolean supported; - ExtendedRobot robot; - static Rectangle max = new Rectangle(100,100,400,400); + public static void main(String[] args) throws Exception { - public void doTest() throws Exception { - robot = new ExtendedRobot(); - - EventQueue.invokeAndWait( () -> { - frame = new Frame( "TestFrame "); - frame.setLayout(new FlowLayout()); - - if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { - supported = true; - frame.setMaximizedBounds(max); - } else { - supported = false; - } - - frame.setSize(200, 200); - frame.setVisible(true); - }); - - robot.waitForIdle(2000); - if (supported) { - EventQueue.invokeAndWait( () -> { - frame.setExtendedState(Frame.MAXIMIZED_BOTH); - }); - robot.waitForIdle(2000); - bound = frame.getBounds(); - if(!bound.equals(max)) - throw new RuntimeException("The bounds of the Frame do not equal to what" - + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); - } else { - System.out.println("Frame.MAXIMIZED_BOTH not supported"); + //Supported platforms are Windows and OS X. + String os = System.getProperty("os.name").toLowerCase(); + if (!os.contains("windows") && !os.contains("os x")) { + return; } - frame.dispose(); + if (!Toolkit.getDefaultToolkit(). + isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { + return; + } + + GraphicsEnvironment ge = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + + if (ge.isHeadlessInstance()) { + return; + } + + for (GraphicsDevice gd : ge.getScreenDevices()) { + for (GraphicsConfiguration gc : gd.getConfigurations()) { + testMaximizedBounds(gc); + } + } } - public static void main(String[] args) throws Exception { - String os = System.getProperty("os.name").toLowerCase(); - System.out.println(os); - if (os.contains("windows") || os.contains("os x")) - new SetMaximizedBounds().doTest(); - else - System.out.println("Platform "+os+" is not supported. Supported platforms are Windows and OS X."); + static void testMaximizedBounds(GraphicsConfiguration gc) throws Exception { + + Frame frame = null; + try { + + Rectangle maxArea = getMaximizedScreenArea(gc); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + frame = new Frame(); + Rectangle maximizedBounds = new Rectangle( + maxArea.x + maxArea.width / 6, + maxArea.y + maxArea.height / 6, + maxArea.width / 3, + maxArea.height / 3); + frame.setMaximizedBounds(maximizedBounds); + frame.setSize(maxArea.width / 8, maxArea.height / 8); + frame.setVisible(true); + robot.waitForIdle(); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle bounds = frame.getBounds(); + if (!bounds.equals(maximizedBounds)) { + throw new RuntimeException("The bounds of the Frame do not equal to what" + + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); + } + + frame.setExtendedState(Frame.NORMAL); + robot.waitForIdle(); + robot.delay(1000); + + maximizedBounds = new Rectangle( + maxArea.x + maxArea.width / 10, + maxArea.y + maxArea.height / 10, + maxArea.width / 5, + maxArea.height / 5); + frame.setMaximizedBounds(maximizedBounds); + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + bounds = frame.getBounds(); + if (!bounds.equals(maximizedBounds)) { + throw new RuntimeException("The bounds of the Frame do not equal to what" + + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + } + + static Rectangle getMaximizedScreenArea(GraphicsConfiguration gc) { + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + return new Rectangle( + bounds.x + insets.left, + bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); } } From 2e68b719a3aa01baa727ab4175d8d82393e72161 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Fri, 22 May 2015 15:27:28 +0400 Subject: [PATCH 033/117] 8080137: Dragged events for extra mouse buttons (4, 5, 6) are not generated on JSplitPane Reviewed-by: serb, azvegint --- .../share/classes/java/awt/Container.java | 33 +++--- .../MouseDragEvent/MouseDraggedTest.java | 103 ++++++++++++++++++ 2 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/Container.java b/jdk/src/java.desktop/share/classes/java/awt/Container.java index cbd01b957ee..5b8d28dea04 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Container.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java @@ -4420,6 +4420,18 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher"); + private static final int BUTTONS_DOWN_MASK; + + static { + int[] buttonsDownMask = AWTAccessor.getInputEventAccessor(). + getButtonDownMasks(); + int mask = 0; + for (int buttonDownMask : buttonsDownMask) { + mask |= buttonDownMask; + } + BUTTONS_DOWN_MASK = mask; + } + LightweightDispatcher(Container nativeContainer) { this.nativeContainer = nativeContainer; mouseEventTarget = new WeakReference<>(null); @@ -4488,25 +4500,12 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { private boolean isMouseGrab(MouseEvent e) { int modifiers = e.getModifiersEx(); - if(e.getID() == MouseEvent.MOUSE_PRESSED - || e.getID() == MouseEvent.MOUSE_RELEASED) - { - switch (e.getButton()) { - case MouseEvent.BUTTON1: - modifiers ^= InputEvent.BUTTON1_DOWN_MASK; - break; - case MouseEvent.BUTTON2: - modifiers ^= InputEvent.BUTTON2_DOWN_MASK; - break; - case MouseEvent.BUTTON3: - modifiers ^= InputEvent.BUTTON3_DOWN_MASK; - break; - } + if (e.getID() == MouseEvent.MOUSE_PRESSED + || e.getID() == MouseEvent.MOUSE_RELEASED) { + modifiers ^= InputEvent.getMaskForButton(e.getButton()); } /* modifiers now as just before event */ - return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK - | InputEvent.BUTTON2_DOWN_MASK - | InputEvent.BUTTON3_DOWN_MASK)) != 0); + return ((modifiers & BUTTONS_DOWN_MASK) != 0); } /** diff --git a/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java b/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java new file mode 100644 index 00000000000..272b21144d3 --- /dev/null +++ b/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +/* + * @test + * @bug 8080137 + * @summary Dragged events for extra mouse buttons (4,5,6) are not generated + * on JSplitPane + * @author alexandr.scherbatiy area=awt.event + * @run main MouseDraggedTest + */ +public class MouseDraggedTest { + + private static JFrame frame; + private static Rectangle frameBounds; + private static volatile boolean mouseDragged; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(MouseDraggedTest::createAndShowGUI); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> frameBounds = frame.getBounds()); + robot.waitForIdle(); + + for (int i = 1; i <= MouseInfo.getNumberOfButtons(); i++) { + testMouseDrag(i, robot); + } + } finally { + SwingUtilities.invokeLater(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void testMouseDrag(int button, Robot robot) { + + mouseDragged = false; + int x1 = frameBounds.x + frameBounds.width / 4; + int y1 = frameBounds.y + frameBounds.height / 4; + int x2 = frameBounds.x + frameBounds.width / 2; + int y2 = frameBounds.y + frameBounds.height / 2; + + robot.mouseMove(x1, y1); + robot.waitForIdle(); + + int buttonMask = InputEvent.getMaskForButton(button); + robot.mousePress(buttonMask); + robot.mouseMove(x2, y2); + robot.mouseRelease(buttonMask); + robot.waitForIdle(); + + if (!mouseDragged) { + throw new RuntimeException("Mouse button " + button + + " is not dragged"); + } + } + + static void createAndShowGUI() { + + frame = new JFrame(); + frame.setSize(400, 400); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel panel = new JPanel(new BorderLayout()); + panel.addMouseMotionListener(new MouseAdapter() { + + @Override + public void mouseDragged(MouseEvent e) { + mouseDragged = true; + } + }); + frame.add(panel, BorderLayout.CENTER); + frame.setVisible(true); + } +} \ No newline at end of file From 4f33aa2348b697da34d827e24c6f644db4dbc6b2 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 16 May 2015 21:31:36 +0300 Subject: [PATCH 034/117] 8041654: OutOfMemoryError: RepaintManager doesn't clean up cache of volatile images Reviewed-by: azvegint, ant --- .../classes/javax/swing/RepaintManager.java | 26 ++++-- .../unix/classes/sun/awt/X11/XToolkit.java | 48 +++++++---- .../DisplayListenerLeak.java | 82 +++++++++++++++++++ 3 files changed, 132 insertions(+), 24 deletions(-) create mode 100644 jdk/test/javax/swing/RepaintManager/DisplayListenerLeak/DisplayListenerLeak.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java index bc50cb734a6..5f7755a159b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -182,9 +182,16 @@ public class RepaintManager */ private final ProcessingRunnable processingRunnable; - private final static JavaSecurityAccess javaSecurityAccess = - SharedSecrets.getJavaSecurityAccess(); + private static final JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + /** + * Listener installed to detect display changes. When display changes, + * schedules a callback to notify all RepaintManagers of the display + * changes. + */ + private static final DisplayChangedListener displayChangedHandler = + new DisplayChangedHandler(); static { SwingAccessor.setRepaintManagerAccessor(new SwingAccessor.RepaintManagerAccessor() { @@ -226,8 +233,8 @@ public class RepaintManager GraphicsEnvironment ge = GraphicsEnvironment. getLocalGraphicsEnvironment(); if (ge instanceof SunGraphicsEnvironment) { - ((SunGraphicsEnvironment)ge).addDisplayChangedListener( - new DisplayChangedHandler()); + ((SunGraphicsEnvironment) ge).addDisplayChangedListener( + displayChangedHandler); } Toolkit tk = Toolkit.getDefaultToolkit(); if ((tk instanceof SunToolkit) @@ -1679,6 +1686,12 @@ public class RepaintManager */ private static final class DisplayChangedHandler implements DisplayChangedListener { + // Empty non private constructor was added because access to this + // class shouldn't be generated by the compiler using synthetic + // accessor method + DisplayChangedHandler() { + } + public void displayChanged() { scheduleDisplayChanges(); } @@ -1686,11 +1699,10 @@ public class RepaintManager public void paletteChanged() { } - private void scheduleDisplayChanges() { + private static void scheduleDisplayChanges() { // To avoid threading problems, we notify each RepaintManager // on the thread it was created on. - for (Object c : AppContext.getAppContexts()) { - AppContext context = (AppContext) c; + for (AppContext context : AppContext.getAppContexts()) { synchronized(context) { if (!context.isDisposed()) { EventQueue eventQueue = (EventQueue)context.get( diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 4da0bb5032b..32b2d8bccaf 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -616,14 +616,19 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } } } - if( keyEventLog.isLoggable(PlatformLogger.Level.FINE) && (ev.get_type() == XConstants.KeyPress || ev.get_type() == XConstants.KeyRelease) ) { - keyEventLog.fine("before XFilterEvent:"+ev); + if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && ( + ev.get_type() == XConstants.KeyPress + || ev.get_type() == XConstants.KeyRelease)) { + keyEventLog.fine("before XFilterEvent:" + ev); } if (XlibWrapper.XFilterEvent(ev.getPData(), w)) { continue; } - if( keyEventLog.isLoggable(PlatformLogger.Level.FINE) && (ev.get_type() == XConstants.KeyPress || ev.get_type() == XConstants.KeyRelease) ) { - keyEventLog.fine("after XFilterEvent:"+ev); // IS THIS CORRECT? + if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && ( + ev.get_type() == XConstants.KeyPress + || ev.get_type() == XConstants.KeyRelease)) { + keyEventLog.fine( + "after XFilterEvent:" + ev); // IS THIS CORRECT? } dispatchEvent(ev); @@ -639,21 +644,28 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } } + /** + * Listener installed to detect display changes. + */ + private static final DisplayChangedListener displayChangedHandler = + new DisplayChangedListener() { + @Override + public void displayChanged() { + // 7045370: Reset the cached values + XToolkit.screenWidth = -1; + XToolkit.screenHeight = -1; + } + + @Override + public void paletteChanged() { + } + }; + static { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); if (ge instanceof SunGraphicsEnvironment) { - ((SunGraphicsEnvironment)ge).addDisplayChangedListener( - new DisplayChangedListener() { - @Override - public void displayChanged() { - // 7045370: Reset the cached values - XToolkit.screenWidth = -1; - XToolkit.screenHeight = -1; - } - - @Override - public void paletteChanged() {} - }); + ((SunGraphicsEnvironment) ge).addDisplayChangedListener( + displayChangedHandler); } } @@ -663,7 +675,9 @@ public final class XToolkit extends UNIXToolkit implements Runnable { try { XWindowAttributes pattr = new XWindowAttributes(); try { - XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), pattr.pData); + XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), + XToolkit.getDefaultRootWindow(), + pattr.pData); screenWidth = pattr.get_width(); screenHeight = pattr.get_height(); } finally { diff --git a/jdk/test/javax/swing/RepaintManager/DisplayListenerLeak/DisplayListenerLeak.java b/jdk/test/javax/swing/RepaintManager/DisplayListenerLeak/DisplayListenerLeak.java new file mode 100644 index 00000000000..ea924bb5541 --- /dev/null +++ b/jdk/test/javax/swing/RepaintManager/DisplayListenerLeak/DisplayListenerLeak.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.GraphicsEnvironment; + +import javax.swing.JFrame; +import javax.swing.JLabel; + +import sun.java2d.SunGraphicsEnvironment; + +/** + * @test + * @bug 8041654 + * @run main/othervm -Xmx80m DisplayListenerLeak + */ +public final class DisplayListenerLeak { + + private static JFrame frame; + private volatile static boolean failed = false; + + private static void createAndShowGUI() { + Thread.currentThread().setUncaughtExceptionHandler((t, e) -> { + e.printStackTrace(); + failed = true; + }); + frame = new JFrame(); + JLabel emptyLabel = new JLabel(""); + emptyLabel.setPreferredSize(new Dimension(600, 400)); + frame.getContentPane().add(emptyLabel, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } + + public static void main(final String[] args) throws Exception { + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (!(ge instanceof SunGraphicsEnvironment)) { + return; + } + EventQueue.invokeAndWait(() -> createAndShowGUI()); + SunGraphicsEnvironment sge = (SunGraphicsEnvironment) ge; + final long startTime = System.nanoTime(); + while (!failed) { + if (System.nanoTime() - startTime > 60_000_000_000L) { + break; + } + System.gc(); // clear all weak references + EventQueue.invokeAndWait(() -> { + frame.setSize(frame.getHeight(), frame.getWidth()); + frame.pack(); + }); + EventQueue.invokeAndWait(sge::displayChanged); + } + EventQueue.invokeAndWait(frame::dispose); + if (failed) { + throw new RuntimeException(); + } + } +} \ No newline at end of file From c55c7818a4faf929f78fee63ae0482c495868a94 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Fri, 22 May 2015 09:09:56 +0200 Subject: [PATCH 035/117] 8066757: Can't build 'images' with --disable-zip-debug-info on OS X after jigsaw m2 merge Reviewed-by: erikj, ihse --- make/StripBinaries.gmk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make/StripBinaries.gmk b/make/StripBinaries.gmk index 17153130574..c7fb8f105f1 100644 --- a/make/StripBinaries.gmk +++ b/make/StripBinaries.gmk @@ -61,9 +61,12 @@ STRIP_CMDS_SRC := $(filter-out $(COPY_CMDS_SRC), $(ALL_CMDS_SRC)) COPY_LIBS_SRC := \ $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs \ \( ! -name '*$(SHARED_LIBRARY_SUFFIX)' -type f \) -o -type l) +# OS X stores symbol information in a .dylib file inside a .dSYM directory - +# that file should not be stripped, so we prune the tree at the .dSYM directory. +# Example: support/modules_libs/java.base/libjsig.dylib.dSYM/Contents/Resources/DWARF/libjsig.dylib STRIP_LIBS_SRC := \ $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs \ - -name '*$(SHARED_LIBRARY_SUFFIX)' -type f) + -name '*$(SHARED_LIBRARY_SUFFIX)' -type f -print -o -name "*.dSYM" -prune) $(eval $(call SetupCopyFiles,STRIP_MODULES_CMDS, \ SRC := $(SUPPORT_OUTPUTDIR)/modules_cmds, \ From 13711e78f09509ab216db83e33be0d0b6c6aec7d Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 22 May 2015 19:27:33 +0300 Subject: [PATCH 036/117] 8071306: GUI perfomance are very slow compared java 1.6.0_45 Reviewed-by: azvegint, ant --- .../share/classes/java/awt/Component.java | 23 +++- .../share/classes/java/awt/Container.java | 105 +++++++++--------- .../SetEnabledPerformance.java | 72 ++++++++++++ 3 files changed, 145 insertions(+), 55 deletions(-) create mode 100644 jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java index 84ae7652c55..99b2d570bd7 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java @@ -1311,6 +1311,25 @@ public abstract class Component implements ImageObserver, MenuContainer, return visible && (parent == null || parent.isRecursivelyVisible()); } + /** + * Determines the bounds of a visible part of the component relative to its + * parent. + * + * @return the visible part of bounds + */ + private Rectangle getRecursivelyVisibleBounds() { + final Component container = getContainer(); + final Rectangle bounds = getBounds(); + if (container == null) { + // we are top level window or haven't a container, return our bounds + return bounds; + } + // translate the container's bounds to our coordinate space + final Rectangle parentsBounds = container.getRecursivelyVisibleBounds(); + parentsBounds.setLocation(0, 0); + return parentsBounds.intersection(bounds); + } + /** * Translates absolute coordinates into coordinates in the coordinate * space of this component. @@ -1487,7 +1506,7 @@ public abstract class Component implements ImageObserver, MenuContainer, ComponentPeer peer = this.peer; if (peer != null) { peer.setEnabled(true); - if (visible) { + if (visible && !getRecursivelyVisibleBounds().isEmpty()) { updateCursorImmediately(); } } @@ -1541,7 +1560,7 @@ public abstract class Component implements ImageObserver, MenuContainer, ComponentPeer peer = this.peer; if (peer != null) { peer.setEnabled(false); - if (visible) { + if (visible && !getRecursivelyVisibleBounds().isEmpty()) { updateCursorImmediately(); } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/Container.java b/jdk/src/java.desktop/share/classes/java/awt/Container.java index 5b8d28dea04..0ed78e598df 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Container.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java @@ -44,6 +44,7 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.security.AccessController; +import java.util.ArrayList; import java.util.EventListener; import java.util.HashSet; import java.util.Set; @@ -100,7 +101,7 @@ public class Container extends Component { * @see #add * @see #getComponents */ - private java.util.List component = new java.util.ArrayList(); + private java.util.List component = new ArrayList<>(); /** * Layout manager for this container. @@ -2568,28 +2569,24 @@ public class Container extends Component { if (!contains(x, y)) { return null; } + Component lightweight = null; synchronized (getTreeLock()) { - // Two passes: see comment in sun.awt.SunGraphicsCallback - for (int i = 0; i < component.size(); i++) { - Component comp = component.get(i); - if (comp != null && - !(comp.peer instanceof LightweightPeer)) { - if (comp.contains(x - comp.x, y - comp.y)) { + // Optimized version of two passes: + // see comment in sun.awt.SunGraphicsCallback + for (final Component comp : component) { + if (comp.contains(x - comp.x, y - comp.y)) { + if (!comp.isLightweight()) { + // return heavyweight component as soon as possible return comp; } - } - } - for (int i = 0; i < component.size(); i++) { - Component comp = component.get(i); - if (comp != null && - comp.peer instanceof LightweightPeer) { - if (comp.contains(x - comp.x, y - comp.y)) { - return comp; + if (lightweight == null) { + // save and return later the first lightweight component + lightweight = comp; } } } } - return this; + return lightweight != null ? lightweight : this; } /** @@ -2693,52 +2690,54 @@ public class Container extends Component { return null; } - final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){ - checkTreeLock(); + final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled) { + // checkTreeLock(); commented for a performance reason if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) { return null; } - - // Two passes: see comment in sun.awt.SunGraphicsCallback - for (int i = 0; i < component.size(); i++) { - Component comp = component.get(i); - if (comp != null && - !(comp.peer instanceof LightweightPeer)) { - if (comp instanceof Container) { - comp = ((Container)comp).findComponentAtImpl(x - comp.x, - y - comp.y, - ignoreEnabled); - } else { - comp = comp.getComponentAt(x - comp.x, y - comp.y); + Component lightweight = null; + // Optimized version of two passes: + // see comment in sun.awt.SunGraphicsCallback + for (final Component comp : component) { + final int x1 = x - comp.x; + final int y1 = y - comp.y; + if (!comp.contains(x1, y1)) { + continue; // fast path + } + if (!comp.isLightweight()) { + final Component child = getChildAt(comp, x1, y1, ignoreEnabled); + if (child != null) { + // return heavyweight component as soon as possible + return child; } - if (comp != null && comp.visible && - (ignoreEnabled || comp.enabled)) - { - return comp; - } - } - } - for (int i = 0; i < component.size(); i++) { - Component comp = component.get(i); - if (comp != null && - comp.peer instanceof LightweightPeer) { - if (comp instanceof Container) { - comp = ((Container)comp).findComponentAtImpl(x - comp.x, - y - comp.y, - ignoreEnabled); - } else { - comp = comp.getComponentAt(x - comp.x, y - comp.y); - } - if (comp != null && comp.visible && - (ignoreEnabled || comp.enabled)) - { - return comp; + } else { + if (lightweight == null) { + // save and return later the first lightweight component + lightweight = getChildAt(comp, x1, y1, ignoreEnabled); } } } + return lightweight != null ? lightweight : this; + } - return this; + /** + * Helper method for findComponentAtImpl. Finds a child component using + * findComponentAtImpl for Container and getComponentAt for Component. + */ + private static Component getChildAt(Component comp, int x, int y, + boolean ignoreEnabled) { + if (comp instanceof Container) { + comp = ((Container) comp).findComponentAtImpl(x, y, + ignoreEnabled); + } else { + comp = comp.getComponentAt(x, y); + } + if (comp != null && comp.visible && + (ignoreEnabled || comp.enabled)) { + return comp; + } + return null; } /** diff --git a/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java b/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java new file mode 100644 index 00000000000..c898ef7ef4b --- /dev/null +++ b/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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. + */ + +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Robot; + +import javax.swing.JButton; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8071306 + * @author Sergey Bylokhov + */ +public final class SetEnabledPerformance { + + private static Frame frame; + + private static void createAndShowGUI() { + frame = new Frame(); + frame.setLayout(new FlowLayout(FlowLayout.CENTER, 25, 0)); + frame.setSize(600, 600); + frame.setLocationRelativeTo(null); + for (int i = 1; i < 10001; ++i) { + frame.add(new JButton("Button " + i)); + } + frame.setVisible(true); + } + + public static void main(final String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> createAndShowGUI()); + final Robot robot = new Robot(); + robot.waitForIdle(); + robot.mouseMove(frame.getX() + 15, frame.getY() + 300); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + long m = System.currentTimeMillis(); + for (final Component comp : frame.getComponents()) { + comp.setEnabled(false); + } + m = System.currentTimeMillis() - m; + System.err.println("Disabled in " + m + " ms"); + frame.dispose(); + // we should be much faster, but leaves 1000 for the slow systems + if (m > 1000) { + throw new RuntimeException("Too slow"); + } + }); + } +} \ No newline at end of file From b081f20d610dbeb25de006931580f6d2b623fda2 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 22 May 2015 23:26:00 +0300 Subject: [PATCH 037/117] 6587235: Incorrect javadoc: "no parameter" in 2d source code Reviewed-by: azvegint, prr --- .../classes/sun/applet/AppletClassLoader.java | 4 +-- .../classes/sun/applet/AppletSecurity.java | 4 +-- .../share/classes/sun/awt/AppContext.java | 4 +-- .../share/classes/sun/awt/EmbeddedFrame.java | 6 ---- .../share/classes/sun/awt/SunToolkit.java | 8 +++--- .../sun/awt/datatransfer/SunClipboard.java | 6 ++-- .../classes/sun/awt/geom/PathConsumer2D.java | 10 +++---- .../awt/im/ExecutableInputMethodManager.java | 2 +- .../sun/awt/image/ByteBandedRaster.java | 24 ++++++++-------- .../sun/awt/image/ByteComponentRaster.java | 20 ++++++------- .../sun/awt/image/ByteInterleavedRaster.java | 20 ++++++------- .../sun/awt/image/BytePackedRaster.java | 20 ++++++------- .../classes/sun/awt/image/ImageFetchable.java | 4 +-- .../sun/awt/image/IntegerComponentRaster.java | 12 ++++---- .../awt/image/IntegerInterleavedRaster.java | 12 ++++---- .../sun/awt/image/ShortBandedRaster.java | 22 +++++++-------- .../sun/awt/image/ShortComponentRaster.java | 20 ++++++------- .../sun/awt/image/ShortInterleavedRaster.java | 20 ++++++------- .../sun/awt/shell/ShellFolderColumnInfo.java | 2 +- .../sun/awt/util/IdentityArrayList.java | 2 +- .../sun/awt/util/IdentityLinkedList.java | 6 ++-- .../share/classes/sun/font/ScriptRun.java | 4 +-- .../classes/sun/font/TextLabelFactory.java | 4 +-- .../classes/sun/java2d/NullSurfaceData.java | 4 +-- .../sun/java2d/SunCompositeContext.java | 20 ++++++------- .../classes/sun/java2d/SunGraphics2D.java | 23 ++++++++------- .../share/classes/sun/java2d/SurfaceData.java | 4 +-- .../pipe/PixelToParallelogramConverter.java | 2 +- .../sun/java2d/pipe/RenderingEngine.java | 10 +++---- .../pipe/hw/AccelDeviceEventNotifier.java | 2 +- .../java2d/pipe/hw/AccelGraphicsConfig.java | 2 +- .../java2d/pipe/hw/ContextCapabilities.java | 2 +- .../sun/java2d/pisces/PiscesCache.java | 2 -- .../java2d/pisces/PiscesRenderingEngine.java | 8 +++--- .../share/classes/sun/print/DialogOwner.java | 5 ++-- .../share/classes/sun/print/OpenBook.java | 8 +++--- .../classes/sun/print/PSPathGraphics.java | 4 +-- .../share/classes/sun/print/PeekGraphics.java | 26 ++++++++--------- .../share/classes/sun/print/PrintJob2D.java | 6 ++-- .../classes/sun/print/ProxyGraphics2D.java | 28 +++++++++---------- .../classes/sun/print/ProxyPrintGraphics.java | 2 +- .../classes/sun/print/RasterPrinterJob.java | 12 ++++---- .../classes/sun/swing/CachedPainter.java | 2 +- .../share/classes/sun/swing/UIAction.java | 1 - .../swing/plaf/synth/DefaultSynthStyle.java | 8 ++---- .../sun/swing/plaf/synth/Paint9Painter.java | 2 +- .../swing/text/TextComponentPrintable.java | 2 +- .../unix/classes/sun/awt/UNIXToolkit.java | 2 +- .../unix/classes/sun/awt/X11/XAtom.java | 1 - .../classes/sun/awt/X11/XComponentPeer.java | 1 - .../unix/classes/sun/awt/X11/XListPeer.java | 2 -- .../classes/sun/awt/X11/XMenuBarPeer.java | 8 +++--- .../classes/sun/awt/X11/XMenuItemPeer.java | 2 +- .../unix/classes/sun/awt/X11/XMenuWindow.java | 6 ++-- .../unix/classes/sun/awt/X11/XScrollbar.java | 15 ++++------ .../classes/sun/awt/X11GraphicsConfig.java | 2 +- .../sun/awt/X11GraphicsEnvironment.java | 2 +- .../unix/classes/sun/awt/X11InputMethod.java | 2 +- .../classes/sun/font/FontConfigManager.java | 6 ---- .../sun/awt/windows/WComponentPeer.java | 2 +- .../sun/awt/windows/WPathGraphics.java | 4 +-- .../classes/sun/awt/windows/WPrinterJob.java | 2 +- .../java2d/d3d/D3DScreenUpdateManager.java | 4 +-- .../sun/java2d/d3d/D3DSurfaceData.java | 2 +- .../sun/java2d/opengl/WGLSurfaceData.java | 2 +- 65 files changed, 228 insertions(+), 258 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java index 13b000d5582..721c2a07473 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java @@ -802,7 +802,7 @@ public void grab() { /** * Determine if applet is targeted for JDK 1.1. * - * @param applet Applet class. + * @param clazz Applet class. * @return TRUE if applet is targeted for JDK 1.1; * FALSE if applet is not; * null if applet is unknown. @@ -815,7 +815,7 @@ public void grab() { /** * Determine if applet is targeted for JDK 1.2. * - * @param applet Applet class. + * @param clazz Applet class. * @return TRUE if applet is targeted for JDK 1.2; * FALSE if applet is not; * null if applet is unknown. diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java index e2287986da8..0eba476fe82 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java @@ -270,10 +270,10 @@ class AppletSecurity extends AWTSecurityManager { * The checkPackageAccess method for class * SecurityManager calls * checkPermission with the - * RuntimePermission("accessClassInPackage."+pkg) + * RuntimePermission("accessClassInPackage."+ pkgname) * permission. * - * @param pkg the package name. + * @param pkgname the package name. * @exception SecurityException if the caller does not have * permission to access the specified package. * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java index 44edefc31df..2125618d466 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -190,7 +190,7 @@ public final class AppContext { * * @see #addPropertyChangeListener * @see #removePropertyChangeListener - * @see #firePropertyChange + * @see PropertyChangeSupport#firePropertyChange */ private PropertyChangeSupport changeSupport = null; @@ -809,7 +809,7 @@ public final class AppContext { * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) - * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) + * @see PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) */ public synchronized void removePropertyChangeListener( String propertyName, diff --git a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java index 8863845566a..d90132e35e9 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java @@ -552,16 +552,10 @@ public abstract class EmbeddedFrame extends Frame } public void setModalBlocked(Dialog blocker, boolean blocked) {} - /** - * @see java.awt.peer.ContainerPeer#restack - */ public void restack() { throw new UnsupportedOperationException(); } - /** - * @see java.awt.peer.ContainerPeer#isRestackSupported - */ public boolean isRestackSupported() { return false; } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java index 91b555a2fce..80b58f37e1c 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -366,8 +366,8 @@ public abstract class SunToolkit extends Toolkit * status to synchronous for any of its windows, then further focus * behaviour is unspecified. *

    - * @param w window for which the lightweight focus request status - * should be set + * @param changed the window for which the lightweight focus request + * status should be set * @param status the value of lightweight focus request status */ @@ -1459,9 +1459,9 @@ public abstract class SunToolkit extends Toolkit *

    Notice that realSync isn't guaranteed to work if recurring * actions occur, such as if during processing of some event * another request which may generate some events occurs. By - * default, sync tries to perform as much as {@value MAX_ITERS} + * default, sync tries to perform as much as {@value #MAX_ITERS} * cycles of event processing, allowing for roughly {@value - * MAX_ITERS} additional requests. + * #MAX_ITERS} additional requests. * *

    For example, requestFocus() generates native request, which * generates one or two Java focus events, which then generate a diff --git a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java index 6178f779be0..3b743cbbaab 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java @@ -151,7 +151,7 @@ public abstract class SunClipboard extends Clipboard /** - * @see java.awt.Clipboard#getAvailableDataFlavors + * @see java.awt.datatransfer.Clipboard#getAvailableDataFlavors * @since 1.5 */ public DataFlavor[] getAvailableDataFlavors() { @@ -167,7 +167,7 @@ public abstract class SunClipboard extends Clipboard } /** - * @see java.awt.Clipboard#isDataFlavorAvailable + * @see java.awt.datatransfer.Clipboard#isDataFlavorAvailable * @since 1.5 */ public boolean isDataFlavorAvailable(DataFlavor flavor) { @@ -186,7 +186,7 @@ public abstract class SunClipboard extends Clipboard } /** - * @see java.awt.Clipboard#getData + * @see java.awt.datatransfer.Clipboard#getData * @since 1.5 */ public Object getData(DataFlavor flavor) diff --git a/jdk/src/java.desktop/share/classes/sun/awt/geom/PathConsumer2D.java b/jdk/src/java.desktop/share/classes/sun/awt/geom/PathConsumer2D.java index 7adcc323979..eac6bd88c9e 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/geom/PathConsumer2D.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/geom/PathConsumer2D.java @@ -27,30 +27,30 @@ package sun.awt.geom; public interface PathConsumer2D { /** - * @see java.awt.geom.Path2D.Float.moveTo + * @see java.awt.geom.Path2D.Float#moveTo */ public void moveTo(float x, float y); /** - * @see java.awt.geom.Path2D.Float.lineTo + * @see java.awt.geom.Path2D.Float#lineTo */ public void lineTo(float x, float y); /** - * @see java.awt.geom.Path2D.Float.quadTo + * @see java.awt.geom.Path2D.Float#quadTo */ public void quadTo(float x1, float y1, float x2, float y2); /** - * @see java.awt.geom.Path2D.Float.curveTo + * @see java.awt.geom.Path2D.Float#curveTo */ public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3); /** - * @see java.awt.geom.Path2D.Float.closePath + * @see java.awt.geom.Path2D.Float#closePath */ public void closePath(); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java b/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java index 11619ba453d..88ee71163b1 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java @@ -519,7 +519,7 @@ class ExecutableInputMethodManager extends InputMethodManager * Writes the preferred input method descriptor class name into * the user's Preferences tree in accordance with the given locale. * - * @param inputMethodLocator input method locator to remember. + * @param locator input method locator to remember. */ private synchronized void putPreferredInputMethod(InputMethodLocator locator) { InputMethodDescriptor descriptor = locator.getDescriptor(); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java index a0431baf4ac..699c1ea2f43 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java @@ -176,7 +176,7 @@ public class ByteBandedRaster extends SunWritableRaster { * Returns data offset for the specified band. The data offset * is the index into the band's data array * in which the first sample of the first scanline is stored. - * @param The band whose offset is returned. + * @param band The band whose offset is returned. */ public int getDataOffset(int band) { return dataOffsets[band]; @@ -222,11 +222,11 @@ public class ByteBandedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. - * @return An object reference to an array of type defined by + * @return An object reference to an array of type defined by * getTransferType() with the request pixel data. */ public Object getDataElements(int x, int y, Object obj) { @@ -267,9 +267,9 @@ public class ByteBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -320,8 +320,8 @@ public class ByteBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -368,8 +368,8 @@ public class ByteBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -412,7 +412,7 @@ public class ByteBandedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -505,7 +505,7 @@ public class ByteBandedRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java index b5f4f7095aa..2ac4d180152 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java @@ -253,7 +253,7 @@ public class ByteComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -299,9 +299,9 @@ public class ByteComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -352,8 +352,8 @@ public class ByteComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -415,8 +415,8 @@ public class ByteComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -458,7 +458,7 @@ public class ByteComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -577,7 +577,7 @@ public class ByteComponentRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java index ec0fef12623..52f01b30b63 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -305,7 +305,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -351,9 +351,9 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -376,8 +376,8 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -437,8 +437,8 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -536,7 +536,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -666,7 +666,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java index 3e60f193ac2..ef78c83d2ce 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java @@ -234,7 +234,7 @@ public class BytePackedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -306,9 +306,9 @@ public class BytePackedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -358,8 +358,8 @@ public class BytePackedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param band The band to return, is ignored. * @param outData If non-null, data elements * at the specified locations are returned in this array. @@ -383,8 +383,8 @@ public class BytePackedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements * at the specified locations are returned in this array. * @return Byte array with data elements. @@ -499,7 +499,7 @@ public class BytePackedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -857,7 +857,7 @@ public class BytePackedRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetchable.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetchable.java index 39b51d0d051..489248efbf6 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetchable.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetchable.java @@ -33,7 +33,7 @@ package sun.awt.image; * threads which manage the applications User Interface. * * @see ImageFetcher - * @see ImageProducer + * @see java.awt.image.ImageProducer * * @author Jim Graham */ @@ -42,7 +42,7 @@ public interface ImageFetchable { * This method is called by one of the ImageFetcher threads to start * the flow of information from the ImageProducer to the ImageConsumer. * @see ImageFetcher - * @see ImageProducer + * @see java.awt.image.ImageProducer */ public void doFetch(); } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java index f7e8bf37100..a420f95f003 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java @@ -263,7 +263,7 @@ public class IntegerComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -309,9 +309,9 @@ public class IntegerComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -358,7 +358,7 @@ public class IntegerComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -489,7 +489,7 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java index b226f07efcb..a852080a701 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java @@ -206,7 +206,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -249,9 +249,9 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -291,7 +291,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -410,7 +410,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java index ccf7740ad53..fd5c610504d 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java @@ -172,7 +172,7 @@ public class ShortBandedRaster extends SunWritableRaster { * Returns the data offset for the specified band. The data offset * is the index into the band's data array * in which the first sample of the first scanline is stored. - * @param The band whose offset is returned. + * @param band The band whose offset is returned. */ public int getDataOffset(int band) { return dataOffsets[band]; @@ -218,7 +218,7 @@ public class ShortBandedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -262,9 +262,9 @@ public class ShortBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -315,8 +315,8 @@ public class ShortBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -363,8 +363,8 @@ public class ShortBandedRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -407,7 +407,7 @@ public class ShortBandedRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -503,7 +503,7 @@ public class ShortBandedRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java index 14ffe5539cf..aa1c56a064d 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java @@ -252,7 +252,7 @@ public class ShortComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -298,9 +298,9 @@ public class ShortComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -351,8 +351,8 @@ public class ShortComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the sample rectangle. - * @param height Height of the sample rectangle. + * @param w Width of the sample rectangle. + * @param h Height of the sample rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -414,8 +414,8 @@ public class ShortComponentRaster extends SunWritableRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -456,7 +456,7 @@ public class ShortComponentRaster extends SunWritableRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -553,7 +553,7 @@ public class ShortComponentRaster extends SunWritableRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java index 4602c19aab0..05310891fe5 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -225,7 +225,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param outData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -271,9 +271,9 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. - * @param outData An object reference to an array of type defined by + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). * If null an array of appropriate type and size will be * allocated. @@ -324,8 +324,8 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the sample rectangle. - * @param height Height of the sample rectangle. + * @param w Width of the sample rectangle. + * @param h Height of the sample rectangle. * @param band The band to return. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. @@ -387,8 +387,8 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * * @param x The X coordinate of the upper left pixel location. * @param y The Y coordinate of the upper left pixel location. - * @param width Width of the pixel rectangle. - * @param height Height of the pixel rectangle. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. * @param outData If non-null, data elements for all bands * at the specified location are returned in this array. * @return Data array with data elements for all bands. @@ -429,7 +429,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * and references anything other than an array of transferType. * @param x The X coordinate of the pixel location. * @param y The Y coordinate of the pixel location. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length getNumDataElements() * containing the pixel data to place at x,y. */ @@ -525,7 +525,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param y The Y coordinate of the upper left pixel location. * @param w Width of the pixel rectangle. * @param h Height of the pixel rectangle. - * @param inData An object reference to an array of type defined by + * @param obj An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and * x+h, y+h. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java index 88dffacec2b..3926b558ba3 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java @@ -40,7 +40,7 @@ public class ShellFolderColumnInfo { private SortOrder sortOrder; private Comparator comparator; /** - * false (default) if the {@link comparator} expects folders as arguments, + * false (default) if the {@link #comparator} expects folders as arguments, * and true if folder's column values. The first option is used default for comparison * on Windows and also for separating files from directories when sorting using * ShellFolderManager's inner comparator. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java index c88452289cb..b6d107b62f6 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java @@ -68,7 +68,7 @@ import java.util.RandomAccess; * synchronizing on some object that naturally encapsulates the list. * * If no such object exists, the list should be "wrapped" using the - * {@link Collections#synchronizedList Collections.synchronizedList} + * {@link java.util.Collections#synchronizedList Collections.synchronizedList} * method. This is best done at creation time, to prevent accidental * unsynchronized access to the list:

      *   List list = Collections.synchronizedList(new IdentityArrayList(...));
    diff --git a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java index 690264ab4d9..f92509fefb4 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java @@ -41,7 +41,7 @@ import java.util.NoSuchElementException; * the IdentityLinkedList class provides uniformly named methods to * get, remove and insert an element at the * beginning and end of the list. These operations allow linked lists to be - * used as a stack, {@linkplain Queue queue}, or {@linkplain Deque + * used as a stack, {@linkplain java.util.Queue queue}, or {@linkplain Deque * double-ended queue}.

    * * The class implements the Deque interface, providing @@ -62,7 +62,7 @@ import java.util.NoSuchElementException; * encapsulates the list. * * If no such object exists, the list should be "wrapped" using the - * {@link Collections#synchronizedList Collections.synchronizedList} + * {@link java.util.Collections#synchronizedList Collections.synchronizedList} * method. This is best done at creation time, to prevent accidental * unsynchronized access to the list:

      *   List list = Collections.synchronizedList(new IdentityLinkedList(...));
    @@ -478,7 +478,7 @@ public class IdentityLinkedList * Adds the specified element as the tail (last element) of this list. * * @param e the element to add - * @return true (as specified by {@link Queue#offer}) + * @return true (as specified by {@link java.util.Queue#offer}) * @since 1.5 */ public boolean offer(E e) { diff --git a/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java b/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java index d023a51c69b..485002ded79 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java +++ b/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java @@ -138,7 +138,7 @@ public final class ScriptRun * Get the script code for the script of the current script run. * * @return the script code for the script of the current script run. - * @see #Script + * @see Script */ public int getScriptCode() { return scriptCode; @@ -274,7 +274,7 @@ public final class ScriptRun * @param scriptOne one of the script codes. * @param scriptTwo the other script code. * @return true if the two scripts are the same. - * @see com.ibm.icu.lang.Script + * @see Script */ private static boolean sameScript(int scriptOne, int scriptTwo) { return scriptOne == scriptTwo || scriptOne <= Script.INHERITED || scriptTwo <= Script.INHERITED; diff --git a/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java b/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java index 1f9ba94159c..d245f33b8af 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java +++ b/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java @@ -41,11 +41,11 @@ import java.text.Bidi; * * @see Font * @see FontRenderContext - * @see GlyphVector + * @see java.awt.font.GlyphVector * @see TextLabel * @see ExtendedTextLabel * @see Bidi - * @see TextLayout + * @see java.awt.font.TextLayout */ public final class TextLabelFactory { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/NullSurfaceData.java b/jdk/src/java.desktop/share/classes/sun/java2d/NullSurfaceData.java index a83e7566be3..c085da0d537 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/NullSurfaceData.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/NullSurfaceData.java @@ -86,7 +86,7 @@ public class NullSurfaceData extends SurfaceData { * In most cases, the returned Raster might contain more pixels * than requested. * - * @see useTightBBoxes + * @see #useTightBBoxes */ public Raster getRaster(int x, int y, int w, int h) { throw new InvalidPipeException("should be NOP"); @@ -101,7 +101,7 @@ public class NullSurfaceData extends SurfaceData { * the pixels has to be made when doing a getRaster. The * fewer pixels copied, the faster the operation will go. * - * @see getRaster + * @see #getRaster */ public boolean useTightBBoxes() { return false; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SunCompositeContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/SunCompositeContext.java index 012e8438063..3fb910e7c52 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SunCompositeContext.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunCompositeContext.java @@ -88,13 +88,13 @@ public class SunCompositeContext implements CompositeContext { * @param src2 The second source tile for the compositing operation. * @param dst The tile where the result of the operation is stored. */ - public void compose(Raster srcArg, Raster dstIn, WritableRaster dstOut) { + public void compose(Raster src1, Raster src2, WritableRaster dst) { WritableRaster src; int w; int h; - if (dstIn != dstOut) { - dstOut.setDataElements(0, 0, dstIn); + if (src2 != dst) { + dst.setDataElements(0, 0, src2); } // REMIND: We should be able to create a SurfaceData from just @@ -102,20 +102,20 @@ public class SunCompositeContext implements CompositeContext { // create a SurfaceData from a BufferedImage then we need to // make a WritableRaster since it is needed to construct a // BufferedImage. - if (srcArg instanceof WritableRaster) { - src = (WritableRaster) srcArg; + if (src1 instanceof WritableRaster) { + src = (WritableRaster) src1; } else { - src = srcArg.createCompatibleWritableRaster(); - src.setDataElements(0, 0, srcArg); + src = src1.createCompatibleWritableRaster(); + src.setDataElements(0, 0, src1); } - w = Math.min(src.getWidth(), dstIn.getWidth()); - h = Math.min(src.getHeight(), dstIn.getHeight()); + w = Math.min(src.getWidth(), src2.getWidth()); + h = Math.min(src.getHeight(), src2.getHeight()); BufferedImage srcImg = new BufferedImage(srcCM, src, srcCM.isAlphaPremultiplied(), null); - BufferedImage dstImg = new BufferedImage(dstCM, dstOut, + BufferedImage dstImg = new BufferedImage(dstCM, dst, dstCM.isAlphaPremultiplied(), null); diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 864b5fb8da2..f3c08ac332c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -874,13 +874,13 @@ public final class SunGraphics2D * space. The rendering attributes taken into account include the * clip, transform, and stroke attributes. * @param rect The area in device space to check for a hit. - * @param p The path to check for a hit. + * @param s The path to check for a hit. * @param onStroke Flag to choose between testing the stroked or * the filled path. * @return True if there is a hit, false otherwise. * @see #setStroke - * @see #fillPath - * @see #drawPath + * @see #fill(Shape) + * @see #draw(Shape) * @see #transform * @see #setTransform * @see #clip @@ -1295,7 +1295,7 @@ public final class SunGraphics2D /** * Returns the preferences for the rendering algorithms. - * @param hintCategory The category of hint to be set. The strings + * @param hintKey The category of hint to be set. The strings * are defined in the RenderingHints class. * @return The preferences for rendering algorithms. The strings * are defined in the RenderingHints class. @@ -1577,7 +1577,7 @@ public final class SunGraphics2D * Cx'(p) = Cx(Tx(p)). * A copy of the Tx is made, if necessary, so further * modifications to Tx do not affect rendering. - * @param Tx The Transform object to be composed with the current + * @param xform The Transform object to be composed with the current * transform. * @see #setTransform * @see AffineTransform @@ -1606,7 +1606,6 @@ public final class SunGraphics2D * Sets the Transform in the current graphics state. * @param Tx The Transform object to be used in the rendering process. * @see #transform - * @see TransformChain * @see AffineTransform */ @Override @@ -1789,8 +1788,8 @@ public final class SunGraphics2D * of the component, use appropriate methods of the component. * @param color The background color that should be used in * subsequent calls to clearRect(). - * @see getBackground - * @see Graphics.clearRect() + * @see #getBackground + * @see Graphics#clearRect */ public void setBackground(Color color) { backgroundColor = color; @@ -1798,7 +1797,7 @@ public final class SunGraphics2D /** * Returns the background color used for clearing a region. - * @see setBackground + * @see #setBackground */ public Color getBackground() { return backgroundColor; @@ -1806,7 +1805,7 @@ public final class SunGraphics2D /** * Returns the current Stroke in the Graphics2D state. - * @see setStroke + * @see #setStroke */ public Stroke getStroke() { return stroke; @@ -2056,7 +2055,7 @@ public final class SunGraphics2D * with the current transform in the Graphics2D state before being * intersected with the current clip. This method is used to make the * current clip smaller. To make the clip larger, use any setClip method. - * @param p The Path to be intersected with the current clip. + * @param s The Path to be intersected with the current clip. */ public void clip(Shape s) { s = transformShape(s); @@ -2483,7 +2482,7 @@ public final class SunGraphics2D * Strokes the outline of a Path using the settings of the current * graphics state. The rendering attributes applied include the * clip, transform, paint or color, composite and stroke attributes. - * @param p The path to be drawn. + * @param s The path to be drawn. * @see #setStroke * @see #setPaint * @see java.awt.Graphics#setColor diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java b/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java index c1b8bf79b70..81794b5d490 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java @@ -939,7 +939,7 @@ public abstract class SurfaceData * In most cases, the returned Raster might contain more pixels * than requested. * - * @see useTightBBoxes + * @see #useTightBBoxes */ public abstract Raster getRaster(int x, int y, int w, int h); @@ -952,7 +952,7 @@ public abstract class SurfaceData * the pixels has to be made when doing a getRaster. The * fewer pixels copied, the faster the operation will go. * - * @see getRaster + * @see #getRaster */ public boolean useTightBBoxes() { // Note: The native equivalent would trigger on VISIBLE_TO_NATIVE diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java index 79fc8eb6780..eecefd97276 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java @@ -56,7 +56,7 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter * @param minPenSize minimum pen size for dropout control * @param normPosition sub-pixel location to normalize endpoints * for STROKE_NORMALIZE cases - * @param adjustFill boolean to control whethere normalization + * @param adjustfill boolean to control whethere normalization * constants are also applied to fill operations * (normally true for non-AA, false for AA) */ diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java index 034a6e8b218..d5fd254fe6c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderingEngine.java @@ -66,7 +66,7 @@ import sun.awt.geom.PathConsumer2D; * line width can get before dropouts occur. Rendering with a BasicStroke * is defined to never allow the line to have breaks, gaps, or dropouts * even if the width is set to 0.0f, so this information allows the - * {@link SunGraphics2D} class to detect the "thin line" case and set + * {@link sun.java2d.SunGraphics2D} class to detect the "thin line" case and set * the rendering attributes accordingly. * * At startup the runtime will load a single instance of this class. @@ -177,11 +177,11 @@ public abstract class RenderingEngine { * The specified {@code src} {@link Shape} is widened according * to the parameters specified by the {@link BasicStroke} object. * Adjustments are made to the path as appropriate for the - * {@link VALUE_STROKE_NORMALIZE} hint if the {@code normalize} - * boolean parameter is true. + * {@link java.awt.RenderingHints#VALUE_STROKE_NORMALIZE} hint if the + * {@code normalize} boolean parameter is true. * Adjustments are made to the path as appropriate for the - * {@link VALUE_ANTIALIAS_ON} hint if the {@code antialias} - * boolean parameter is true. + * {@link java.awt.RenderingHints#VALUE_ANTIALIAS_ON} hint if the + * {@code antialias} boolean parameter is true. *

    * The geometry of the widened path is forwarded to the indicated * {@link PathConsumer2D} object as it is calculated. diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java index 69264c51c4a..9cca142c48f 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java @@ -137,7 +137,7 @@ public class AccelDeviceEventNotifier { * * @param screen a screen number with which the device which is a source of * the event is associated with - * @param eventType a type of the event + * @param deviceEventType a type of the event * @see #DEVICE_DISPOSED * @see #DEVICE_RESET */ diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java index c503500a213..50712319180 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/AccelGraphicsConfig.java @@ -77,7 +77,7 @@ public interface AccelGraphicsConfig extends BufferedContextProvider { * events. * * Note: a hard link to the listener may be kept so it must be explicitly - * removed via {@link #removeDeviceEventListener()}. + * removed via {@link #removeDeviceEventListener}. * * @param l the listener * @see AccelDeviceEventListener diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java index 12aad7b2f11..833273ca70c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/hw/ContextCapabilities.java @@ -65,7 +65,7 @@ public class ContextCapabilities { /** * Constructs a {@code ContextCapabilities} object. * @param caps an {@code int} representing the capabilities - * @param a {@code String} representing the name of the adapter, or null, + * @param adapterId {@code String} representing the name of the adapter, or null, * in which case the adapterId will be set to "unknown adapter". */ protected ContextCapabilities(int caps, String adapterId) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java index a26e7aa05f3..7e23ed4c5f1 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java @@ -29,8 +29,6 @@ import java.util.Arrays; /** * An object used to cache pre-rendered complex paths. - * - * @see PiscesRenderer#render */ final class PiscesCache { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java index f6057fe2b73..af2d25506cf 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java @@ -108,11 +108,11 @@ public class PiscesRenderingEngine extends RenderingEngine { * The specified {@code src} {@link Shape} is widened according * to the parameters specified by the {@link BasicStroke} object. * Adjustments are made to the path as appropriate for the - * {@link VALUE_STROKE_NORMALIZE} hint if the {@code normalize} - * boolean parameter is true. + * {@link java.awt.RenderingHints#VALUE_STROKE_NORMALIZE} hint if the + * {@code normalize} boolean parameter is true. * Adjustments are made to the path as appropriate for the - * {@link VALUE_ANTIALIAS_ON} hint if the {@code antialias} - * boolean parameter is true. + * {@link java.awt.RenderingHints#VALUE_ANTIALIAS_ON} hint if the + * {@code antialias} boolean parameter is true. *

    * The geometry of the widened path is forwarded to the indicated * {@link PathConsumer2D} object as it is calculated. diff --git a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java index 96a67eb8106..a08c06bac58 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java +++ b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java @@ -45,10 +45,9 @@ public final class DialogOwner private Frame dlgOwner; /** - * Construct a new dialog type selection enumeration value with the - * given integer value. + * Construct a new dialog owner attribute with the given frame. * - * @param value Integer value. + * @param frame the frame that owns the print dialog */ public DialogOwner(Frame frame) { dlgOwner = frame; diff --git a/jdk/src/java.desktop/share/classes/sun/print/OpenBook.java b/jdk/src/java.desktop/share/classes/sun/print/OpenBook.java index c16c5170e3a..4ce61b45456 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/OpenBook.java +++ b/jdk/src/java.desktop/share/classes/sun/print/OpenBook.java @@ -74,8 +74,8 @@ class OpenBook implements Pageable { /** * Return the PageFormat of the page specified by 'pageIndex'. - * @param int The zero based index of the page whose - * PageFormat is being requested. + * @param pageIndex The zero based index of the page whose + * PageFormat is being requested. * @return The PageFormat describing the size and orientation */ public PageFormat getPageFormat(int pageIndex) { @@ -85,8 +85,8 @@ class OpenBook implements Pageable { /** * Return the Printable instance responsible for rendering * the page specified by 'pageIndex'. - * @param int The zero based index of the page whose - * Printable is being requested. + * @param pageIndex The zero based index of the page whose + * Printable is being requested. * @return The Printable that will draw the page. */ public Printable getPrintable(int pageIndex) diff --git a/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java index 73a77ff6020..1b00d4b7851 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java @@ -126,7 +126,7 @@ class PSPathGraphics extends PathGraphics { * such as Hebrew and Arabic, the glyphs can be rendered from right to * left, in which case the coordinate supplied is the location of the * leftmost character on the baseline. - * @param s the String to be rendered + * @param str the String to be rendered * @param x, y the coordinates where the String * should be rendered * @see #setPaint @@ -256,7 +256,7 @@ class PSPathGraphics extends PathGraphics { * is transformed by the supplied AffineTransform and * drawn using PS to the printer context. * - * @param img The image to be drawn. + * @param image The image to be drawn. * This method does nothing if img is null. * @param xform Used to transform the image before drawing. * This can be null. diff --git a/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java index dd6e0e7472c..ffa0aabe25d 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java @@ -361,9 +361,9 @@ public class PeekGraphics extends Graphics2D * use this font. * @param font the font. * @see java.awt.Graphics#getFont - * @see java.awt.Graphics#drawChars(java.lang.String, int, int) - * @see java.awt.Graphics#drawString(byte[], int, int, int, int) - * @see java.awt.Graphics#drawBytes(char[], int, int, int, int) + * @see java.awt.Graphics#drawChars(char[], int, int, int, int) + * @see java.awt.Graphics#drawString(String, int, int) + * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) * @since 1.0 */ public void setFont(Font font) { @@ -1446,7 +1446,7 @@ public class PeekGraphics extends Graphics2D * Draws a string of text. * The rendering attributes applied include the clip, transform, * paint or color, font and composite attributes. - * @param s The string to be drawn. + * @param str The string to be drawn. * @param x,y The coordinates where the string should be drawn. * @see #setPaint * @see java.awt.Graphics#setColor @@ -1548,7 +1548,7 @@ public class PeekGraphics extends Graphics2D * @param comp The Composite object to be used for drawing. * @see java.awt.Graphics#setXORMode * @see java.awt.Graphics#setPaintMode - * @see AlphaComposite + * @see java.awt.AlphaComposite */ public void setComposite(Composite comp) { mGraphics.setComposite(comp); @@ -1560,8 +1560,8 @@ public class PeekGraphics extends Graphics2D * @param paint The Paint object to be used to generate color in * the rendering process. * @see java.awt.Graphics#setColor - * @see GradientPaint - * @see TexturePaint + * @see java.awt.GradientPaint + * @see java.awt.TexturePaint */ public void setPaint(Paint paint) { mGraphics.setPaint(paint); @@ -1594,7 +1594,7 @@ public class PeekGraphics extends Graphics2D * Returns the preferences for the rendering algorithms. * @param hintCategory The category of hint to be set. * @return The preferences for rendering algorithms. - * @see RenderingHings + * @see RenderingHints */ public Object getRenderingHint(Key hintCategory) { return mGraphics.getRenderingHint(hintCategory); @@ -1647,7 +1647,6 @@ public class PeekGraphics extends Graphics2D * @param Tx The Transform object to be composed with the current * transform. * @see #setTransform - * @see TransformChain * @see AffineTransform */ public void transform(AffineTransform Tx) { @@ -1658,7 +1657,6 @@ public class PeekGraphics extends Graphics2D * Sets the Transform in the current graphics state. * @param Tx The Transform object to be used in the rendering process. * @see #transform - * @see TransformChain * @see AffineTransform */ public void setTransform(AffineTransform Tx) { @@ -1700,8 +1698,8 @@ public class PeekGraphics extends Graphics2D * of the component, use appropriate methods of the component. * @param color The background color that should be used in * subsequent calls to clearRect(). - * @see getBackground - * @see Graphics.clearRect() + * @see #getBackground + * @see Graphics#clearRect */ public void setBackground(Color color) { mGraphics.setBackground(color); @@ -1709,7 +1707,7 @@ public class PeekGraphics extends Graphics2D /** * Returns the background color used for clearing a region. - * @see setBackground + * @see #setBackground */ public Color getBackground() { return mGraphics.getBackground(); @@ -1717,7 +1715,7 @@ public class PeekGraphics extends Graphics2D /** * Returns the current Stroke in the Graphics2D state. - * @see setStroke + * @see #setStroke */ public Stroke getStroke() { return mGraphics.getStroke(); diff --git a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java index cab43fef354..0ae31dfb56e 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -79,7 +79,7 @@ import sun.print.SunMinMaxPage; * A class which initiates and executes a print job using * the underlying PrinterJob graphics conversions. * - * @see Toolkit#getPrintJob + * @see java.awt.Toolkit#getPrintJob * */ public class PrintJob2D extends PrintJob implements Printable, Runnable { @@ -750,7 +750,7 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { * The page is sent to the printer when the graphics * object is disposed. This graphics object will also implement * the PrintGraphics interface. - * @see PrintGraphics + * @see java.awt.PrintGraphics */ public Graphics getGraphics() { @@ -937,7 +937,7 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { * If the requested page does not exist then this method returns * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned. * The Graphics class or subclass implements the - * {@link PrinterGraphics} interface to provide additional + * {@link java.awt.PrintGraphics} interface to provide additional * information. If the Printable object * aborts the print job then it throws a {@link PrinterException}. * @param graphics the context into which the page is drawn diff --git a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java index 6187e639b69..57f8ec876b3 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java @@ -297,9 +297,9 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * use this font. * @param font the font. * @see java.awt.Graphics#getFont - * @see java.awt.Graphics#drawChars(java.lang.String, int, int) - * @see java.awt.Graphics#drawString(byte[], int, int, int, int) - * @see java.awt.Graphics#drawBytes(char[], int, int, int, int) + * @see java.awt.Graphics#drawChars(char[], int, int, int, int) + * @see java.awt.Graphics#drawString(String, int, int) + * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) * @since 1.0 */ public void setFont(Font font) { @@ -1345,7 +1345,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Draws a string of text. * The rendering attributes applied include the clip, transform, * paint or color, font and composite attributes. - * @param s The string to be drawn. + * @param str The string to be drawn. * @param x,y The coordinates where the string should be drawn. * @see #setPaint * @see java.awt.Graphics#setColor @@ -1432,7 +1432,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * @param comp The Composite object to be used for drawing. * @see java.awt.Graphics#setXORMode * @see java.awt.Graphics#setPaintMode - * @see AlphaComposite + * @see java.awt.AlphaComposite */ public void setComposite(Composite comp) { mGraphics.setComposite(comp); @@ -1444,8 +1444,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * @param paint The Paint object to be used to generate color in * the rendering process. * @see java.awt.Graphics#setColor - * @see GradientPaint - * @see TexturePaint + * @see java.awt.GradientPaint + * @see java.awt.TexturePaint */ public void setPaint(Paint paint) { mGraphics.setPaint(paint); @@ -1455,7 +1455,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Sets the Stroke in the current graphics state. * @param s The Stroke object to be used to stroke a Shape in * the rendering process. - * @see BasicStroke + * @see java.awt.BasicStroke */ public void setStroke(Stroke s) { mGraphics.setStroke(s); @@ -1478,7 +1478,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Returns the preferences for the rendering algorithms. * @param hintCategory The category of hint to be set. * @return The preferences for rendering algorithms. - * @see RenderingHings + * @see RenderingHints */ public Object getRenderingHint(Key hintCategory) { return mGraphics.getRenderingHint(hintCategory); @@ -1531,7 +1531,6 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * @param Tx The Transform object to be composed with the current * transform. * @see #setTransform - * @see TransformChain * @see AffineTransform */ public void transform(AffineTransform Tx) { @@ -1542,7 +1541,6 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Sets the Transform in the current graphics state. * @param Tx The Transform object to be used in the rendering process. * @see #transform - * @see TransformChain * @see AffineTransform */ public void setTransform(AffineTransform Tx) { @@ -1584,8 +1582,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * of the component, use appropriate methods of the component. * @param color The background color that should be used in * subsequent calls to clearRect(). - * @see getBackground - * @see Graphics.clearRect() + * @see #getBackground + * @see Graphics#clearRect */ public void setBackground(Color color) { mGraphics.setBackground(color); @@ -1593,7 +1591,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Returns the background color used for clearing a region. - * @see setBackground + * @see #setBackground */ public Color getBackground() { return mGraphics.getBackground(); @@ -1601,7 +1599,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Returns the current Stroke in the Graphics2D state. - * @see setStroke + * @see #setStroke */ public Stroke getStroke() { return mGraphics.getStroke(); diff --git a/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java index 7c5d17efd17..f46caed3ea3 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java @@ -69,7 +69,7 @@ public class ProxyPrintGraphics extends ProxyGraphics * Graphics object, but with a new translation and * clip area. * Refer to - * {@link sun.print.ProxyGraphics#createGraphics} + * {@link sun.print.ProxyGraphics#create(int, int, int, int)} * for a complete description of this method. *

    * @param x the x coordinate. diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 906058f8a81..a87c8123c7f 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -498,7 +498,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * Throws PrinterException if the specified service * cannot support the Pageable and * Printable interfaces necessary to support 2D printing. - * @param a print service which supports 2D printing. + * @param service print service which supports 2D printing. * * @throws PrinterException if the specified service does not support * 2D printing or no longer available. @@ -1024,7 +1024,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * The pages in the document to be printed by this PrinterJob * are drawn by the Printable object 'painter'. The PageFormat * for each page is the default page format. - * @param Printable Called to render each page of the document. + * @param painter Called to render each page of the document. */ public void setPrintable(Printable painter) { setPageable(new OpenBook(defaultPage(new PageFormat()), painter)); @@ -1034,9 +1034,9 @@ public abstract class RasterPrinterJob extends PrinterJob { * The pages in the document to be printed by this PrinterJob * are drawn by the Printable object 'painter'. The PageFormat * of each page is 'format'. - * @param Printable Called to render each page of the document. - * @param PageFormat The size and orientation of each page to - * be printed. + * @param painter Called to render each page of the document. + * @param format The size and orientation of each page to + * be printed. */ public void setPrintable(Printable painter, PageFormat format) { setPageable(new OpenBook(format, painter)); @@ -1048,7 +1048,7 @@ public abstract class RasterPrinterJob extends PrinterJob { * Pageable instance 'document'. 'document' will be queried * for the number of pages as well as the PageFormat and * Printable for each page. - * @param Pageable The document to be printed. It may not be null. + * @param document The document to be printed. It may not be null. * @exception NullPointerException the Pageable passed in was null. * @see PageFormat * @see Printable diff --git a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java index dedee99cc27..ef9a3c2baaf 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java @@ -89,7 +89,7 @@ public abstract class CachedPainter { * @param y Y-coordinate to render to * @param w Width to render in * @param h Height to render in - * @param arg Variable arguments that will be passed to paintToImage + * @param args Variable arguments that will be passed to paintToImage */ public void paint(Component c, Graphics g, int x, int y, int w, int h, Object... args) { diff --git a/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java b/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java index 097001e4045..98aa04c06c4 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java @@ -54,7 +54,6 @@ import javax.swing.Action; * isEnabled(Component), and be aware that the passed in * Component may be null. * - * @see com.sun.java.swing.ExtendedAction * @see javax.swing.Action * @author Scott Violet */ diff --git a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java index 8829f369460..8e4c2159679 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java @@ -289,7 +289,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { /** * Sets the insets. * - * @param Insets. + * @param insets the new insets. */ public void setInsets(Insets insets) { this.insets = insets; @@ -300,7 +300,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { * insets will be placed in it, otherwise a new Insets object will be * created and returned. * - * @param context SynthContext identifying requestor + * @param state SynthContext identifying requestor * @param to Where to place Insets * @return Insets. */ @@ -435,7 +435,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { * Returns the default value for a particular property. This is only * invoked if this style doesn't define a property for key. * - * @param state SynthContext identifying requestor + * @param context SynthContext identifying requestor * @param key Property being requested. * @return Value of the named property */ @@ -724,8 +724,6 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { * * @param state Component state(s) that this StateInfo should be used * for - * @param painter Painter responsible for rendering - * @param bgPainter Painter responsible for rendering the background * @param font Font for this state * @param colors Colors for this state */ diff --git a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/Paint9Painter.java b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/Paint9Painter.java index 2a7aa577e05..df9fed5c36b 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/Paint9Painter.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/Paint9Painter.java @@ -118,7 +118,7 @@ public class Paint9Painter extends CachedPainter { * @param dInsets Destination insets specifying the portion of the image * will be stretched or tiled, if null empty * Insets will be used. - * @param paintType Specifies what type of algorithm to use in painting + * @param type Specifies what type of algorithm to use in painting * @param mask Specifies portion of image to render, if * PAINT_ALL is specified, any other regions * specified will not be painted, for example diff --git a/jdk/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java b/jdk/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java index 63d3c5890dd..eace48bcc26 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/text/TextComponentPrintable.java @@ -212,7 +212,7 @@ public class TextComponentPrintable implements CountingPrintable { * level {@code JEditorPanes}. For instance if there is a frame * inside the frame it will return the top frame only. * - * @param c the container to find all frames under + * @param container the container to find all frames under * @param list {@code List} to append the results too */ private static void getFrames(final Container container, List list) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index d03644ffec6..42dd34e6943 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -189,7 +189,7 @@ public abstract class UNIXToolkit extends SunToolkit * @param stockId String which defines the stock id of the gtk item. * For a complete list reference the API at www.gtk.org for StockItems. * @param iconSize One of the GtkIconSize values defined in GTKConstants - * @param textDirection One of the TextDirection values defined in + * @param direction One of the TextDirection values defined in * GTKConstants * @param detail Render detail that is passed to the native engine (feel * free to pass null) diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java index 3e14dda589d..01d17fdad21 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java @@ -338,7 +338,6 @@ public final class XAtom { /** Gets the window property for the specified window * @param window window id to use - * @param str value to set to. * @return string with the property. * @since 1.5 */ diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java index b84054ea4ed..3c5d162bd18 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java @@ -680,7 +680,6 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget * obtained * @return the font metrics for font * @see #getFont - * @see #getPeer * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) * @see Toolkit#getFontMetrics(Font) * @since 1.0 diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XListPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XListPeer.java index 77545589889..b744d5e8cbd 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XListPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XListPeer.java @@ -1952,7 +1952,6 @@ class XListPeer extends XComponentPeer implements ListPeer, XScrollbarClient { * Paint the horizontal scrollbar to the screen * * @param g the graphics context to draw into - * @param colors the colors used to draw the scrollbar * @param paintAll paint the whole scrollbar if true, just the thumb if false */ void paintHorScrollbar(Graphics g, boolean paintAll) { @@ -1964,7 +1963,6 @@ class XListPeer extends XComponentPeer implements ListPeer, XScrollbarClient { * Paint the vertical scrollbar to the screen * * @param g the graphics context to draw into - * @param colors the colors used to draw the scrollbar * @param paintAll paint the whole scrollbar if true, just the thumb if false */ void paintVerScrollbar(Graphics g, boolean paintAll) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java index cf6ba6e1025..256767446e2 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java @@ -222,7 +222,7 @@ public class XMenuBarPeer extends XBaseMenuWindow implements MenuBarPeer { } /** - * @see XBaseMenuWindow.map + * @see XBaseMenuWindow#map */ protected MappingData map() { XMenuItemPeer[] itemVector = copyItems(); @@ -292,7 +292,7 @@ public class XMenuBarPeer extends XBaseMenuWindow implements MenuBarPeer { } /** - * @see XBaseMenuWindow.getSubmenuBounds + * @see XBaseMenuWindow#getSubmenuBounds */ protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) { Rectangle globalBounds = toGlobal(itemBounds); @@ -362,7 +362,7 @@ public class XMenuBarPeer extends XBaseMenuWindow implements MenuBarPeer { ************************************************/ /** - * @see XBaseMenuWindow.doDispose() + * @see XBaseMenuWindow#doDispose() */ protected void doDispose() { super.doDispose(); @@ -388,7 +388,7 @@ public class XMenuBarPeer extends XBaseMenuWindow implements MenuBarPeer { /** * Performs ungrabbing of input - * @see XBaseWindow.ungrabInputImpl() + * @see XBaseWindow#ungrabInputImpl() */ void ungrabInputImpl() { selectItem(null, false); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java index 7aa9c3c1b0d..dd576070ff2 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java @@ -437,7 +437,7 @@ public class XMenuItemPeer implements MenuItemPeer { * Sets mapping of item to window. * @param bounds bounds of item in container's coordinates * @param textOrigin point for drawString in container's coordinates - * @see XBaseMenuWindow.map() + * @see XBaseMenuWindow#map() */ void map(Rectangle bounds, Point textOrigin) { this.bounds = bounds; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java index b5fbfca919c..a79753facf0 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java @@ -192,14 +192,14 @@ public class XMenuWindow extends XBaseMenuWindow { ************************************************/ /** - * @see XBaseMenuWindow.getParentMenuWindow() + * @see XBaseMenuWindow#getParentMenuWindow() */ protected XBaseMenuWindow getParentMenuWindow() { return (menuPeer != null) ? menuPeer.getContainer() : null; } /** - * @see XBaseMenuWindow.map() + * @see XBaseMenuWindow#map() */ protected MappingData map() { //TODO:Implement popup-menu caption mapping and painting and tear-off @@ -274,7 +274,7 @@ public class XMenuWindow extends XBaseMenuWindow { } /** - * @see XBaseMenuWindow.getSubmenuBounds() + * @see XBaseMenuWindow#getSubmenuBounds */ protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) { Rectangle globalBounds = toGlobal(itemBounds); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XScrollbar.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XScrollbar.java index 49381c05716..71aa8fe0de4 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XScrollbar.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XScrollbar.java @@ -161,8 +161,6 @@ abstract class XScrollbar { * paint the scrollbar * @param g the graphics context to paint into * @param colors the colors to use when painting the scrollbar - * @param width the width of the scrollbar - * @param height the height of the scrollbar * @param paintAll paint the whole scrollbar if true, just the thumb is false */ void paint(Graphics g, Color colors[], boolean paintAll) { @@ -393,7 +391,7 @@ abstract class XScrollbar { /** * Scroll one unit. - * @see notifyValue + * @see #notifyValue */ void scroll() { switch (mode) { @@ -607,7 +605,6 @@ abstract class XScrollbar { * @param minimum is the minimum value of the scrollbar * @param maximum is the maximum value of the scrollbar * @param unitSize is the unit size for increment or decrement of the value - * @param page is the block size for increment or decrement of the value * @see #setValues */ synchronized void setValues(int value, int visible, int minimum, int maximum, @@ -631,7 +628,7 @@ abstract class XScrollbar { /** * Sets the value of this Scrollbar to the specified value. - * @param value the new value of the Scrollbar. If this value is + * @param newValue the new value of the Scrollbar. If this value is * below the current minimum or above the current maximum minus * the visible amount, it becomes the new one of those values, * respectively. @@ -655,7 +652,7 @@ abstract class XScrollbar { /** * Sets the minimum value for this Scrollbar. - * @param minimum the minimum value of the scrollbar + * @param newMinimum the minimum value of the scrollbar */ synchronized void setMinimum(int newMinimum) { /* Use setValues so that a consistent policy @@ -675,7 +672,7 @@ abstract class XScrollbar { /** * Sets the maximum value for this Scrollbar. - * @param maximum the maximum value of the scrollbar + * @param newMaximum the maximum value of the scrollbar */ synchronized void setMaximum(int newMaximum) { /* Use setValues so that a consistent policy @@ -694,7 +691,7 @@ abstract class XScrollbar { /** * Sets the visible amount of this Scrollbar, which is the range * of values represented by the width of the scroll bar's bubble. - * @param visible the amount visible per page + * @param newAmount the amount visible per page */ synchronized void setVisibleAmount(int newAmount) { setValues(val, newAmount, min, max); @@ -759,7 +756,7 @@ abstract class XScrollbar { /** * Returns the scale factor for the thumbArea ( thumbAreaH / (max - min)). - * @see #getArrowAreaSize + * @see #getArrowAreaWidth */ private double getScaleFactor(){ double f = (double)(barLength - 2*getArrowAreaWidth()) / Math.max(1,(max - min)); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java index 7432c8b7159..9ac71d82993 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java @@ -58,7 +58,7 @@ import sun.awt.image.SurfaceManager; * This is an implementation of a GraphicsConfiguration object for a * single X11 visual. * - * @see GraphicsEnvironment + * @see java.awt.GraphicsEnvironment * @see GraphicsDevice */ public class X11GraphicsConfig extends GraphicsConfiguration diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java index fec7daa620b..81e6ae8375f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java @@ -48,7 +48,7 @@ import sun.java2d.xr.XRSurfaceData; * for X11 environments. * * @see GraphicsDevice - * @see GraphicsConfiguration + * @see java.awt.GraphicsConfiguration */ public final class X11GraphicsEnvironment extends SunGraphicsEnvironment { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java index 5fc2825306e..54153af8011 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java @@ -548,7 +548,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { * method is invoked from the event handler in canvas.c in the * AWT Toolkit thread context and thus inside the AWT Lock. * @param str committed text - * @param long when + * @param when when */ // NOTE: This method may be called by privileged threads. // This functionality is implemented in a package-private method diff --git a/jdk/src/java.desktop/unix/classes/sun/font/FontConfigManager.java b/jdk/src/java.desktop/unix/classes/sun/font/FontConfigManager.java index 725ae4e060b..dcb99ba89ce 100644 --- a/jdk/src/java.desktop/unix/classes/sun/font/FontConfigManager.java +++ b/jdk/src/java.desktop/unix/classes/sun/font/FontConfigManager.java @@ -436,12 +436,6 @@ public class FontConfigManager { return (fcInfo.compFont = new CompositeFont(physFont, jdkFont)); } - /** - * - * @param locale - * @param fcFamily - * @return - */ public FcCompFont[] getFontConfigFonts() { return fontConfigFonts; } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java index 3aa2387495c..6c40c230120 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java @@ -663,7 +663,7 @@ public abstract class WComponentPeer extends WObjectPeer * This method is intentionally not synchronized as it is called while * holding other locks. * - * @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData) + * @see sun.java2d.d3d.D3DScreenUpdateManager#validate */ public Color getBackgroundNoSync() { return background; diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java index 3b90f2fa215..75e51636ec2 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java @@ -386,7 +386,7 @@ final class WPathGraphics extends PathGraphics { * such as Hebrew and Arabic, the glyphs can be rendered from right to * left, in which case the coordinate supplied is the location of the * leftmost character on the baseline. - * @param s the String to be rendered + * @param str the String to be rendered * @param x, y the coordinates where the String * should be rendered * @see #setPaint @@ -877,7 +877,7 @@ final class WPathGraphics extends PathGraphics { * is transformed by the supplied AffineTransform and * drawn using GDI to the printer context. * - * @param img The image to be drawn. + * @param image The image to be drawn. * @param xform Used to transform the image before drawing. * This can be null. * @param bgcolor This color is drawn where the image has transparent diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index 57e3e8bab0f..e365bd7cd96 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -591,7 +591,7 @@ public final class WPrinterJob extends RasterPrinterJob * Throws PrinterException if the specified service * cannot support the Pageable and * Printable interfaces necessary to support 2D printing. - * @param a print service which supports 2D printing. + * @param service print service which supports 2D printing. * * @throws PrinterException if the specified service does not support * 2D printing. diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index 54bf7dc2485..e4ebb4b9cd8 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -59,7 +59,7 @@ import sun.misc.InnocuousThread; * GDIWindowSurfaceData. A background thread handles the swap chain flips. * * There are some restrictions to which windows we would use this for. - * @see #createScreenSurface() + * @see #createScreenSurface */ public class D3DScreenUpdateManager extends ScreenUpdateManager implements Runnable @@ -290,7 +290,7 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager /** * Adds a surface to the list of tracked surfaces. * - * @param d3dw the surface to be added + * @param sd the surface to be added */ private void trackScreenSurface(SurfaceData sd) { if (!done && sd instanceof D3DWindowSurfaceData) { diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java index ffab9092a5a..4ff6f4c54c5 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java @@ -118,7 +118,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { /** * To be used with getNativeResource() only. - * @see #getNativeResource() + * @see #getNativeResource */ public static final int D3D_DEVICE_RESOURCE= 100; /* diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java b/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java index a96d58fa73c..75b691c54a5 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java @@ -244,7 +244,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { * Updates the layered window with the contents of the surface. * * @param psdops pointer to the native ogl sd structure - * @param pData pointer to the AwtWindow peer data + * @param peer pointer to the AwtWindow peer data * @param w width of the window * @param h height of the window * @see sun.awt.windows.TranslucentWindowPainter From 243208ab2e5296571c8494888443a22373d7de3a Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Mon, 25 May 2015 16:10:12 +0300 Subject: [PATCH 038/117] 8003399: JFileChooser gives wrong path to selected file when saving to Libraries folder on Windows 7 Reviewed-by: serb, ant --- .../sun/awt/shell/Win32ShellFolder2.java | 65 ++++- .../native/libawt/windows/ShellFolder2.cpp | 223 +++++++++++++++++- .../awt/FileDialog/8003399/bug8003399.java | 61 +++++ 3 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/awt/FileDialog/8003399/bug8003399.java diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 5fd7c34cad5..bb645e1a3a0 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -163,6 +163,27 @@ final class Win32ShellFolder2 extends ShellFolder { } } + // Known Folder data + static class KnownFolderDefinition { + String guid; + int category; + String name; + String description; + String parent; + String relativePath; + String parsingName; + String tooltip; + String localizedName; + String icon; + String security; + long attributes; + int defenitionFlags; + String ftidType; + String path; + String saveLocation; + static final List libraries = getLibraries(); + } + static class FolderDisposer implements sun.java2d.DisposerRecord { /* * This is cached as a concession to getFolderType(), which needs @@ -578,7 +599,22 @@ final class Win32ShellFolder2 extends ShellFolder { return s; } } - return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING); + String path = getDisplayNameOf(parentIShellFolder, relativePIDL, + SHGDN_FORPARSING); + // if this is a library its default save location is taken as a path + // this is a temp fix until java.io starts support Libraries + if( path != null && path.startsWith("::{") && + path.toLowerCase().endsWith(".library-ms")) { + for (KnownFolderDefinition kf : KnownFolderDefinition.libraries) { + if( path.toLowerCase().endsWith( + kf.relativePath.toLowerCase()) && + path.toUpperCase().startsWith( + kf.parsingName.substring(0, 40).toUpperCase()) ) { + return kf.saveLocation; + } + } + } + return path; } // Needs to be accessible to Win32ShellFolderManager2 @@ -848,6 +884,9 @@ final class Win32ShellFolder2 extends ShellFolder { long relativePIDL, int attrs); + // Returns data of all Known Folders registered in the system + private static native KnownFolderDefinition[] loadKnownFolders(); + /** * @return The name used to display this shell folder */ @@ -1178,4 +1217,26 @@ final class Win32ShellFolder2 extends ShellFolder { return result == null ? 0 : result; } } + + // Extracts libraries and their default save locations from Known Folders list + private static List getLibraries() { + return invoke(new Callable>() { + @Override + public List call() throws Exception { + KnownFolderDefinition[] all = loadKnownFolders(); + List folders = new ArrayList<>(); + if (all != null) { + for (KnownFolderDefinition kf : all) { + if (kf.relativePath == null || kf.parsingName == null || + kf.saveLocation == null) { + continue; + } + folders.add(kf); + } + } + return folders; + } + }); + } + } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp index cdc60d9ee9c..cd3918bd4eb 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -64,6 +64,16 @@ DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0); //#include +#define DEFINE_FIELD_ID(var, cls, field, type) \ + jfieldID var = env->GetFieldID(cls, field, type); \ + DASSERT(var != NULL); \ + CHECK_NULL_RETURN(var, NULL); + +#define EXCEPTION_CHECK \ + if(env->ExceptionCheck()) { \ + throw std::bad_alloc(); \ + } + // Shell Functions typedef BOOL (WINAPI *DestroyIconType)(HICON); typedef HINSTANCE (WINAPI *FindExecutableType)(LPCTSTR,LPCTSTR,LPTSTR); @@ -1263,5 +1273,216 @@ JNIEXPORT jint JNICALL return 0; } +/* + * Class: sun_awt_shell_Win32ShellFolder2 + * Method: loadKnownFolders + * Signature: (V)[BLsun/awt/shell/Win32ShellFolder2$KnownfolderDefenition; + */ +JNIEXPORT jobjectArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_loadKnownFolders + (JNIEnv* env, jclass cls ) +{ + CoInitialize(NULL); + IKnownFolderManager* pkfm = NULL; + HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm)); + if (!SUCCEEDED(hr)) return NULL; + + TRY; + + jclass cl = env->FindClass("sun/awt/shell/Win32ShellFolder2$KnownFolderDefinition"); + CHECK_NULL_RETURN(cl, NULL); + DEFINE_FIELD_ID(field_guid, cl, "guid", "Ljava/lang/String;") + DEFINE_FIELD_ID(field_name, cl, "name", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_description, cl, "description", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_parent, cl, "parent", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_relativePath, cl, "relativePath", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_parsingName, cl, "parsingName", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_tooltip, cl, "tooltip", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_localizedName, cl, "localizedName", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_icon, cl, "icon", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_security, cl, "security", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_path, cl, "path", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_saveLocation, cl, "saveLocation", "Ljava/lang/String;"); + DEFINE_FIELD_ID(field_category, cl, "category", "I"); + DEFINE_FIELD_ID(field_attributes, cl, "attributes", "J"); + DEFINE_FIELD_ID(field_defenitionFlags, cl, "defenitionFlags", "I"); + DEFINE_FIELD_ID(field_ftidType, cl, "ftidType", "Ljava/lang/String;"); + + jobjectArray result; + KNOWNFOLDERID* pFoldersIds = NULL; + UINT count = 0; + if (SUCCEEDED(pkfm->GetFolderIds(&pFoldersIds, &count))) { + jmethodID initMethod; + try { + result = env->NewObjectArray(count, cl, NULL); + initMethod = env->GetMethodID(cl, "", "()V"); + EXCEPTION_CHECK + } catch (std::bad_alloc&) { + CoTaskMemFree(pFoldersIds); + pkfm->Release(); + throw; + } + for(UINT i = 0; i < count; ++i) + { + jobject fld; + const KNOWNFOLDERID& folderId = pFoldersIds[i]; + LPOLESTR guid = NULL; + try { + fld = env->NewObject(cl, initMethod); + if (fld) { + env->SetObjectArrayElement(result, i, fld); + } + EXCEPTION_CHECK + + if (SUCCEEDED(StringFromCLSID(folderId, &guid))) { + jstring jstr = JNU_NewStringPlatform(env, guid); + if (jstr) { + env->SetObjectField(fld, field_guid, jstr); + } + CoTaskMemFree(guid); + EXCEPTION_CHECK + } + } catch (std::bad_alloc&) { + CoTaskMemFree(pFoldersIds); + pkfm->Release(); + throw; + } + + IKnownFolder* pFolder = NULL; + if (SUCCEEDED(pkfm->GetFolder(folderId, &pFolder))) { + KNOWNFOLDER_DEFINITION kfDef; + if (SUCCEEDED(pFolder->GetFolderDefinition(&kfDef))) + { + try { + jstring jstr = JNU_NewStringPlatform(env, kfDef.pszName); + if(jstr) { + env->SetObjectField(fld, field_name, jstr); + } + EXCEPTION_CHECK + if (kfDef.pszDescription) { + jstr = JNU_NewStringPlatform(env, kfDef.pszDescription); + if (jstr) { + env->SetObjectField(fld, field_description, jstr); + } + EXCEPTION_CHECK + } + EXCEPTION_CHECK + if (SUCCEEDED(StringFromCLSID(kfDef.fidParent, &guid))) { + jstr = JNU_NewStringPlatform(env, guid); + if (jstr) { + env->SetObjectField(fld, field_parent, jstr); + } + CoTaskMemFree(guid); + EXCEPTION_CHECK + } + if (kfDef.pszRelativePath) { + jstr = JNU_NewStringPlatform(env, kfDef.pszRelativePath); + if (jstr) { + env->SetObjectField(fld, field_relativePath, jstr); + } + EXCEPTION_CHECK + } + if (kfDef.pszParsingName) { + jstr = JNU_NewStringPlatform(env, kfDef.pszParsingName); + if (jstr) { + env->SetObjectField(fld, field_parsingName, jstr); + } + EXCEPTION_CHECK + } + if (kfDef.pszTooltip) { + jstr = JNU_NewStringPlatform(env, kfDef.pszTooltip); + if (jstr) { + env->SetObjectField(fld, field_tooltip, jstr); + } + EXCEPTION_CHECK + } + if (kfDef.pszLocalizedName) { + jstr = JNU_NewStringPlatform(env, kfDef.pszLocalizedName); + if (jstr) { + env->SetObjectField(fld, field_localizedName, jstr); + } + EXCEPTION_CHECK + } + if (kfDef.pszIcon) { + jstr = JNU_NewStringPlatform(env, kfDef.pszIcon); + if (jstr) { + env->SetObjectField(fld, field_icon, jstr); + } + EXCEPTION_CHECK + } + if (kfDef.pszSecurity) { + jstr = JNU_NewStringPlatform(env, kfDef.pszSecurity); + if (jstr) { + env->SetObjectField(fld, field_security, jstr); + } + EXCEPTION_CHECK + } + if (SUCCEEDED(StringFromCLSID(kfDef.ftidType, &guid))) { + jstr = JNU_NewStringPlatform(env, guid); + if (jstr) { + env->SetObjectField(fld, field_ftidType, jstr); + } + CoTaskMemFree(guid); + EXCEPTION_CHECK + } + env->SetIntField(fld, field_category, kfDef.category); + env->SetIntField(fld, field_defenitionFlags, kfDef.kfdFlags); + env->SetLongField(fld, field_attributes, kfDef.dwAttributes); + + LPWSTR folderPath = NULL; + if (SUCCEEDED(pFolder->GetPath(KF_FLAG_NO_ALIAS, &folderPath)) + && folderPath) { + jstr = JNU_NewStringPlatform(env, folderPath); + if (jstr) { + env->SetObjectField(fld, field_path, jstr); + } + CoTaskMemFree(folderPath); + EXCEPTION_CHECK + } + + IShellLibrary *plib = NULL; + hr = CoCreateInstance(CLSID_ShellLibrary, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&plib)); + if (SUCCEEDED(hr)) { + hr = plib->LoadLibraryFromKnownFolder(folderId, STGM_READWRITE); + if (SUCCEEDED(hr)) { + IShellItem *item = NULL; + hr = plib->GetDefaultSaveFolder(DSFT_DETECT, + IID_PPV_ARGS(&item)); + if (SUCCEEDED(hr) && item) { + LPWSTR loc = NULL; + hr = item->GetDisplayName(SIGDN_FILESYSPATH, &loc); + if (SUCCEEDED(hr) && loc) + { + jstr = JNU_NewStringPlatform(env, loc); + if (jstr) { + env->SetObjectField(fld, field_saveLocation, jstr); + } + CoTaskMemFree(loc); + } + item->Release(); + } + } + plib->Release(); + EXCEPTION_CHECK + } + FreeKnownFolderDefinitionFields(&kfDef); + } catch (std::bad_alloc&) { + FreeKnownFolderDefinitionFields(&kfDef); + pFolder->Release(); + CoTaskMemFree(pFoldersIds); + pkfm->Release(); + throw; + } + } + } + pFolder->Release(); + } + CoTaskMemFree(pFoldersIds); + } + pkfm->Release(); + return result; + CATCH_BAD_ALLOC_RET(NULL); +} } // extern "C" diff --git a/jdk/test/java/awt/FileDialog/8003399/bug8003399.java b/jdk/test/java/awt/FileDialog/8003399/bug8003399.java new file mode 100644 index 00000000000..1049fe573ff --- /dev/null +++ b/jdk/test/java/awt/FileDialog/8003399/bug8003399.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 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 8003399 + @summary JFileChooser gives wrong path to selected file when saving to Libraries folder on Windows 7 + @author Semyon Sadetsky + @library /lib/testlibrary + @build jdk.testlibrary.OSInfo + @run main bug8003399 + */ + +import jdk.testlibrary.OSInfo; + +import javax.swing.filechooser.FileSystemView; +import java.io.File; + +public class bug8003399 { + + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && + OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_VISTA) > 0 ) { + FileSystemView fsv = FileSystemView.getFileSystemView(); + for (File file : fsv.getFiles(fsv.getHomeDirectory(), false)) { + if(file.isDirectory()) { + for (File file1 : fsv.getFiles(file, false)) { + if(file1.isDirectory()) + { + String path = file1.getPath(); + if(path.startsWith("::{") && + path.toLowerCase().endsWith(".library-ms")) { + throw new RuntimeException("Unconverted library link found"); + } + } + } + } + } + } + System.out.println("ok"); + } +} From 3ef1c8d4c37ace132fbdff2afde4059a70cf573e Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 26 May 2015 08:33:32 +0300 Subject: [PATCH 039/117] 8079640: GroupLayout incorrect layout with large JTextArea Reviewed-by: serb, alexsch, azvegint --- .../classes/javax/swing/GroupLayout.java | 7 +- .../swing/GroupLayout/8079640/bug8079640.java | 99 +++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/swing/GroupLayout/8079640/bug8079640.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java b/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java index 9dc7a034e6d..b1012ce1a8c 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -218,6 +218,9 @@ public class GroupLayout implements LayoutManager2 { private static final int UNSET = Integer.MIN_VALUE; + // Maximum spring size constrain to avoid integer overflow + private static final int INFINITE = Integer.MAX_VALUE >> 1; + /** * Indicates the size from the component or gap should be used for a * particular range value. @@ -1389,7 +1392,7 @@ public class GroupLayout implements LayoutManager2 { } int constrain(int value) { - return Math.min(value, Short.MAX_VALUE); + return Math.min(value, INFINITE); } int getBaseline() { diff --git a/jdk/test/javax/swing/GroupLayout/8079640/bug8079640.java b/jdk/test/javax/swing/GroupLayout/8079640/bug8079640.java new file mode 100644 index 00000000000..c61949fdeef --- /dev/null +++ b/jdk/test/javax/swing/GroupLayout/8079640/bug8079640.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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 8079640 + @summary GroupLayout incorrect layout with large JTextArea + @author Semyon Sadetsky + */ + + +import javax.swing.*; +import java.awt.*; + +public class bug8079640 { + + private static JFrame frame; + private static JComponent comp2; + + public static void main(String[] args) throws Exception { + + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame("A Frame"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setUndecorated(true); + setup(frame); + frame.setVisible(true); + } + }); + + test(); + System.out.println("ok"); + + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if(comp2.getLocation().getY() > frame.getHeight()) + throw new RuntimeException("GroupLayout fails: comp2 is out of the window"); + } + }); + } + + + static void setup(JFrame frame) { + JPanel panel = new JPanel(); + JComponent comp1 = new JLabel("Test Label 1"); + comp1.setMinimumSize(new Dimension(1000, 40000)); + comp1.setPreferredSize(new Dimension(1000, 40000)); + JScrollPane scroll = new JScrollPane(comp1); + comp2 = new JLabel("Test Label 2"); + GroupLayout layout = new GroupLayout(panel); + layout.setHorizontalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(scroll) + .addComponent(comp2)); + layout.setVerticalGroup( + layout.createSequentialGroup() + .addComponent(scroll) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comp2)); + panel.setLayout(layout); + frame.getContentPane().add(panel, BorderLayout.CENTER); + frame.setSize(800, 600); + } + +} From 183dd96318e633e0c7d78a1451e5c33c2609c93d Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 26 May 2015 11:57:51 +0200 Subject: [PATCH 040/117] 8080663: Use sun.misc.SharedSecrets to allow access from java.management to @ConstructorProperties Reviewed-by: alanb, mchung, dfuchs --- ...pectorAccess.java => JavaBeansAccess.java} | 20 ++++- .../share/classes/sun/misc/SharedSecrets.java | 12 +-- .../classes/java/beans/Introspector.java | 29 +++++-- .../DefaultMXBeanMappingFactory.java | 52 +------------ .../com/sun/jmx/mbeanserver/Introspector.java | 34 +------- .../jmx/mbeanserver/JavaBeansAccessor.java | 78 +++++++++++++++++++ 6 files changed, 132 insertions(+), 93 deletions(-) rename jdk/src/java.base/share/classes/sun/misc/{JavaBeansIntrospectorAccess.java => JavaBeansAccess.java} (61%) create mode 100644 jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java diff --git a/jdk/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java b/jdk/src/java.base/share/classes/sun/misc/JavaBeansAccess.java similarity index 61% rename from jdk/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java rename to jdk/src/java.base/share/classes/sun/misc/JavaBeansAccess.java index c32f24c655f..ef1b696d717 100644 --- a/jdk/src/java.base/share/classes/sun/misc/JavaBeansIntrospectorAccess.java +++ b/jdk/src/java.base/share/classes/sun/misc/JavaBeansAccess.java @@ -25,8 +25,26 @@ package sun.misc; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; -public interface JavaBeansIntrospectorAccess { +public interface JavaBeansAccess { + /** + * Returns the getter method for a property of the given name + * @param clazz The JavaBeans class + * @param property The property name + * @return The resolved property getter method + * @throws Exception + */ Method getReadMethod(Class clazz, String property) throws Exception; + + /** + * Return the value attribute of the associated + * @ConstructorProperties annotation if that is present. + * @param ctr The constructor to extract the annotation value from + * @return The {@code value} attribute of the @ConstructorProperties + * annotation or {@code null} if the constructor is not annotated by + * this annotation or the annotation is not accessible. + */ + String[] getConstructorPropertiesValue(Constructor ctr); } diff --git a/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java index 49f06b5d39b..8164783952a 100644 --- a/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/sun/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -56,7 +56,7 @@ public class SharedSecrets { private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaAWTAccess javaAWTAccess; private static JavaAWTFontAccess javaAWTFontAccess; - private static JavaBeansIntrospectorAccess javaBeansIntrospectorAccess; + private static JavaBeansAccess javaBeansAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -194,11 +194,11 @@ public class SharedSecrets { return javaAWTFontAccess; } - public static JavaBeansIntrospectorAccess getJavaBeansIntrospectorAccess() { - return javaBeansIntrospectorAccess; + public static JavaBeansAccess getJavaBeansAccess() { + return javaBeansAccess; } - public static void setJavaBeansIntrospectorAccess(JavaBeansIntrospectorAccess access) { - javaBeansIntrospectorAccess = access; + public static void setJavaBeansAccess(JavaBeansAccess access) { + javaBeansAccess = access; } } diff --git a/jdk/src/java.desktop/share/classes/java/beans/Introspector.java b/jdk/src/java.desktop/share/classes/java/beans/Introspector.java index 079b348c8b3..6b88e9a87fb 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/Introspector.java +++ b/jdk/src/java.desktop/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -35,16 +35,19 @@ import java.awt.Component; import java.lang.ref.Reference; import java.lang.ref.SoftReference; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Map; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.EventObject; import java.util.List; import java.util.TreeMap; +import sun.misc.JavaBeansAccess; import sun.misc.SharedSecrets; import sun.reflect.misc.ReflectUtil; @@ -146,15 +149,25 @@ public class Introspector { // register with SharedSecrets for JMX usage static { - SharedSecrets.setJavaBeansIntrospectorAccess((clazz, property) -> { - BeanInfo bi = Introspector.getBeanInfo(clazz); - PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - for (PropertyDescriptor pd: pds) { - if (pd.getName().equals(property)) { - return pd.getReadMethod(); + SharedSecrets.setJavaBeansAccess(new JavaBeansAccess() { + @Override + public Method getReadMethod(Class clazz, String property) throws Exception { + BeanInfo bi = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] pds = bi.getPropertyDescriptors(); + for (PropertyDescriptor pd: pds) { + if (pd.getName().equals(property)) { + return pd.getReadMethod(); + } } + return null; + } + + @Override + public String[] getConstructorPropertiesValue(Constructor ctr) { + ConstructorProperties cp = ctr.getAnnotation(ConstructorProperties.class); + String [] ret = cp != null ? cp.value() : null; + return ret; } - return null; }); } diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java index 740732b2f82..0b2835f9ee0 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -33,14 +33,12 @@ import static javax.management.openmbean.SimpleType.*; import com.sun.jmx.remote.util.EnvHelp; import java.io.InvalidObjectException; -import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.ref.WeakReference; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; @@ -1138,55 +1136,13 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { to getters. */ private static final class CompositeBuilderViaConstructor extends CompositeBuilder { - static class AnnotationHelper { - private static Class constructorPropertiesClass; - private static Method valueMethod; - static { - findConstructorPropertiesClass(); - } - - @SuppressWarnings("unchecked") - private static void findConstructorPropertiesClass() { - try { - constructorPropertiesClass = (Class) - Class.forName("java.beans.ConstructorProperties", false, - DefaultMXBeanMappingFactory.class.getClassLoader()); - valueMethod = constructorPropertiesClass.getMethod("value"); - } catch (ClassNotFoundException cnf) { - // java.beans not present - } catch (NoSuchMethodException e) { - // should not reach here - throw new InternalError(e); - } - } - - static boolean isAvailable() { - return constructorPropertiesClass != null; - } - - static String[] getPropertyNames(Constructor constr) { - if (!isAvailable()) - return null; - - Annotation a = constr.getAnnotation(constructorPropertiesClass); - if (a == null) return null; - - try { - return (String[]) valueMethod.invoke(a); - } catch (InvocationTargetException e) { - throw new InternalError(e); - } catch (IllegalAccessException e) { - throw new InternalError(e); - } - } - } CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) { super(targetClass, itemNames); } String applicable(Method[] getters) throws InvalidObjectException { - if (!AnnotationHelper.isAvailable()) + if (!JavaBeansAccessor.isAvailable()) return "@ConstructorProperties annotation not available"; Class targetClass = getTargetClass(); @@ -1196,7 +1152,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { List> annotatedConstrList = newList(); for (Constructor constr : constrs) { if (Modifier.isPublic(constr.getModifiers()) - && AnnotationHelper.getPropertyNames(constr) != null) + && JavaBeansAccessor.getConstructorPropertiesValue(constr) != null) annotatedConstrList.add(constr); } @@ -1225,7 +1181,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { // so we can test unambiguity. Set getterIndexSets = newSet(); for (Constructor constr : annotatedConstrList) { - String[] propertyNames = AnnotationHelper.getPropertyNames(constr); + String[] propertyNames = JavaBeansAccessor.getConstructorPropertiesValue(constr); Type[] paramTypes = constr.getGenericParameterTypes(); if (paramTypes.length != propertyNames.length) { diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java index d713166c504..e3c273328fc 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -56,7 +56,7 @@ import java.security.AccessController; import javax.management.AttributeNotFoundException; import javax.management.openmbean.CompositeData; -import sun.misc.JavaBeansIntrospectorAccess; +import sun.misc.JavaBeansAccess; import sun.misc.SharedSecrets; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; @@ -552,10 +552,8 @@ public class Introspector { // Java Beans introspection // Class clazz = complex.getClass(); - Method readMethod; - if (BeansIntrospector.isAvailable()) { - readMethod = BeansIntrospector.getReadMethod(clazz, element); - } else { + Method readMethod = JavaBeansAccessor.getReadMethod(clazz, element); + if (readMethod == null) { // Java Beans not available so use simple introspection // to locate method readMethod = SimpleIntrospector.getReadMethod(clazz, element); @@ -579,30 +577,6 @@ public class Introspector { } } - /** - * Provides access to java.beans.Introspector if available. - */ - private static class BeansIntrospector { - private static final JavaBeansIntrospectorAccess JBIA; - static { - // ensure that java.beans.Introspector is initialized (if present) - try { - Class.forName("java.beans.Introspector", true, - BeansIntrospector.class.getClassLoader()); - } catch (ClassNotFoundException ignore) { } - - JBIA = SharedSecrets.getJavaBeansIntrospectorAccess(); - } - - static boolean isAvailable() { - return JBIA != null; - } - - static Method getReadMethod(Class clazz, String property) throws Exception { - return JBIA.getReadMethod(clazz, property); - } - } - /** * A simple introspector that uses reflection to analyze a class and * identify its "getter" methods. This class is intended for use only when diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java new file mode 100644 index 00000000000..9f050bd6b11 --- /dev/null +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/JavaBeansAccessor.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package com.sun.jmx.mbeanserver; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import sun.misc.JavaBeansAccess; +import sun.misc.SharedSecrets; + +/** + * A centralized place for gaining access to java.beans related functionality - + * if available. + */ +class JavaBeansAccessor { + static { + // ensure that java.beans.Introspector is initialized (if present) + // it will fill in the SharedSecrets + try { + Class.forName("java.beans.Introspector", true, + JavaBeansAccessor.class.getClassLoader()); + } catch (ClassNotFoundException ignore) { } + } + + private static JavaBeansAccess getJavaBeansAccess() { + return SharedSecrets.getJavaBeansAccess(); + } + + static boolean isAvailable() { + return getJavaBeansAccess() != null; + } + + /** + * Returns the getter method for a property of the given name + * @param clazz The JavaBeans class + * @param property The property name + * @return The resolved property getter name or null + * @throws Exception + */ + static Method getReadMethod(Class clazz, String property) throws Exception { + JavaBeansAccess jba = getJavaBeansAccess(); + return jba != null ? jba.getReadMethod(clazz, property) : null; + } + + /** + * Return the value attribute of the associated + * @ConstructorProperties annotation if that is present. + * @param ctr The constructor to extract the annotation value from + * @return The {@code value} attribute of the @ConstructorProperties + * annotation or {@code null} if the constructor is not annotated by + * this annotation or the annotation is not accessible. + */ + static String[] getConstructorPropertiesValue(Constructor ctr) { + JavaBeansAccess jba = getJavaBeansAccess(); + return jba != null ? jba.getConstructorPropertiesValue(ctr) : null; + } +} From 8d0ec77fc6cf6873936c7f3b9961e427f0a80e2a Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 26 May 2015 14:47:12 +0300 Subject: [PATCH 041/117] 8080628: No mnemonics on Open and Save buttons in JFileChooser Reviewed-by: serb, alexsch --- .../swing/plaf/gtk/resources/gtk.properties | 6 +- .../plaf/gtk/resources/gtk_de.properties | 6 +- .../plaf/gtk/resources/gtk_es.properties | 6 +- .../plaf/gtk/resources/gtk_fr.properties | 6 +- .../plaf/gtk/resources/gtk_it.properties | 6 +- .../plaf/gtk/resources/gtk_ja.properties | 6 +- .../plaf/gtk/resources/gtk_ko.properties | 6 +- .../plaf/gtk/resources/gtk_pt_BR.properties | 6 +- .../plaf/gtk/resources/gtk_sv.properties | 6 +- .../plaf/gtk/resources/gtk_zh_CN.properties | 6 +- .../plaf/gtk/resources/gtk_zh_TW.properties | 6 +- .../plaf/basic/resources/basic.properties | 6 +- .../plaf/basic/resources/basic_de.properties | 6 +- .../plaf/basic/resources/basic_es.properties | 6 +- .../plaf/basic/resources/basic_fr.properties | 6 +- .../plaf/basic/resources/basic_it.properties | 6 +- .../basic/resources/basic_pt_BR.properties | 6 +- .../plaf/basic/resources/basic_sv.properties | 6 +- .../plaf/metal/resources/metal.properties | 2 - .../plaf/metal/resources/metal_de.properties | 2 - .../plaf/metal/resources/metal_es.properties | 2 - .../plaf/metal/resources/metal_fr.properties | 2 - .../plaf/metal/resources/metal_it.properties | 2 - .../plaf/metal/resources/metal_ja.properties | 2 - .../plaf/metal/resources/metal_ko.properties | 2 - .../metal/resources/metal_pt_BR.properties | 2 - .../plaf/metal/resources/metal_sv.properties | 2 - .../metal/resources/metal_zh_CN.properties | 2 - .../metal/resources/metal_zh_TW.properties | 2 - .../JFileChooser/8080628/bug8080628.java | 100 ++++++++++++++++++ 30 files changed, 154 insertions(+), 76 deletions(-) create mode 100644 jdk/test/javax/swing/JFileChooser/8080628/bug8080628.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk.properties index dc84d130187..ab5a2e4db4b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Error FileChooser.newFolderNoDirectoryError.textAndMnemonic=Error creating directory "{0}": No such file or directory FileChooser.deleteFileButton.textAndMnemonic=De&lete File FileChooser.renameFileButton.textAndMnemonic=&Rename File -FileChooser.cancelButton.textAndMnemonic=&Cancel -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Cancel +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Save FileChooser.openDialogTitle.textAndMnemonic=Open FileChooser.pathLabel.textAndMnemonic=&Selection: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties index a8985ce605f..1720c8e384a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_de.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Fehler FileChooser.newFolderNoDirectoryError.textAndMnemonic=Fehler beim Erstellen von Verzeichnis "{0}": Datei oder Verzeichnis nicht vorhanden FileChooser.deleteFileButton.textAndMnemonic=Datei &l\u00F6schen FileChooser.renameFileButton.textAndMnemonic=Datei &umbenennen -FileChooser.cancelButton.textAndMnemonic=&Abbrechen -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Abbrechen +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Speichern FileChooser.openDialogTitle.textAndMnemonic=\u00D6ffnen FileChooser.pathLabel.textAndMnemonic=Aus&wahl: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_es.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_es.properties index 412938e1a50..f5e90e19ce8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_es.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_es.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Error FileChooser.newFolderNoDirectoryError.textAndMnemonic=Error al crear el directorio "{0}": no existe dicho archivo o directorio FileChooser.deleteFileButton.textAndMnemonic=Su&primir Archivo FileChooser.renameFileButton.textAndMnemonic=Cambiar Nomb&re de Archivo -FileChooser.cancelButton.textAndMnemonic=&Cancelar -FileChooser.saveButton.textAndMnemonic=&Aceptar -FileChooser.openButton.textAndMnemonic=&Aceptar +FileChooser.cancelButton.textAndMnemonic=Cancelar +FileChooser.saveButton.textAndMnemonic=Aceptar +FileChooser.openButton.textAndMnemonic=Aceptar FileChooser.saveDialogTitle.textAndMnemonic=Guardar FileChooser.openDialogTitle.textAndMnemonic=Abrir FileChooser.pathLabel.textAndMnemonic=&Selecci\u00F3n: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_fr.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_fr.properties index 380f3d4426b..b436568b846 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_fr.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_fr.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Erreur FileChooser.newFolderNoDirectoryError.textAndMnemonic=Erreur lors de la cr\u00E9ation du r\u00E9pertoire "{0}" : ce fichier ou r\u00E9pertoire n''existe pas FileChooser.deleteFileButton.textAndMnemonic=Supprimer &le fichier FileChooser.renameFileButton.textAndMnemonic=&Renommer le fichier -FileChooser.cancelButton.textAndMnemonic=&Annuler -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Annuler +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Enregistrer FileChooser.openDialogTitle.textAndMnemonic=Ouvrir FileChooser.pathLabel.textAndMnemonic=&S\u00E9lection : diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_it.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_it.properties index c629de5dad8..7e955bf1bf9 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_it.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_it.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Errore FileChooser.newFolderNoDirectoryError.textAndMnemonic=Errore durante la creazione della directory "{0}": file o directory inesistente FileChooser.deleteFileButton.textAndMnemonic=E&limina file FileChooser.renameFileButton.textAndMnemonic=&Rinomina file -FileChooser.cancelButton.textAndMnemonic=&Annulla -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Annulla +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Salva FileChooser.openDialogTitle.textAndMnemonic=Apri FileChooser.pathLabel.textAndMnemonic=&Selezione: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ja.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ja.properties index 5f4343ea679..479abec7b8d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ja.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ja.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=\u30A8\u30E9\u30FC FileChooser.newFolderNoDirectoryError.textAndMnemonic=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u306E\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F: \u3053\u306E\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u5B58\u5728\u3057\u307E\u305B\u3093 FileChooser.deleteFileButton.textAndMnemonic=\u30D5\u30A1\u30A4\u30EB\u306E\u524A\u9664(&L) FileChooser.renameFileButton.textAndMnemonic=\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D\u5909\u66F4(&R) -FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88(&C) -FileChooser.saveButton.textAndMnemonic=OK(&O) -FileChooser.openButton.textAndMnemonic=OK(&O) +FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=\u4FDD\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u958B\u304F FileChooser.pathLabel.textAndMnemonic=\u9078\u629E(&S): diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ko.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ko.properties index c3696a95a88..a43a8be7062 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ko.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_ko.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=\uC624\uB958 FileChooser.newFolderNoDirectoryError.textAndMnemonic="{0}" \uB514\uB809\uD1A0\uB9AC\uB97C \uC0DD\uC131\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: \uD574\uB2F9 \uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. FileChooser.deleteFileButton.textAndMnemonic=\uD30C\uC77C \uC0AD\uC81C(&L) FileChooser.renameFileButton.textAndMnemonic=\uD30C\uC77C \uC774\uB984 \uBC14\uAFB8\uAE30(&R) -FileChooser.cancelButton.textAndMnemonic=\uCDE8\uC18C(&C) -FileChooser.saveButton.textAndMnemonic=\uD655\uC778(&O) -FileChooser.openButton.textAndMnemonic=\uD655\uC778(&O) +FileChooser.cancelButton.textAndMnemonic=\uCDE8\uC18C +FileChooser.saveButton.textAndMnemonic=\uD655\uC778 +FileChooser.openButton.textAndMnemonic=\uD655\uC778 FileChooser.saveDialogTitle.textAndMnemonic=\uC800\uC7A5 FileChooser.openDialogTitle.textAndMnemonic=\uC5F4\uAE30 FileChooser.pathLabel.textAndMnemonic=\uC120\uD0DD \uC0AC\uD56D(&S): diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_pt_BR.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_pt_BR.properties index 383fd9f7d6e..c6c6649a011 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_pt_BR.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_pt_BR.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Erro FileChooser.newFolderNoDirectoryError.textAndMnemonic=Erro ao criar o diret\u00F3rio "{0}": N\u00E3o h\u00E1 arquivo ou diret\u00F3rio FileChooser.deleteFileButton.textAndMnemonic=De&letar Arquivo FileChooser.renameFileButton.textAndMnemonic=&Renomear Arquivo -FileChooser.cancelButton.textAndMnemonic=&Cancelar -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Cancelar +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Salvar FileChooser.openDialogTitle.textAndMnemonic=Abrir FileChooser.pathLabel.textAndMnemonic=&Sele\u00E7\u00E3o: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_sv.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_sv.properties index 1737b5761bd..5149f9e9b6a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_sv.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_sv.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=Fel FileChooser.newFolderNoDirectoryError.textAndMnemonic=Ett fel intr\u00E4ffade vid f\u00F6rs\u00F6k att skapa katalogen "{0}": Filen eller katalogen finns inte FileChooser.deleteFileButton.textAndMnemonic=Ta &bort fil FileChooser.renameFileButton.textAndMnemonic=&\u00C4ndra namn p\u00E5 filen -FileChooser.cancelButton.textAndMnemonic=&Avbryt -FileChooser.saveButton.textAndMnemonic=&OK -FileChooser.openButton.textAndMnemonic=&OK +FileChooser.cancelButton.textAndMnemonic=Avbryt +FileChooser.saveButton.textAndMnemonic=OK +FileChooser.openButton.textAndMnemonic=OK FileChooser.saveDialogTitle.textAndMnemonic=Spara FileChooser.openDialogTitle.textAndMnemonic=\u00D6ppna FileChooser.pathLabel.textAndMnemonic=&Urval: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_CN.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_CN.properties index 9e00fe1f99e..12ab10ec21e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_CN.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_CN.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=\u9519\u8BEF FileChooser.newFolderNoDirectoryError.textAndMnemonic=\u521B\u5EFA\u76EE\u5F55 "{0}" \u65F6\u51FA\u9519: \u6CA1\u6709\u6B64\u7C7B\u6587\u4EF6\u6216\u76EE\u5F55 FileChooser.deleteFileButton.textAndMnemonic=\u5220\u9664\u6587\u4EF6(&L) FileChooser.renameFileButton.textAndMnemonic=\u91CD\u547D\u540D\u6587\u4EF6(&R) -FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88(&C) -FileChooser.saveButton.textAndMnemonic=\u786E\u5B9A(&O) -FileChooser.openButton.textAndMnemonic=\u786E\u5B9A(&O) +FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 +FileChooser.saveButton.textAndMnemonic=\u786E\u5B9A +FileChooser.openButton.textAndMnemonic=\u786E\u5B9A FileChooser.saveDialogTitle.textAndMnemonic=\u4FDD\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u6253\u5F00 FileChooser.pathLabel.textAndMnemonic=\u9009\u5B9A\u5185\u5BB9(&S): diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_TW.properties b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_TW.properties index 9ee492a4b73..807b0d31cc0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_TW.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources/gtk_zh_TW.properties @@ -34,9 +34,9 @@ FileChooser.newFolderNoDirectoryErrorTitle.textAndMnemonic=\u932F\u8AA4 FileChooser.newFolderNoDirectoryError.textAndMnemonic=\u5EFA\u7ACB\u76EE\u9304 "{0}" \u6642\u767C\u751F\u932F\u8AA4: \u6C92\u6709\u6B64\u6A94\u6848\u6216\u76EE\u9304 FileChooser.deleteFileButton.textAndMnemonic=\u522A\u9664\u6A94\u6848(&L) FileChooser.renameFileButton.textAndMnemonic=\u91CD\u65B0\u547D\u540D\u6A94\u6848(&R) -FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88(&C) -FileChooser.saveButton.textAndMnemonic=\u78BA\u5B9A(&O) -FileChooser.openButton.textAndMnemonic=\u78BA\u5B9A(&O) +FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 +FileChooser.saveButton.textAndMnemonic=\u78BA\u5B9A +FileChooser.openButton.textAndMnemonic=\u78BA\u5B9A FileChooser.saveDialogTitle.textAndMnemonic=\u5132\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u958B\u555F FileChooser.pathLabel.textAndMnemonic=\u9078\u53D6(&S): diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties index 4a8d160c02c..01b5218a884 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties @@ -43,13 +43,13 @@ FileChooser.renameErrorFileExists.textAndMnemonic=Cannot rename {0}: A file with Specify a different file name. FileChooser.acceptAllFileFilter.textAndMnemonic=All Files FileChooser.cancelButton.textAndMnemonic=Cancel -FileChooser.saveButton.textAndMnemonic=&Save -FileChooser.openButton.textAndMnemonic=&Open +FileChooser.saveButton.textAndMnemonic=Save +FileChooser.openButton.textAndMnemonic=Open FileChooser.saveDialogTitle.textAndMnemonic=Save FileChooser.openDialogTitle.textAndMnemonic=Open FileChooser.updateButton.textAndMnemonic=&Update FileChooser.helpButton.textAndMnemonic=&Help -FileChooser.directoryOpenButton.textAndMnemonic=&Open +FileChooser.directoryOpenButton.textAndMnemonic=Open # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties index 5f3d8e2494c..bd8ad6d6af6 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0} kann nicht umbenannt werden FileChooser.renameErrorFileExists.textAndMnemonic={0} kann nicht umbenannt werden: Es ist bereits eine Datei mit dem angegebenen Namen vorhanden. Geben Sie einen anderen Dateinamen an. FileChooser.acceptAllFileFilter.textAndMnemonic=Alle Dateien FileChooser.cancelButton.textAndMnemonic=Abbrechen -FileChooser.saveButton.textAndMnemonic=&Speichern -FileChooser.openButton.textAndMnemonic=\u00D6&ffnen +FileChooser.saveButton.textAndMnemonic=Speichern +FileChooser.openButton.textAndMnemonic=\u00D6ffnen FileChooser.saveDialogTitle.textAndMnemonic=Speichern FileChooser.openDialogTitle.textAndMnemonic=\u00D6ffnen FileChooser.updateButton.textAndMnemonic=A&ktualisieren FileChooser.helpButton.textAndMnemonic=&Hilfe -FileChooser.directoryOpenButton.textAndMnemonic=\u00D6&ffnen +FileChooser.directoryOpenButton.textAndMnemonic=\u00D6ffnen # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties index 485ed06aeff..71d145cfbcf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=No se puede cambiar el nombre de {0} FileChooser.renameErrorFileExists.textAndMnemonic=No se puede cambiar el nombre de {0}: ya existe un archivo con el nombre especificado. Especifique otro nombre de archivo. FileChooser.acceptAllFileFilter.textAndMnemonic=Todos los Archivos FileChooser.cancelButton.textAndMnemonic=Cancelar -FileChooser.saveButton.textAndMnemonic=&Guardar -FileChooser.openButton.textAndMnemonic=&Abrir +FileChooser.saveButton.textAndMnemonic=Guardar +FileChooser.openButton.textAndMnemonic=Abrir FileChooser.saveDialogTitle.textAndMnemonic=Guardar FileChooser.openDialogTitle.textAndMnemonic=Abrir FileChooser.updateButton.textAndMnemonic=Act&ualizar FileChooser.helpButton.textAndMnemonic=A&yuda -FileChooser.directoryOpenButton.textAndMnemonic=&Abrir +FileChooser.directoryOpenButton.textAndMnemonic=Abrir # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties index ac89a2258be..3ee5668e23a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=Impossible de renommer {0} FileChooser.renameErrorFileExists.textAndMnemonic=Impossible de renommer {0} : il existe d\u00E9j\u00E0 un fichier portant le nom indiqu\u00E9. Indiquez-en un autre. FileChooser.acceptAllFileFilter.textAndMnemonic=Tous les fichiers FileChooser.cancelButton.textAndMnemonic=Annuler -FileChooser.saveButton.textAndMnemonic=Enregi&strer -FileChooser.openButton.textAndMnemonic=&Ouvrir +FileChooser.saveButton.textAndMnemonic=Enregistrer +FileChooser.openButton.textAndMnemonic=Ouvrir FileChooser.saveDialogTitle.textAndMnemonic=Enregistrer FileChooser.openDialogTitle.textAndMnemonic=Ouvrir FileChooser.updateButton.textAndMnemonic=Mettre \u00E0 jo&ur FileChooser.helpButton.textAndMnemonic=&Aide -FileChooser.directoryOpenButton.textAndMnemonic=&Ouvrir +FileChooser.directoryOpenButton.textAndMnemonic=Ouvrir # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties index c86d214cc9c..7844f11f719 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=Impossibile rinominare {0} FileChooser.renameErrorFileExists.textAndMnemonic=Impossibile rinominare {0}: esiste gi\u00E0 un file con il nome specificato. Specificare un altro nome. FileChooser.acceptAllFileFilter.textAndMnemonic=Tutti i file FileChooser.cancelButton.textAndMnemonic=Annulla -FileChooser.saveButton.textAndMnemonic=Sal&va -FileChooser.openButton.textAndMnemonic=&Apri +FileChooser.saveButton.textAndMnemonic=Salva +FileChooser.openButton.textAndMnemonic=Apri FileChooser.saveDialogTitle.textAndMnemonic=Salva FileChooser.openDialogTitle.textAndMnemonic=Apri FileChooser.updateButton.textAndMnemonic=Ag&giorna FileChooser.helpButton.textAndMnemonic=&? -FileChooser.directoryOpenButton.textAndMnemonic=&Apri +FileChooser.directoryOpenButton.textAndMnemonic=Apri # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_pt_BR.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_pt_BR.properties index 5c5ad20f963..f29f4ec5c05 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_pt_BR.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_pt_BR.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=N\u00E3o \u00E9 poss\u00EDvel renomear { FileChooser.renameErrorFileExists.textAndMnemonic=N\u00E3o \u00E9 poss\u00EDvel renomear {0}: Um arquivo com o nome especificado j\u00E1 existe. Especifique outro nome de arquivo. FileChooser.acceptAllFileFilter.textAndMnemonic=Todos os Arquivos FileChooser.cancelButton.textAndMnemonic=Cancelar -FileChooser.saveButton.textAndMnemonic=&Salvar -FileChooser.openButton.textAndMnemonic=A&brir +FileChooser.saveButton.textAndMnemonic=Salvar +FileChooser.openButton.textAndMnemonic=Abrir FileChooser.saveDialogTitle.textAndMnemonic=Salvar FileChooser.openDialogTitle.textAndMnemonic=Abrir FileChooser.updateButton.textAndMnemonic=At&ualizar FileChooser.helpButton.textAndMnemonic=Aj&uda -FileChooser.directoryOpenButton.textAndMnemonic=A&brir +FileChooser.directoryOpenButton.textAndMnemonic=Abrir # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties index 825a0257e96..8c8a501a294 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=Kan inte namn\u00E4ndra {0} FileChooser.renameErrorFileExists.textAndMnemonic=Kan inte namn\u00E4ndra {0}: En fil med angivet namn finns redan. Ange ett annat filnamn. FileChooser.acceptAllFileFilter.textAndMnemonic=Alla filer FileChooser.cancelButton.textAndMnemonic=Avbryt -FileChooser.saveButton.textAndMnemonic=&Spara -FileChooser.openButton.textAndMnemonic=&\u00D6ppna +FileChooser.saveButton.textAndMnemonic=Spara +FileChooser.openButton.textAndMnemonic=\u00D6ppna FileChooser.saveDialogTitle.textAndMnemonic=Spara FileChooser.openDialogTitle.textAndMnemonic=\u00D6ppna FileChooser.updateButton.textAndMnemonic=Upp&datera FileChooser.helpButton.textAndMnemonic=&Hj\u00E4lp -FileChooser.directoryOpenButton.textAndMnemonic=&\u00D6ppna +FileChooser.directoryOpenButton.textAndMnemonic=\u00D6ppna # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties index 431d7124fac..cd35fd8bd1b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Size FileChooser.fileTypeHeader.textAndMnemonic=Type FileChooser.fileDateHeader.textAndMnemonic=Modified FileChooser.fileAttrHeader.textAndMnemonic=Attributes -FileChooser.saveButton.textAndMnemonic=Save -FileChooser.openButton.textAndMnemonic=Open ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Restore diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties index 48315d3553b..af23756487f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Gr\u00F6\u00DFe FileChooser.fileTypeHeader.textAndMnemonic=Typ FileChooser.fileDateHeader.textAndMnemonic=Ge\u00E4ndert FileChooser.fileAttrHeader.textAndMnemonic=Attribute -FileChooser.saveButton.textAndMnemonic=Speichern -FileChooser.openButton.textAndMnemonic=\u00D6ffnen ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Wiederherstellen diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties index 72ec82e2efa..09df76e76b7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Tama\u00F1o FileChooser.fileTypeHeader.textAndMnemonic=Tipo FileChooser.fileDateHeader.textAndMnemonic=Modificado FileChooser.fileAttrHeader.textAndMnemonic=Atributos -FileChooser.saveButton.textAndMnemonic=Guardar -FileChooser.openButton.textAndMnemonic=Abrir ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Restaurar diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties index 05a1c7016b5..9dd46c0dec7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Taille FileChooser.fileTypeHeader.textAndMnemonic=Type FileChooser.fileDateHeader.textAndMnemonic=Modifi\u00E9 FileChooser.fileAttrHeader.textAndMnemonic=Attributs -FileChooser.saveButton.textAndMnemonic=Enregistrer -FileChooser.openButton.textAndMnemonic=Ouvrir ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Restaurer diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties index 61946214225..9b3e47142ef 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Dimensioni FileChooser.fileTypeHeader.textAndMnemonic=Tipo FileChooser.fileDateHeader.textAndMnemonic=Modificato FileChooser.fileAttrHeader.textAndMnemonic=Attributi -FileChooser.saveButton.textAndMnemonic=Salva -FileChooser.openButton.textAndMnemonic=Apri ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Ripristina diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties index 8a8fef8b7ee..4aa9ebda3c3 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=\u30B5\u30A4\u30BA FileChooser.fileTypeHeader.textAndMnemonic=\u30BF\u30A4\u30D7 FileChooser.fileDateHeader.textAndMnemonic=\u4FEE\u6B63\u65E5 FileChooser.fileAttrHeader.textAndMnemonic=\u5C5E\u6027 -FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58 -FileChooser.openButton.textAndMnemonic=\u958B\u304F ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=\u5FA9\u5143(&R) diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties index 264976c8974..f01b47d1ab7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=\uD06C\uAE30 FileChooser.fileTypeHeader.textAndMnemonic=\uC720\uD615 FileChooser.fileDateHeader.textAndMnemonic=\uC218\uC815 \uB0A0\uC9DC FileChooser.fileAttrHeader.textAndMnemonic=\uC18D\uC131 -FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5 -FileChooser.openButton.textAndMnemonic=\uC5F4\uAE30 ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=\uBCF5\uC6D0(&R) diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties index 79c45cb338b..2edccf06dbf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_pt_BR.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Tamanho FileChooser.fileTypeHeader.textAndMnemonic=Tipo FileChooser.fileDateHeader.textAndMnemonic=Modificado FileChooser.fileAttrHeader.textAndMnemonic=Atributos -FileChooser.saveButton.textAndMnemonic=Salvar -FileChooser.openButton.textAndMnemonic=Abrir ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&Restaurar diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties index 1b9b7e217c7..08e642cda2a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=Storlek FileChooser.fileTypeHeader.textAndMnemonic=Typ FileChooser.fileDateHeader.textAndMnemonic=\u00C4ndrad FileChooser.fileAttrHeader.textAndMnemonic=Attribut -FileChooser.saveButton.textAndMnemonic=Spara -FileChooser.openButton.textAndMnemonic=\u00D6ppna ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=&\u00C5terst\u00E4ll diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties index 2d6cf13f3fa..d1bda4d699d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=\u5927\u5C0F FileChooser.fileTypeHeader.textAndMnemonic=\u7C7B\u578B FileChooser.fileDateHeader.textAndMnemonic=\u4FEE\u6539\u65E5\u671F FileChooser.fileAttrHeader.textAndMnemonic=\u5C5E\u6027 -FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58 -FileChooser.openButton.textAndMnemonic=\u6253\u5F00 ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=\u8FD8\u539F(&R) diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties index 1d2b826d95b..45045af4813 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties @@ -43,8 +43,6 @@ FileChooser.fileSizeHeader.textAndMnemonic=\u5927\u5C0F FileChooser.fileTypeHeader.textAndMnemonic=\u985E\u578B FileChooser.fileDateHeader.textAndMnemonic=\u4FEE\u6539\u65E5\u671F FileChooser.fileAttrHeader.textAndMnemonic=\u5C6C\u6027 -FileChooser.saveButton.textAndMnemonic=\u5132\u5B58 -FileChooser.openButton.textAndMnemonic=\u958B\u555F ############ Used by MetalTitlePane if rendering window decorations############ MetalTitlePane.restore.titleAndMnemonic=\u56DE\u5FA9(&R) diff --git a/jdk/test/javax/swing/JFileChooser/8080628/bug8080628.java b/jdk/test/javax/swing/JFileChooser/8080628/bug8080628.java new file mode 100644 index 00000000000..fc72ef2fc96 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/8080628/bug8080628.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 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. + */ + +import java.util.Locale; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; + +import sun.swing.SwingUtilities2; + +/* + * @test + * @bug 8080628 + * @summary No mnemonics on Open and Save buttons in JFileChooser. + * @author Alexey Ivanov + * @run main bug8080628 + */ +public class bug8080628 { + public static final String[] MNEMONIC_KEYS = new String[] { + "FileChooser.saveButtonMnemonic", + "FileChooser.openButtonMnemonic", + "FileChooser.cancelButtonMnemonic", + "FileChooser.directoryOpenButtonMnemonic" + }; + + public static final Locale[] LOCALES = new Locale[] { + new Locale("en"), + new Locale("de"), + new Locale("es"), + new Locale("fr"), + new Locale("it"), + new Locale("ja"), + new Locale("ko"), + new Locale("pt", "BR"), + new Locale("sv"), + new Locale("zh", "CN"), + new Locale("zh", "TW") + }; + + private static volatile Exception exception; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + runTest(); + } + }); + + if (exception != null) { + throw exception; + } + } + + private static void runTest() { + try { + LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels(); + for (LookAndFeelInfo info : lafInfo) { + UIManager.setLookAndFeel(info.getClassName()); + + for (Locale locale : LOCALES) { + for (String key : MNEMONIC_KEYS) { + int mnemonic = SwingUtilities2.getUIDefaultsInt(key, locale); + if (mnemonic != 0) { + throw new RuntimeException("No mnemonic expected (" + mnemonic + ") " + + "for '" + key + "' " + + "in locale '" + locale + "' " + + "in Look-and-Feel '" + + UIManager.getLookAndFeel().getClass().getName() + "'"); + } + } + } + } + System.out.println("Test passed"); + } catch (Exception e) { + exception = e; + } + } + +} From 6fe284e4018b2586f60876ca4f9452e52db44ae7 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 26 May 2015 15:06:42 -0700 Subject: [PATCH 042/117] 8081231: JDK9 client build broken on Windows Reviewed-by: azvegint --- .../windows/native/libawt/windows/ShellFolder2.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp index cd3918bd4eb..0f5a0e8d942 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp @@ -64,6 +64,9 @@ DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0); //#include +#ifndef DASSERT +#define DASSERT(x) +#endif #define DEFINE_FIELD_ID(var, cls, field, type) \ jfieldID var = env->GetFieldID(cls, field, type); \ DASSERT(var != NULL); \ From adc531d210a52de1f8a34b308da56cc6bf423544 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 29 May 2015 09:41:20 +0800 Subject: [PATCH 043/117] 8051952: Unreachable.java test failing on Windows Reviewed-by: xuelei --- jdk/test/ProblemList.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 37bc736a7ac..df34b7e011c 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -222,8 +222,7 @@ java/rmi/activation/Activatable/extLoadedImpl/ext.sh generic-all sun/security/pkcs11/ec/TestKeyFactory.java generic-all # 7164518: no PortUnreachableException on Mac -# 8051952: Unreachable.java test failing on Windows -sun/security/krb5/auto/Unreachable.java windows-all,macosx-all +sun/security/krb5/auto/Unreachable.java macosx-all # 8058849 sun/security/krb5/config/dns.sh generic-all From 4815781a4a335e909cdeec700bad3a0563b79d64 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Fri, 29 May 2015 09:15:42 +0530 Subject: [PATCH 044/117] 8081271: NPE while compiling a program with erroneous use of constructor reference expressions Missing enclosing instance error should not be swallowed when attributing constructor reference expressions. Reviewed-by: mcimadamore, vromero --- .../com/sun/tools/javac/comp/Resolve.java | 6 ++--- .../tools/javac/lambda/MethodReference23.java | 6 ++--- .../tools/javac/lambda/MethodReference23.out | 2 +- .../tools/javac/lambda/MethodReference37.java | 4 ++-- .../tools/javac/lambda/MethodReference37.out | 4 ++-- .../MethodRefToInnerWithoutOuter.java | 24 +++++++++++++++++++ .../MethodRefToInnerWithoutOuter.out | 2 ++ 7 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.java create mode 100644 langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 741ebb6c33e..64c8cb2521d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -3185,10 +3185,8 @@ public class Resolve { findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) : findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()); - return (sym.kind != MTH || - site.getEnclosingType().hasTag(NONE) || - hasEnclosingInstance(env, site)) ? - sym : new BadConstructorReferenceError(sym); + return site.getEnclosingType().hasTag(CLASS) && !hasEnclosingInstance(env, site) ? + new BadConstructorReferenceError(sym) : sym; } @Override diff --git a/langtools/test/tools/javac/lambda/MethodReference23.java b/langtools/test/tools/javac/lambda/MethodReference23.java index 2ac0e04b3ee..917ccf8e4ed 100644 --- a/langtools/test/tools/javac/lambda/MethodReference23.java +++ b/langtools/test/tools/javac/lambda/MethodReference23.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 8075184 + * @bug 8003280 8075184 8081271 * @summary Add lambda tests * check that pair of bound/non-bound constructor references is flagged as ambiguous * @author Maurizio Cimadamore @@ -49,8 +49,8 @@ class MethodReference23 { static void call3(SAM22 s) { } static void test11() { - SAM11 s = MethodReference23.Inner1::new; //ok - call11(MethodReference23.Inner1::new); //ok + SAM11 s = MethodReference23.Inner1::new; // fail. + call11(MethodReference23.Inner1::new); // fail. } static void test12() { diff --git a/langtools/test/tools/javac/lambda/MethodReference23.out b/langtools/test/tools/javac/lambda/MethodReference23.out index 456a002bd99..f81c0a6745e 100644 --- a/langtools/test/tools/javac/lambda/MethodReference23.out +++ b/langtools/test/tools/javac/lambda/MethodReference23.out @@ -1,5 +1,5 @@ MethodReference23.java:52:19: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23) -MethodReference23.java:53:16: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23) +MethodReference23.java:53:16: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23) MethodReference23.java:57:19: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23) MethodReference23.java:58:16: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23) MethodReference23.java:72:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference23.SAM21), MethodReference23, kindname.method, call3(MethodReference23.SAM22), MethodReference23 diff --git a/langtools/test/tools/javac/lambda/MethodReference37.java b/langtools/test/tools/javac/lambda/MethodReference37.java index c991a957a7e..513971fda7b 100644 --- a/langtools/test/tools/javac/lambda/MethodReference37.java +++ b/langtools/test/tools/javac/lambda/MethodReference37.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 + * @bug 8003280 8081271 * @summary Add lambda tests * spurious exceptions when checking references to inner constructors where * the enclosing class is not defined in any outer context @@ -20,7 +20,7 @@ class MethodReference37 { static class Outer { class Inner { } - static void test1() { + void test1() { SAM2 sam = Inner::new; } diff --git a/langtools/test/tools/javac/lambda/MethodReference37.out b/langtools/test/tools/javac/lambda/MethodReference37.out index 09dc966bd4a..8db8e456daf 100644 --- a/langtools/test/tools/javac/lambda/MethodReference37.out +++ b/langtools/test/tools/javac/lambda/MethodReference37.out @@ -1,5 +1,5 @@ MethodReference37.java:24:38: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) MethodReference37.java:29:39: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) -MethodReference37.java:34:40: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) -MethodReference37.java:38:41: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Inner, compiler.misc.no.args, MethodReference37.Outer, kindname.class, MethodReference37.Outer.Inner, (compiler.misc.arg.length.mismatch))) +MethodReference37.java:34:40: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner, MethodReference37.Outer, MethodReference37.Outer) +MethodReference37.java:38:41: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner, MethodReference37.Outer, MethodReference37.Outer) 4 errors diff --git a/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.java b/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.java new file mode 100644 index 00000000000..39b81f1b2e9 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.java @@ -0,0 +1,24 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8081271 + * @summary NPE while compiling a program with erroneous use of constructor reference expressions. + * @compile/fail/ref=MethodRefToInnerWithoutOuter.out -XDrawDiagnostics MethodRefToInnerWithoutOuter.java +*/ + +import java.util.List; +import java.util.ArrayList; + +class MethodRefToInnerBase { + class TestString { + String str; + TestString(String strin) { + str = strin; + } + } +} +public class MethodRefToInnerWithoutOuter extends MethodRefToInnerBase { + public static void main(String[] args) { + List list = new ArrayList<>(); + list.stream().forEach(TestString::new); + } +} diff --git a/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out b/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out new file mode 100644 index 00000000000..bafb5d1a193 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/MethodRefToInnerWithoutOuter.out @@ -0,0 +1,2 @@ +MethodRefToInnerWithoutOuter.java:22:31: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: TestString, , MethodRefToInnerBase) +1 error From f1a3698f4c30ac989dd2287e6ad33218d30f9fbb Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Fri, 29 May 2015 10:15:36 +0530 Subject: [PATCH 045/117] 8080842: Using Lambda Expression with name clash results in ClassFormatError Ensure ScopeImpl can cope properly with remove when a field and method share the name Reviewed-by: mcimadamore, jlahoda --- .../com/sun/tools/javac/code/Scope.java | 7 +- .../tools/javac/scope/RemoveSymbolTest.java | 77 +++++++++++++++ .../javac/scope/RemoveSymbolUnitTest.java | 98 +++++++++++++++++++ 3 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 langtools/test/tools/javac/scope/RemoveSymbolTest.java create mode 100644 langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java index a47d5a585e1..dac3ce31329 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -407,12 +407,11 @@ public abstract class Scope { } } - /** Remove symbol from this scope. Used when an inner class - * attribute tells us that the class isn't a package member. + /** Remove symbol from this scope. */ public void remove(Symbol sym) { Assert.check(shared == 0); - Entry e = lookup(sym.name); + Entry e = lookup(sym.name, candidate -> candidate == sym); if (e.scope == null) return; // remove e from table and shadowed list; diff --git a/langtools/test/tools/javac/scope/RemoveSymbolTest.java b/langtools/test/tools/javac/scope/RemoveSymbolTest.java new file mode 100644 index 00000000000..bc466dfa4c6 --- /dev/null +++ b/langtools/test/tools/javac/scope/RemoveSymbolTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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 8080842 + * @summary Ensure Scope impl can cope with remove() when a field and method share the name. + * @run main RemoveSymbolTest + */ + +import java.util.Iterator; +import java.util.LinkedList; + +public class RemoveSymbolTest implements Iterable { + static class Widget { + private String name; + Widget(String s) { name = s; } + @Override public String toString() { return name; } + } + + private LinkedList data; + // Instantiate an Iterable instance using a Lambda expression. + // Causes ClassFormatError if a local variable of type Widget is named after one of the methods. + private final Iterable myIterator1 = () -> new Iterator() { + private W hasNext = null; + private int index = 0; + @Override public boolean hasNext() { return index < data.size(); } + @Override public W next() { return data.get(index++); } + }; + + // Instantiate an Iterable instance using an anonymous class. + // Always works fine regardless of the name of the local variable. + private final Iterable myIterator2 = + new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + private W hasNext = null; + private int index = 0; + @Override public boolean hasNext() { return index < data.size(); } + @Override public W next() { return data.get(index++); } + }; + } + }; + public RemoveSymbolTest() { data = new LinkedList<>(); } + public void add(W e) { data.add(e); } + @Override public String toString() { return data.toString(); } + @Override public Iterator iterator() { return myIterator1.iterator(); } + public static void main(String[] args) { + RemoveSymbolTest widgets = new RemoveSymbolTest<>(); + widgets.add(new Widget("W1")); + widgets.add(new Widget("W2")); + widgets.add(new Widget("W3")); + System.out.println(".foreach() call: "); + widgets.forEach(w -> System.out.println(w + " ")); + } +} diff --git a/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java b/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java new file mode 100644 index 00000000000..cf21521bc2e --- /dev/null +++ b/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 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 8080842 + * @summary Ensure Scope impl can cope with remove() when a field and method share the name. + * @modules jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.util + */ + +import com.sun.tools.javac.util.*; +import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Scope.*; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.file.JavacFileManager; + +public class RemoveSymbolUnitTest { + + Context context; + Names names; + Symtab symtab; + + public static void main(String... args) throws Exception { + new RemoveSymbolUnitTest().run(); + } + + public void run() { + context = new Context(); + JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab + names = Names.instance(context); + symtab = Symtab.instance(context); + + Name hasNext = names.fromString("hasNext"); + ClassSymbol clazz = new ClassSymbol(0, + names.fromString("X"), + Type.noType, + symtab.unnamedPackage); + + VarSymbol v = new VarSymbol(0, hasNext, Type.noType, clazz); + MethodSymbol m = new MethodSymbol(0, hasNext, Type.noType, clazz); + + // Try enter and remove in different shuffled combinations. + // working with fresh scope each time. + WriteableScope cs = WriteableScope.create(clazz); + cs.enter(v); + cs.enter(m); + cs.remove(v); + Symbol s = cs.findFirst(hasNext); + if (s != m) + throw new AssertionError("Wrong symbol"); + + cs = WriteableScope.create(clazz); + cs.enter(m); + cs.enter(v); + cs.remove(v); + s = cs.findFirst(hasNext); + if (s != m) + throw new AssertionError("Wrong symbol"); + + cs = WriteableScope.create(clazz); + cs.enter(v); + cs.enter(m); + cs.remove(m); + s = cs.findFirst(hasNext); + if (s != v) + throw new AssertionError("Wrong symbol"); + + cs = WriteableScope.create(clazz); + cs.enter(m); + cs.enter(v); + cs.remove(m); + s = cs.findFirst(hasNext); + if (s != v) + throw new AssertionError("Wrong symbol"); + } +} From 9cc4a70ee91872142d485d0e2a3bbde8b0239f54 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Fri, 29 May 2015 11:05:52 +0200 Subject: [PATCH 046/117] 8081470: com/sun/jdi tests are failing with "Error. failed to clean up files after test" with jtreg 4.1 b12 Reviewed-by: mgerdin, brutisso, iignatyev --- jdk/test/com/sun/jdi/AllLineLocations.java | 1 - jdk/test/com/sun/jdi/ClassesByName.java | 1 - jdk/test/com/sun/jdi/ExceptionEvents.java | 1 - jdk/test/com/sun/jdi/FilterMatch.java | 1 - jdk/test/com/sun/jdi/FilterNoMatch.java | 1 - jdk/test/com/sun/jdi/LaunchCommandLine.java | 1 - jdk/test/com/sun/jdi/ModificationWatchpoints.java | 1 - jdk/test/com/sun/jdi/NativeInstanceFilter.java | 1 - jdk/test/com/sun/jdi/UnpreparedByName.java | 1 - jdk/test/com/sun/jdi/UnpreparedClasses.java | 1 - jdk/test/com/sun/jdi/Vars.java | 1 - 11 files changed, 11 deletions(-) diff --git a/jdk/test/com/sun/jdi/AllLineLocations.java b/jdk/test/com/sun/jdi/AllLineLocations.java index ef85878e3f3..939880c5cca 100644 --- a/jdk/test/com/sun/jdi/AllLineLocations.java +++ b/jdk/test/com/sun/jdi/AllLineLocations.java @@ -27,7 +27,6 @@ * @summary Test ReferenceType.allLineLocations * @author Gordon Hirsch * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g RefTypes.java diff --git a/jdk/test/com/sun/jdi/ClassesByName.java b/jdk/test/com/sun/jdi/ClassesByName.java index 420b1cb703b..1e920328044 100644 --- a/jdk/test/com/sun/jdi/ClassesByName.java +++ b/jdk/test/com/sun/jdi/ClassesByName.java @@ -26,7 +26,6 @@ * @bug 4287992 * @author Robert Field * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g HelloWorld.java diff --git a/jdk/test/com/sun/jdi/ExceptionEvents.java b/jdk/test/com/sun/jdi/ExceptionEvents.java index ab8a66b0894..054ad248cc2 100644 --- a/jdk/test/com/sun/jdi/ExceptionEvents.java +++ b/jdk/test/com/sun/jdi/ExceptionEvents.java @@ -28,7 +28,6 @@ * * @author Robert Field * - * @library scaffold * @modules jdk.jdi * @run build TestScaffold VMConnection * @run compile -g ExceptionEvents.java diff --git a/jdk/test/com/sun/jdi/FilterMatch.java b/jdk/test/com/sun/jdi/FilterMatch.java index 3d3953b199a..478ec77f04a 100644 --- a/jdk/test/com/sun/jdi/FilterMatch.java +++ b/jdk/test/com/sun/jdi/FilterMatch.java @@ -28,7 +28,6 @@ * * @author Robert Field/Jim Holmlund * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g HelloWorld.java diff --git a/jdk/test/com/sun/jdi/FilterNoMatch.java b/jdk/test/com/sun/jdi/FilterNoMatch.java index 04038999c7b..1c3d6b81656 100644 --- a/jdk/test/com/sun/jdi/FilterNoMatch.java +++ b/jdk/test/com/sun/jdi/FilterNoMatch.java @@ -28,7 +28,6 @@ * * @author Robert Field/Jim Holmlund * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g HelloWorld.java diff --git a/jdk/test/com/sun/jdi/LaunchCommandLine.java b/jdk/test/com/sun/jdi/LaunchCommandLine.java index 65e7fa8d20c..3a55a5ce66d 100644 --- a/jdk/test/com/sun/jdi/LaunchCommandLine.java +++ b/jdk/test/com/sun/jdi/LaunchCommandLine.java @@ -27,7 +27,6 @@ * @summary Test launcher command line construction * @author Gordon Hirsch * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g HelloWorld.java diff --git a/jdk/test/com/sun/jdi/ModificationWatchpoints.java b/jdk/test/com/sun/jdi/ModificationWatchpoints.java index 0f407ac4269..482f8b78ef9 100644 --- a/jdk/test/com/sun/jdi/ModificationWatchpoints.java +++ b/jdk/test/com/sun/jdi/ModificationWatchpoints.java @@ -29,7 +29,6 @@ * @author Daniel Prusa (or someone in the FFJ group) * @author Robert Field (modified to JDIScaffold) * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g ModificationWatchpoints.java diff --git a/jdk/test/com/sun/jdi/NativeInstanceFilter.java b/jdk/test/com/sun/jdi/NativeInstanceFilter.java index f62ad007cd8..c14960860e1 100644 --- a/jdk/test/com/sun/jdi/NativeInstanceFilter.java +++ b/jdk/test/com/sun/jdi/NativeInstanceFilter.java @@ -28,7 +28,6 @@ * * @author Keith McGuigan * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @compile -XDignore.symbol.file NativeInstanceFilterTarg.java diff --git a/jdk/test/com/sun/jdi/UnpreparedByName.java b/jdk/test/com/sun/jdi/UnpreparedByName.java index 9e6b3d59922..aa7c6639f1e 100644 --- a/jdk/test/com/sun/jdi/UnpreparedByName.java +++ b/jdk/test/com/sun/jdi/UnpreparedByName.java @@ -28,7 +28,6 @@ * won't be returned by classesByName. * @author Robert Field * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g InnerTarg.java diff --git a/jdk/test/com/sun/jdi/UnpreparedClasses.java b/jdk/test/com/sun/jdi/UnpreparedClasses.java index 013b5ddcc33..4e96fb6415e 100644 --- a/jdk/test/com/sun/jdi/UnpreparedClasses.java +++ b/jdk/test/com/sun/jdi/UnpreparedClasses.java @@ -28,7 +28,6 @@ * loaded class list are prepared classes. * @author Robert Field * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g InnerTarg.java diff --git a/jdk/test/com/sun/jdi/Vars.java b/jdk/test/com/sun/jdi/Vars.java index c101e86fab5..edffff3f720 100644 --- a/jdk/test/com/sun/jdi/Vars.java +++ b/jdk/test/com/sun/jdi/Vars.java @@ -27,7 +27,6 @@ * * @author Robert Field * - * @library scaffold * @modules jdk.jdi * @run build JDIScaffold VMConnection * @run compile -g Vars.java From 38bcbb873f872284051218cfebb5e9fbce5991ef Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Fri, 29 May 2015 12:28:40 +0300 Subject: [PATCH 047/117] 8081392: getNodeValue should return 'null' value for Element nodes Reviewed-by: joehw --- .../sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java | 2 +- .../org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java | 6 +----- .../jaxp/unittest/javax/xml/transform/DocumentExtFunc.java | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java index d9ca5b010f5..5fdf6535a51 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMNodeProxy.java @@ -2116,7 +2116,7 @@ public class DTMNodeProxy */ @Override public String getTextContent() throws DOMException { - return getNodeValue(); // overriden in some subclasses + return dtm.getStringValue(node).toString(); } /** diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java index ea0e9b7a9a4..526f5e1b5f0 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java @@ -3145,11 +3145,7 @@ public class SAX2DTM2 extends SAX2DTM m_data.elementAt(-dataIndex+1)); } } - else if (DTM.ELEMENT_NODE == type) - { - return getStringValueX(nodeHandle); - } - else if (DTM.DOCUMENT_FRAGMENT_NODE == type + else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type || DTM.DOCUMENT_NODE == type) { return null; diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/transform/DocumentExtFunc.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/transform/DocumentExtFunc.java index afb3e4f0e99..44976edcc1a 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/transform/DocumentExtFunc.java +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/transform/DocumentExtFunc.java @@ -30,6 +30,6 @@ public class DocumentExtFunc { public static String test(NodeList list) { Node node = list.item(0); - return "["+node.getNodeName() + ":" + node.getNodeValue()+"]"; + return "["+node.getNodeName() + ":" + node.getTextContent()+"]"; } } From d78a5bc2c1866096d3889fca91ac94dfb048d9b7 Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Fri, 29 May 2015 12:28:46 +0300 Subject: [PATCH 048/117] 8081392: getNodeValue should return 'null' value for Element nodes Reviewed-by: joehw --- jdk/test/javax/xml/jaxp/common/8032908/TestFunc.java | 5 +++-- jdk/test/javax/xml/jaxp/common/8032908/XSLT.java | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/jdk/test/javax/xml/jaxp/common/8032908/TestFunc.java b/jdk/test/javax/xml/jaxp/common/8032908/TestFunc.java index 20eb23fa513..62a18f77749 100644 --- a/jdk/test/javax/xml/jaxp/common/8032908/TestFunc.java +++ b/jdk/test/javax/xml/jaxp/common/8032908/TestFunc.java @@ -26,8 +26,9 @@ import org.w3c.dom.Node; public class TestFunc { public static String test(Node node) { - String s = node.getTextContent(); - return s; + String textContent = node.getTextContent(); + String nodeValue = node.getNodeValue(); + return textContent + ":" + nodeValue; } } diff --git a/jdk/test/javax/xml/jaxp/common/8032908/XSLT.java b/jdk/test/javax/xml/jaxp/common/8032908/XSLT.java index 77ddcbcfaea..22a4346edae 100644 --- a/jdk/test/javax/xml/jaxp/common/8032908/XSLT.java +++ b/jdk/test/javax/xml/jaxp/common/8032908/XSLT.java @@ -23,9 +23,10 @@ /** * @test - * @bug 8032908 + * @bug 8032908 8081392 * @summary Test if Node.getTextContent() function correctly returns children - * content + * content and also check that Node.getNodeValue() returns null value for + * Element nodes * @compile TestFunc.java XSLT.java * @run main/othervm XSLT */ @@ -40,7 +41,7 @@ public class XSLT { static final String XMLTOTRANSFORM = "/in.xml"; static final String XSLTRANSFORMER = "/test.xsl"; - static final String EXPECTEDRESULT = "ABCDEFG"; + static final String EXPECTEDRESULT = "ABCDEFG:null"; public static void main(String[] args) throws TransformerException { ByteArrayOutputStream resStream = new ByteArrayOutputStream(); From 5fe4d18385a20deffe97faeaa50852cc59f31bb7 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 29 May 2015 09:08:36 -0700 Subject: [PATCH 049/117] 8081452: Move sun.nio.cs.AbstractCharsetProvider into jdk.charset/sun.nio.cs.ext To AbstractCharsetProvider class from base.java module to jdk.charsets module Reviewed-by: alanb --- .../share/classes/sun/nio/cs/ext}/AbstractCharsetProvider.java | 2 +- .../share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) rename jdk/src/{java.base/share/classes/sun/nio/cs => jdk.charsets/share/classes/sun/nio/cs/ext}/AbstractCharsetProvider.java (99%) diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/AbstractCharsetProvider.java b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java similarity index 99% rename from jdk/src/java.base/share/classes/sun/nio/cs/AbstractCharsetProvider.java rename to jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java index e10a9400280..972d6593573 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/AbstractCharsetProvider.java +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java @@ -23,7 +23,7 @@ * questions. */ -package sun.nio.cs; +package sun.nio.cs.ext; import java.lang.ref.SoftReference; import java.nio.charset.Charset; diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template index a25018a1235..19a278f4ba1 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template @@ -35,7 +35,6 @@ import java.nio.charset.spi.CharsetProvider; import sun.nio.cs.AbstractCharsetProvider; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.nio.cs.AbstractCharsetProvider; /** * Provider for extended charsets. From 97f5b473ec0a38eb088cf3c9b825d1137dd14db1 Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Fri, 29 May 2015 19:20:22 +0300 Subject: [PATCH 050/117] 8081027: Create a common test to check adequacy of initial size of static HashMap/ArrayList fields Reviewed-by: martin --- .../share/classes/java/lang/Character.java | 6 +- .../sun/invoke/anon/ConstantPoolPatch.java | 2 +- .../sun/security/ssl/ExtensionType.java | 5 +- .../UnicodeBlock/NonOptimalMapSize.java | 72 ------ .../UnicodeBlock/OptimalMapSize.java | 57 +++++ .../jdk/testlibrary/OptimalCapacity.java | 216 ++++++++++++++++++ .../ConstantPoolPatch/OptimalMapSize.java | 41 ++++ .../ssl/ExtensionType/OptimalListSize.java | 41 ++++ 8 files changed, 361 insertions(+), 79 deletions(-) delete mode 100644 jdk/test/java/lang/Character/UnicodeBlock/NonOptimalMapSize.java create mode 100644 jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java create mode 100644 jdk/test/sun/invoke/anon/ConstantPoolPatch/OptimalMapSize.java create mode 100644 jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java diff --git a/jdk/src/java.base/share/classes/java/lang/Character.java b/jdk/src/java.base/share/classes/java/lang/Character.java index e3d6c38a7c6..cb316f14730 100644 --- a/jdk/src/java.base/share/classes/java/lang/Character.java +++ b/jdk/src/java.base/share/classes/java/lang/Character.java @@ -646,13 +646,11 @@ class Character implements java.io.Serializable, Comparable { */ public static final class UnicodeBlock extends Subset { /** - * 510 - the expected number of enteties + * 510 - the expected number of entities * 0.75 - the default load factor of HashMap */ - private static final int INITIAL_CAPACITY = - (int)(510 / 0.75f + 1.0f); private static Map map = - new HashMap<>(INITIAL_CAPACITY); + new HashMap<>((int)(510 / 0.75f + 1.0f)); /** * Creates a UnicodeBlock with the given identifier name. diff --git a/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java b/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java index d83c2a6d61a..eb4c9b32975 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java +++ b/jdk/src/java.base/share/classes/sun/invoke/anon/ConstantPoolPatch.java @@ -417,7 +417,7 @@ public class ConstantPoolPatch { | CONSTANT_InterfaceMethodref; private static final Map, Byte> CONSTANT_VALUE_CLASS_TAG - = new IdentityHashMap, Byte>(); + = new IdentityHashMap, Byte>(6); private static final Class[] CONSTANT_VALUE_CLASS = new Class[16]; static { Object[][] values = { diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java b/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java index 99de20a6ca5..f53593b570d 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -43,7 +43,8 @@ final class ExtensionType { return name; } - static List knownExtensions = new ArrayList(9); + static List knownExtensions = + new ArrayList(13); static ExtensionType get(int id) { for (ExtensionType ext : knownExtensions) { diff --git a/jdk/test/java/lang/Character/UnicodeBlock/NonOptimalMapSize.java b/jdk/test/java/lang/Character/UnicodeBlock/NonOptimalMapSize.java deleted file mode 100644 index 73688021596..00000000000 --- a/jdk/test/java/lang/Character/UnicodeBlock/NonOptimalMapSize.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 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 8080535 - * @summary Expected size of Character.UnicodeBlock.map is not optimal - */ - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -public class NonOptimalMapSize { - public static void main(String[] args) throws Throwable { - Class ubCls = Character.UnicodeBlock.class; - Field mapField = ubCls.getDeclaredField("map"); - mapField.setAccessible(true); - Map map = (Map)mapField.get(null); - if (!map.getClass().equals(HashMap.class)) { - throw new RuntimeException( - "Character.UnicodeBlock.map is expected to be HashMap"); - } - int mapSize = map.size(); - - Field sizeField = ubCls.getDeclaredField("INITIAL_CAPACITY"); - sizeField.setAccessible(true); - int INITIAL_CAPACITY = sizeField.getInt(null); - - // Construct a HashMap with specified initial capacity - HashMap map1 = new HashMap<>(INITIAL_CAPACITY); - Class hmCls = HashMap.class; - Field tableField = hmCls.getDeclaredField("table"); - tableField.setAccessible(true); - // ... and fill it up - map1.put(new Object(), new Object()); - final Object initialTable = tableField.get(map1); - while (map1.size() < map.size() && - initialTable == tableField.get(map1)) { - map1.put(new Object(), new Object()); - } - - // Now check that internal storage didn't change - if (initialTable != tableField.get(map1)) { - throw new RuntimeException( - "Initial capacity " + INITIAL_CAPACITY + - " was only enough to hold " + (map1.size()-1) + - " entries, but needed " + map.size()); - } - } -} diff --git a/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java b/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java new file mode 100644 index 00000000000..0a4905d6046 --- /dev/null +++ b/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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 8080535 + * @summary Expected size of Character.UnicodeBlock.map is not optimal + * @library /lib/testlibrary + * @build jdk.testlibrary.OptimalCapacity + * @run main OptimalMapSize + */ + +import jdk.testlibrary.OptimalCapacity; + +// What will be the number of the Unicode blocks in the future. +// +// According to http://www.unicode.org/versions/Unicode7.0.0/ , +// in Unicode 7 there will be added 32 new blocks (96 with aliases). +// According to http://www.unicode.org/versions/beta-8.0.0.html , +// in Unicode 8 there will be added 10 more blocks (30 with aliases). +// +// After implementing support of Unicode 7 and 8 in Java, there will +// be 510+96+30 = 636 entries in Character.UnicodeBlock.map. +// +// Initialization of the map and this test will have to be adjusted +// accordingly then. + +public class OptimalMapSize { + public static void main(String[] args) throws Throwable { + // The initial size of Character.UnicodeBlock.map. + // See src/java.base/share/classes/java/lang/Character.java + int initialCapacity = (int)(510 / 0.75f + 1.0f); + + OptimalCapacity.ofHashMap(Character.UnicodeBlock.class, + "map", initialCapacity); + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java new file mode 100644 index 00000000000..2d1ada3842a --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 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. + */ + +package jdk.testlibrary; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; + +/** + * Utility functions to check that the static storages are pre-sized + * optimally. + */ +public final class OptimalCapacity { + + private OptimalCapacity() {} + + /** + * Checks adequacy of the initial capacity of a static field + * of type {@code ArrayList}. + * + * Having + *

    +     * class XClass {
    +     *     static ArrayList theList = new ArrayList(N);
    +     * }
    +     * 
    + * + * you should call from the test + * + *
    +     * OptimalCapacity.assertProperlySized(XClass.class, "theList", N);
    +     * 
    + */ + public static void ofArrayList(Class clazz, String fieldName, + int initialCapacity) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (!ArrayList.class.equals(obj.getClass())) { + throw new RuntimeException("'" + field + + "' expected to be of type ArrayList"); + } + ArrayList list = (ArrayList)obj; + + // For ArrayList the optimal capacity is its final size + if (list.size() != initialCapacity) { + throw new RuntimeException("Size of '" + field + + "' is " + list.size() + + ", but expected to be " + initialCapacity); + } + if (internalArraySize(list) != initialCapacity) { + throw new RuntimeException("Capacity of '" + field + + "' is " + internalArraySize(list) + + ", but expected to be " + initialCapacity); + } + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Checks adequacy of the initial capacity of a static field + * of type {@code HashMap}. + * + * Having + *
    +     * class XClass {
    +     *     static HashMap theMap = new HashMap(N);
    +     * }
    +     * 
    + * + * you should call from the test + * + *
    +     * OptimalCapacity.ofHashMap(XClass.class, "theMap", N);
    +     * 
    + */ + public static void ofHashMap(Class clazz, String fieldName, + int initialCapacity) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (!HashMap.class.equals(obj.getClass())) { + throw new RuntimeException(field + + " expected to be of type HashMap"); + } + HashMap map = (HashMap)obj; + + // Check that the map allocates only necessary amount of space + HashMap tmp = new HashMap<>(map); + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Final capacity of '" + field + + "' is " + internalArraySize(map) + + ", which exceeds necessary minimum " + internalArraySize(tmp)); + } + + // Check that map is initially properly sized + tmp = new HashMap<>(initialCapacity); + tmp.put(new Object(), new Object()); // trigger storage init + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Requested capacity of '" + field + + "' was " + initialCapacity + + ", which resulted in final capacity " + internalArraySize(tmp) + + ", which differs from necessary minimum " + internalArraySize(map)); + } + + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Checks adequacy of the expected maximum size of a static field + * of type {@code IdentityHashMap}. + * + * Having + *
    +     * class XClass {
    +     *     static IdentityHashMap theMap = new IdentityHashMap(M);
    +     * }
    +     * 
    + * + * you should call from the test + * + *
    +     * OptimalCapacity.ofIdentityHashMap(XClass.class, "theMap", M);
    +     * 
    + */ + public static void ofIdentityHashMap(Class clazz, String fieldName, + int expectedMaxSize) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (!IdentityHashMap.class.equals(obj.getClass())) { + throw new RuntimeException("'" + field + + "' expected to be of type IdentityHashMap"); + } + IdentityHashMap map = (IdentityHashMap)obj; + + // Check that size of map is what was expected + if (map.size() != expectedMaxSize) { + throw new RuntimeException("Size of '" + field + + "' is " + map.size() + + ", which differs from expected " + expectedMaxSize); + } + + // Check that the map allocated only necessary amount of memory + IdentityHashMap tmp = new IdentityHashMap<>(map); + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Final capacity of '" + field + + "' is " + internalArraySize(map) + + ", which exceeds necessary minimum " + internalArraySize(tmp)); + } + + // Check that map was initially properly sized + tmp = new IdentityHashMap<>(expectedMaxSize); + tmp.put(new Object(), new Object()); // trigger storage init + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Requested number of elements in '" + field + + "' was " + expectedMaxSize + + ", which resulted in final capacity " + internalArraySize(tmp) + + ", which differs from necessary minimum " + internalArraySize(map)); + } + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Returns size of the internal storage. + */ + private static int internalArraySize(Object container) + throws ReflectiveOperationException { + Field field; + if (ArrayList.class.equals(container.getClass())) { + field = ArrayList.class.getDeclaredField("elementData"); + } else if (HashMap.class.equals(container.getClass())) { + field = HashMap.class.getDeclaredField("table"); + } else if (IdentityHashMap.class.equals(container.getClass())) { + field = IdentityHashMap.class.getDeclaredField("table"); + } else { + throw new RuntimeException("Unexpected class " + + container.getClass()); + } + field.setAccessible(true); + return ((Object[])field.get(container)).length; + } +} diff --git a/jdk/test/sun/invoke/anon/ConstantPoolPatch/OptimalMapSize.java b/jdk/test/sun/invoke/anon/ConstantPoolPatch/OptimalMapSize.java new file mode 100644 index 00000000000..d3895dd9255 --- /dev/null +++ b/jdk/test/sun/invoke/anon/ConstantPoolPatch/OptimalMapSize.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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 8080535 + * @summary Static storages should be initialized with optimal capacity + * @library /lib/testlibrary + * @build jdk.testlibrary.OptimalCapacity + * @run main OptimalMapSize + */ + +import jdk.testlibrary.OptimalCapacity; + +public class OptimalMapSize { + public static void main(String[] args) throws Throwable { + OptimalCapacity.ofIdentityHashMap( + Class.forName("sun.invoke.anon.ConstantPoolPatch"), + "CONSTANT_VALUE_CLASS_TAG", 6); + } +} diff --git a/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java b/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java new file mode 100644 index 00000000000..2b1dff93a88 --- /dev/null +++ b/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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 8080535 + * @summary Expected size of Character.UnicodeBlock.map is not optimal + * @library /lib/testlibrary + * @build jdk.testlibrary.OptimalCapacity + * @run main OptimalListSize + */ + +import jdk.testlibrary.OptimalCapacity; + +public class OptimalListSize { + public static void main(String[] args) throws Throwable { + OptimalCapacity.ofArrayList( + Class.forName("sun.security.ssl.ExtensionType"), + "knownExtensions", 13); + } +} From 5fbfe34bf69a66bb19d671ceaabb8780200bbdb2 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 29 May 2015 10:28:28 -0700 Subject: [PATCH 051/117] 8081522: build failed with jdk8081452 change To remove the missed import line Reviewed-by: alanb --- .../share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template index 19a278f4ba1..f654c778b81 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template @@ -32,7 +32,6 @@ package sun.nio.cs.ext; import java.lang.ref.SoftReference; import java.nio.charset.Charset; import java.nio.charset.spi.CharsetProvider; -import sun.nio.cs.AbstractCharsetProvider; import java.security.AccessController; import java.security.PrivilegedAction; From 103d99baf189ef352b65297cca5576f6da3839bf Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 29 May 2015 14:04:12 -0400 Subject: [PATCH 052/117] 8077350: JEP 102 Process API Updates Implementation Reviewed-by: chegar, plevart, psandoz, darcy, martin, alanb --- jdk/make/mapfiles/libjava/mapfile-vers | 16 +- .../native/libjava/ProcessHandleImpl_macosx.c | 401 +++++++++ .../share/classes/java/lang/Process.java | 379 +++++++-- .../classes/java/lang/ProcessHandle.java | 361 ++++++++ .../classes/java/lang/ProcessHandleImpl.java | 528 ++++++++++++ .../classes/java/lang/RuntimePermission.java | 8 +- .../libjava/ProcessHandleImpl_solaris.c | 371 +++++++++ .../unix/classes/java/lang/ProcessImpl.java | 204 +++-- .../native/libjava/ProcessHandleImpl_unix.c | 769 ++++++++++++++++++ .../unix/native/libjava/ProcessImpl_md.c | 55 -- .../classes/java/lang/ProcessImpl.java | 41 +- .../native/libjava/ProcessHandleImpl_win.c | 426 ++++++++++ jdk/test/TEST.ROOT | 2 +- jdk/test/java/lang/ProcessBuilder/Basic.java | 16 +- jdk/test/java/lang/ProcessHandle/Basic.java | 143 ++++ .../java/lang/ProcessHandle/InfoTest.java | 350 ++++++++ .../java/lang/ProcessHandle/JavaChild.java | 524 ++++++++++++ .../java/lang/ProcessHandle/OnExitTest.java | 193 +++++ .../lang/ProcessHandle/PermissionTest.java | 222 +++++ .../java/lang/ProcessHandle/ProcessUtil.java | 246 ++++++ .../java/lang/ProcessHandle/ScaleTest.java | 126 +++ .../java/lang/ProcessHandle/TEST.properties | 4 + .../java/lang/ProcessHandle/TreeTest.java | 358 ++++++++ 23 files changed, 5508 insertions(+), 235 deletions(-) create mode 100644 jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c create mode 100644 jdk/src/java.base/share/classes/java/lang/ProcessHandle.java create mode 100644 jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java create mode 100644 jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c create mode 100644 jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c create mode 100644 jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c create mode 100644 jdk/test/java/lang/ProcessHandle/Basic.java create mode 100644 jdk/test/java/lang/ProcessHandle/InfoTest.java create mode 100644 jdk/test/java/lang/ProcessHandle/JavaChild.java create mode 100644 jdk/test/java/lang/ProcessHandle/OnExitTest.java create mode 100644 jdk/test/java/lang/ProcessHandle/PermissionTest.java create mode 100644 jdk/test/java/lang/ProcessHandle/ProcessUtil.java create mode 100644 jdk/test/java/lang/ProcessHandle/ScaleTest.java create mode 100644 jdk/test/java/lang/ProcessHandle/TEST.properties create mode 100644 jdk/test/java/lang/ProcessHandle/TreeTest.java diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index df91f947ad8..cc406fa6e7a 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -166,6 +166,16 @@ SUNWprivate_1.1 { Java_java_lang_Package_getSystemPackage0; Java_java_lang_Package_getSystemPackages0; Java_java_lang_ProcessEnvironment_environ; + Java_java_lang_ProcessHandleImpl_getCurrentPid0; + Java_java_lang_ProcessHandleImpl_parent0; + Java_java_lang_ProcessHandleImpl_isAlive0; + Java_java_lang_ProcessHandleImpl_getProcessPids0; + Java_java_lang_ProcessHandleImpl_destroy0; + Java_java_lang_ProcessHandleImpl_waitForProcessExit0; + Java_java_lang_ProcessHandleImpl_00024Info_initIDs; + Java_java_lang_ProcessHandleImpl_00024Info_info0; + Java_java_lang_ProcessImpl_init; + Java_java_lang_ProcessImpl_forkAndExec; Java_java_lang_reflect_Array_get; Java_java_lang_reflect_Array_getBoolean; Java_java_lang_reflect_Array_getByte; @@ -214,10 +224,6 @@ SUNWprivate_1.1 { Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_lang_ProcessImpl_init; - Java_java_lang_ProcessImpl_waitForProcessExit; - Java_java_lang_ProcessImpl_forkAndExec; - Java_java_lang_ProcessImpl_destroyProcess; Java_java_nio_Bits_copyFromShortArray; Java_java_nio_Bits_copyToShortArray; Java_java_nio_Bits_copyFromIntArray; @@ -277,7 +283,7 @@ SUNWprivate_1.1 { Java_jdk_internal_jimage_concurrent_ConcurrentPReader_initIDs; Java_jdk_internal_jimage_concurrent_ConcurrentPReader_pread; - + # ZipFile.c needs this one throwFileNotFoundException; # zip_util.c needs this one diff --git a/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c b/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c new file mode 100644 index 00000000000..b526703df17 --- /dev/null +++ b/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +#include "jni.h" +#include "jni_util.h" +#include "java_lang_ProcessHandleImpl.h" +#include "java_lang_ProcessHandleImpl_Info.h" + +#include +#include +#include +#include +#include +#include + +#include + +/** + * Implementations of ProcessHandleImpl functions for MAC OS X; + * are NOT common to all Unix variants. + */ + +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid); +static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid); + +/* + * Common Unix function to lookup the uid and return the user name. + */ +extern jstring uidToUser(JNIEnv* env, uid_t uid); + +/* Field id for jString 'command' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_commandID; + +/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_argumentsID; + +/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_totalTimeID; + +/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_startTimeID; + +/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_userID; + +/* static value for clock ticks per second. */ +static long clock_ticks_per_second; + +/************************************************************** + * Static method to initialize field IDs and the ticks per second rate. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_initIDs + (JNIEnv *env, jclass clazz) { + + CHECK_NULL(ProcessHandleImpl_Info_commandID = + (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_argumentsID = + (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = + (*env)->GetFieldID(env, clazz, "totalTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_startTimeID = + (*env)->GetFieldID(env, clazz, "startTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_userID = + (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;")); + clock_ticks_per_second = sysconf(_SC_CLK_TCK); +} + +/* + * Returns the parent pid of the requested pid. + * + * Class: java_lang_ProcessHandleImpl + * Method: parent0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_parent0 +(JNIEnv *env, jobject obj, jlong jpid) { + pid_t pid = (pid_t) jpid; + pid_t ppid = -1; + + if (pid == getpid()) { + ppid = getppid(); + } else { + const pid_t pid = (pid_t) jpid; + struct kinfo_proc kp; + size_t bufSize = sizeof kp; + + // Read the process info for the specific pid + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + return -1; + } + ppid = (bufSize > 0 && kp.kp_proc.p_pid == pid) ? kp.kp_eproc.e_ppid : -1; + } + return (jlong) ppid; +} + +/* + * Returns the children of the requested pid and optionally each parent. + * + * Class: java_lang_ProcessHandleImpl + * Method: getProcessPids0 + * Signature: (J[J[J)I + * + * Use sysctl to accumulate any process whose parent pid is zero or matches. + * The resulting pids are stored into the array of longs. + * The number of pids is returned if they all fit. + * If the parentArray is non-null, store the parent pid. + * If the array is too short, excess pids are not stored and + * the desired length is returned. + */ +JNIEXPORT jint JNICALL Java_java_lang_ProcessHandleImpl_getProcessPids0 +(JNIEnv *env, jclass clazz, jlong jpid, + jlongArray jarray, jlongArray jparentArray) +{ + size_t count = 0; + jlong* pids = NULL; + jlong* ppids = NULL; + size_t parentArraySize = 0; + size_t arraySize = 0; + size_t bufSize = 0; + pid_t pid = (pid_t) jpid; + + arraySize = (*env)->GetArrayLength(env, jarray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + if (jparentArray != NULL) { + parentArraySize = (*env)->GetArrayLength(env, jparentArray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + + if (arraySize != parentArraySize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + + // Get buffer size needed to read all processes + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; + if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + return -1; + } + + // Allocate buffer big enough for all processes + void *buffer = malloc(bufSize); + if (buffer == NULL) { + JNU_ThrowOutOfMemoryError(env, "malloc failed"); + return -1; + } + + // Read process info for all processes + if (sysctl(mib, 4, buffer, &bufSize, NULL, 0) < 0) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + free(buffer); + return -1; + } + + do { // Block to break out of on Exception + struct kinfo_proc *kp = (struct kinfo_proc *) buffer; + unsigned long nentries = bufSize / sizeof (struct kinfo_proc); + long i; + + pids = (*env)->GetLongArrayElements(env, jarray, NULL); + if (pids == NULL) { + break; + } + if (jparentArray != NULL) { + ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL); + if (ppids == NULL) { + break; + } + } + + // Process each entry in the buffer + for (i = nentries; --i >= 0; ++kp) { + if (pid == 0 || kp->kp_eproc.e_ppid == pid) { + if (count < arraySize) { + // Only store if it fits + pids[count] = (jlong) kp->kp_proc.p_pid; + if (ppids != NULL) { + // Store the parentPid + ppids[count] = (jlong) kp->kp_eproc.e_ppid; + } + } + count++; // Count to tabulate size needed + } + } + } while (0); + + if (pids != NULL) { + (*env)->ReleaseLongArrayElements(env, jarray, pids, 0); + } + if (ppids != NULL) { + (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0); + } + + free(buffer); + // If more pids than array had size for; count will be greater than array size + return count; +} + +/************************************************************** + * Implementation of ProcessHandleImpl_Info native methods. + */ + +/* + * Fill in the Info object from the OS information about the process. + * + * Class: java_lang_ProcessHandleImpl + * Method: info0 + * Signature: (J)I + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_info0 + (JNIEnv *env, jobject jinfo, jlong jpid) { + pid_t pid = (pid_t) jpid; + getStatInfo(env, jinfo, pid); + getCmdlineInfo(env, jinfo, pid); +} + +/** + * Read /proc//stat and fill in the fields of the Info object. + * The executable name, plus the user, system, and start times are gathered. + */ +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) { + jlong totalTime; // nanoseconds + unsigned long long startTime; // microseconds + + const pid_t pid = (pid_t) jpid; + struct kinfo_proc kp; + size_t bufSize = sizeof kp; + + // Read the process info for the specific pid + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + + if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) { + if (errno == EINVAL) { + return; + } else { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + } + return; + } + + // Convert the UID to the username + jstring name = NULL; + CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid))); + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name); + JNU_CHECK_EXCEPTION(env); + + startTime = kp.kp_proc.p_starttime.tv_sec * 1000 + + kp.kp_proc.p_starttime.tv_usec / 1000; + + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime); + JNU_CHECK_EXCEPTION(env); + + // Get cputime if for current process + if (pid == getpid()) { + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage) != 0) { + return; + } + jlong microsecs = + usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec + + usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec; + totalTime = microsecs * 1000; + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime); + JNU_CHECK_EXCEPTION(env); + } +} + +/** + * Construct the argument array by parsing the arguments from the sequence of arguments. + */ +static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs, + const char *cp, const char *argsEnd) { + jstring str = NULL; + jobject argsArray; + int i; + + if (nargs < 1) { + return 0; + } + // Create a String array for nargs-1 elements + CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env, + nargs - 1, JNU_ClassString(env), NULL)), -1); + + for (i = 0; i < nargs - 1; i++) { + // skip to the next argument; omits arg[0] + cp += strnlen(cp, (argsEnd - cp)) + 1; + + if (cp > argsEnd || *cp == '\0') { + return -2; // Off the end pointer or an empty argument is an error + } + + CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1); + + (*env)->SetObjectArrayElement(env, argsArray, i, str); + JNU_CHECK_EXCEPTION_RETURN(env, -3); + } + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray); + JNU_CHECK_EXCEPTION_RETURN(env, -4); + return 0; +} + +/** + * Retrieve the command and arguments for the process and store them + * into the Info object. + */ +static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) { + int mib[3], maxargs, nargs, i; + size_t size; + char *args, *cp, *sp, *np; + + // Get the maximum size of the arguments + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + size = sizeof(maxargs); + if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + return; + } + + // Allocate an args buffer and get the arguments + args = (char *)malloc(maxargs); + if (args == NULL) { + JNU_ThrowOutOfMemoryError(env, "malloc failed"); + return; + } + + do { // a block to break out of on error + char *argsEnd; + jstring str = NULL; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = pid; + size = (size_t) maxargs; + if (sysctl(mib, 3, args, &size, NULL, 0) == -1) { + if (errno != EINVAL) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "sysctl failed"); + } + break; + } + memcpy(&nargs, args, sizeof(nargs)); + + cp = &args[sizeof(nargs)]; // Strings start after nargs + argsEnd = &args[size]; + + // Store the command executable path + if ((str = JNU_NewStringPlatform(env, cp)) == NULL) { + break; + } + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str); + if ((*env)->ExceptionCheck(env)) { + break; + } + + // Skip trailing nulls after the executable path + for (cp = cp + strnlen(cp, argsEnd - cp); cp < argsEnd; cp++) { + if (*cp != '\0') { + break; + } + } + + fillArgArray(env, jinfo, nargs, cp, argsEnd); + } while (0); + // Free the arg buffer + free(args); +} + diff --git a/jdk/src/java.base/share/classes/java/lang/Process.java b/jdk/src/java.base/share/classes/java/lang/Process.java index b05d19f67a0..7eca3fd4699 100644 --- a/jdk/src/java.base/share/classes/java/lang/Process.java +++ b/jdk/src/java.base/share/classes/java/lang/Process.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -26,25 +26,31 @@ package java.lang; import java.io.*; +import java.lang.ProcessBuilder.Redirect; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; /** + * {@code Process} provides control of native processes started by + * ProcessBuilder.start and Runtime.exec. + * The class provides methods for performing input from the process, performing + * output to the process, waiting for the process to complete, + * checking the exit status of the process, and destroying (killing) + * the process. * The {@link ProcessBuilder#start()} and * {@link Runtime#exec(String[],String[],File) Runtime.exec} * methods create a native process and return an instance of a * subclass of {@code Process} that can be used to control the process - * and obtain information about it. The class {@code Process} - * provides methods for performing input from the process, performing - * output to the process, waiting for the process to complete, - * checking the exit status of the process, and destroying (killing) - * the process. + * and obtain information about it. * *

    The methods that create processes may not work well for special * processes on certain native platforms, such as native windowing * processes, daemon processes, Win16/DOS processes on Microsoft * Windows, or shell scripts. * - *

    By default, the created subprocess does not have its own terminal + *

    By default, the created process does not have its own terminal * or console. All its standard I/O (i.e. stdin, stdout, stderr) * operations will be redirected to the parent process, where they can * be accessed via the streams obtained using the methods @@ -52,35 +58,49 @@ import java.util.concurrent.TimeUnit; * {@link #getInputStream()}, and * {@link #getErrorStream()}. * The parent process uses these streams to feed input to and get output - * from the subprocess. Because some native platforms only provide + * from the process. Because some native platforms only provide * limited buffer size for standard input and output streams, failure * to promptly write the input stream or read the output stream of - * the subprocess may cause the subprocess to block, or even deadlock. + * the process may cause the process to block, or even deadlock. * *

    Where desired, - * subprocess I/O can also be redirected + * process I/O can also be redirected * using methods of the {@link ProcessBuilder} class. * - *

    The subprocess is not killed when there are no more references to - * the {@code Process} object, but rather the subprocess + *

    The process is not killed when there are no more references to + * the {@code Process} object, but rather the process * continues executing asynchronously. * - *

    There is no requirement that a process represented by a {@code + *

    There is no requirement that the process represented by a {@code * Process} object execute asynchronously or concurrently with respect * to the Java process that owns the {@code Process} object. * *

    As of 1.5, {@link ProcessBuilder#start()} is the preferred way * to create a {@code Process}. * + *

    Subclasses of Process should override the {@link #onExit()} and + * {@link #toHandle()} methods to provide a fully functional Process including the + * {@link #getPid() process id}, + * {@link #info() information about the process}, + * {@link #children() direct children}, and + * {@link #allChildren() direct and indirect children} of the process. + * Delegating to the underlying Process or ProcessHandle is typically + * easiest and most efficient. + * * @since 1.0 */ public abstract class Process { + /** + * Default constructor for Process. + */ + public Process() {} + /** * Returns the output stream connected to the normal input of the - * subprocess. Output to the stream is piped into the standard + * process. Output to the stream is piped into the standard * input of the process represented by this {@code Process} object. * - *

    If the standard input of the subprocess has been redirected using + *

    If the standard input of the process has been redirected using * {@link ProcessBuilder#redirectInput(Redirect) * ProcessBuilder.redirectInput} * then this method will return a @@ -90,42 +110,42 @@ public abstract class Process { * output stream to be buffered. * * @return the output stream connected to the normal input of the - * subprocess + * process */ public abstract OutputStream getOutputStream(); /** * Returns the input stream connected to the normal output of the - * subprocess. The stream obtains data piped from the standard + * process. The stream obtains data piped from the standard * output of the process represented by this {@code Process} object. * - *

    If the standard output of the subprocess has been redirected using + *

    If the standard output of the process has been redirected using * {@link ProcessBuilder#redirectOutput(Redirect) * ProcessBuilder.redirectOutput} * then this method will return a * null input stream. * - *

    Otherwise, if the standard error of the subprocess has been + *

    Otherwise, if the standard error of the process has been * redirected using * {@link ProcessBuilder#redirectErrorStream(boolean) * ProcessBuilder.redirectErrorStream} * then the input stream returned by this method will receive the - * merged standard output and the standard error of the subprocess. + * merged standard output and the standard error of the process. * *

    Implementation note: It is a good idea for the returned * input stream to be buffered. * * @return the input stream connected to the normal output of the - * subprocess + * process */ public abstract InputStream getInputStream(); /** * Returns the input stream connected to the error output of the - * subprocess. The stream obtains data piped from the error output + * process. The stream obtains data piped from the error output * of the process represented by this {@code Process} object. * - *

    If the standard error of the subprocess has been redirected using + *

    If the standard error of the process has been redirected using * {@link ProcessBuilder#redirectError(Redirect) * ProcessBuilder.redirectError} or * {@link ProcessBuilder#redirectErrorStream(boolean) @@ -137,19 +157,19 @@ public abstract class Process { * input stream to be buffered. * * @return the input stream connected to the error output of - * the subprocess + * the process */ public abstract InputStream getErrorStream(); /** * Causes the current thread to wait, if necessary, until the * process represented by this {@code Process} object has - * terminated. This method returns immediately if the subprocess - * has already terminated. If the subprocess has not yet + * terminated. This method returns immediately if the process + * has already terminated. If the process has not yet * terminated, the calling thread will be blocked until the - * subprocess exits. + * process exits. * - * @return the exit value of the subprocess represented by this + * @return the exit value of the process represented by this * {@code Process} object. By convention, the value * {@code 0} indicates normal termination. * @throws InterruptedException if the current thread is @@ -161,10 +181,10 @@ public abstract class Process { /** * Causes the current thread to wait, if necessary, until the - * subprocess represented by this {@code Process} object has + * process represented by this {@code Process} object has * terminated, or the specified waiting time elapses. * - *

    If the subprocess has already terminated then this method returns + *

    If the process has already terminated then this method returns * immediately with the value {@code true}. If the process has not * terminated and the timeout value is less than, or equal to, zero, then * this method returns immediately with the value {@code false}. @@ -176,8 +196,8 @@ public abstract class Process { * * @param timeout the maximum time to wait * @param unit the time unit of the {@code timeout} argument - * @return {@code true} if the subprocess has exited and {@code false} if - * the waiting time elapsed before the subprocess has exited. + * @return {@code true} if the process has exited and {@code false} if + * the waiting time elapsed before the process has exited. * @throws InterruptedException if the current thread is interrupted * while waiting. * @throws NullPointerException if unit is null @@ -204,41 +224,60 @@ public abstract class Process { } /** - * Returns the exit value for the subprocess. + * Returns the exit value for the process. * - * @return the exit value of the subprocess represented by this + * @return the exit value of the process represented by this * {@code Process} object. By convention, the value * {@code 0} indicates normal termination. - * @throws IllegalThreadStateException if the subprocess represented + * @throws IllegalThreadStateException if the process represented * by this {@code Process} object has not yet terminated */ public abstract int exitValue(); /** - * Kills the subprocess. Whether the subprocess represented by this - * {@code Process} object is forcibly terminated or not is + * Kills the process. + * Whether the process represented by this {@code Process} object is + * {@link #supportsNormalTermination normally terminated} or not is * implementation dependent. + * Forcible process destruction is defined as the immediate termination of a + * process, whereas normal termination allows the process to shut down cleanly. + * If the process is not alive, no action is taken. + *

    + * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is + * {@link java.util.concurrent.CompletableFuture#complete completed} + * when the process has terminated. */ public abstract void destroy(); /** - * Kills the subprocess. The subprocess represented by this + * Kills the process forcibly. The process represented by this * {@code Process} object is forcibly terminated. + * Forcible process destruction is defined as the immediate termination of a + * process, whereas normal termination allows the process to shut down cleanly. + * If the process is not alive, no action is taken. + *

    + * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is + * {@link java.util.concurrent.CompletableFuture#complete completed} + * when the process has terminated. + *

    + * Invoking this method on {@code Process} objects returned by + * {@link ProcessBuilder#start} and {@link Runtime#exec} forcibly terminate + * the process. * - *

    The default implementation of this method invokes {@link #destroy} - * and so may not forcibly terminate the process. Concrete implementations - * of this class are strongly encouraged to override this method with a - * compliant implementation. Invoking this method on {@code Process} - * objects returned by {@link ProcessBuilder#start} and - * {@link Runtime#exec} will forcibly terminate the process. - * - *

    Note: The subprocess may not terminate immediately. + * @implSpec + * The default implementation of this method invokes {@link #destroy} + * and so may not forcibly terminate the process. + * @implNote + * Concrete implementations of this class are strongly encouraged to override + * this method with a compliant implementation. + * @apiNote + * The process may not terminate immediately. * i.e. {@code isAlive()} may return true for a brief period * after {@code destroyForcibly()} is called. This method * may be chained to {@code waitFor()} if needed. * * @return the {@code Process} object representing the - * subprocess to be forcibly destroyed. + * process forcibly destroyed * @since 1.8 */ public Process destroyForcibly() { @@ -247,10 +286,36 @@ public abstract class Process { } /** - * Tests whether the subprocess represented by this {@code Process} is + * Returns {@code true} if the implementation of {@link #destroy} is to + * normally terminate the process, + * Returns {@code false} if the implementation of {@code destroy} + * forcibly and immediately terminates the process. + *

    + * Invoking this method on {@code Process} objects returned by + * {@link ProcessBuilder#start} and {@link Runtime#exec} return + * {@code true} or {@code false} depending on the platform implementation. + * + * @implSpec + * This implementation throws an instance of + * {@link java.lang.UnsupportedOperationException} and performs no other action. + * + * @return {@code true} if the implementation of {@link #destroy} is to + * normally terminate the process; + * otherwise, {@link #destroy} forcibly terminates the process + * @throws UnsupportedOperationException if the Process implementation + * does not support this operation + * @since 1.9 + */ + public boolean supportsNormalTermination() { + throw new UnsupportedOperationException(this.getClass() + + ".supportsNormalTermination() not supported" ); + } + + /** + * Tests whether the process represented by this {@code Process} is * alive. * - * @return {@code true} if the subprocess represented by this + * @return {@code true} if the process represented by this * {@code Process} object has not yet terminated. * @since 1.8 */ @@ -264,16 +329,222 @@ public abstract class Process { } /** - * Returns the native process id of the subprocess. - * The native process id is an identification number that the operating + * Returns the native process ID of the process. + * The native process ID is an identification number that the operating * system assigns to the process. * - * @return the native process id of the subprocess + * @implSpec + * The implementation of this method returns the process id as: + * {@link #toHandle toHandle().getPid()}. + * + * @return the native process id of the process * @throws UnsupportedOperationException if the Process implementation - * does not support this operation + * does not support this operation * @since 1.9 */ public long getPid() { - throw new UnsupportedOperationException(); + return toHandle().getPid(); } + + /** + * Returns a {@code CompletableFuture} for the termination of the Process. + * The {@link java.util.concurrent.CompletableFuture} provides the ability + * to trigger dependent functions or actions that may be run synchronously + * or asynchronously upon process termination. + * When the process terminates the CompletableFuture is + * {@link java.util.concurrent.CompletableFuture#complete completed} regardless + * of the exit status of the process. + *

    + * Calling {@code onExit().get()} waits for the process to terminate and returns + * the Process. The future can be used to check if the process is + * {@link java.util.concurrent.CompletableFuture#isDone done} or to + * {@link java.util.concurrent.CompletableFuture#get() wait} for it to terminate. + * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling} + * the CompletableFuture does not affect the Process. + *

    + * If the process is {@link #isAlive not alive} the {@link CompletableFuture} + * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. + *

    + * Processes returned from {@link ProcessBuilder#start} override the + * default implementation to provide an efficient mechanism to wait + * for process exit. + *

    + * @apiNote + * Using {@link #onExit() onExit} is an alternative to + * {@link #waitFor() waitFor} that enables both additional concurrency + * and convenient access to the result of the Process. + * Lambda expressions can be used to evaluate the result of the Process + * execution. + * If there is other processing to be done before the value is used + * then {@linkplain #onExit onExit} is a convenient mechanism to + * free the current thread and block only if and when the value is needed. + *
    + * For example, launching a process to compare two files and get a boolean if they are identical: + *

     {@code   Process p = new ProcessBuilder("cmp", "f1", "f2").start();
    +     *    Future identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
    +     *    ...
    +     *    if (identical.get()) { ... }
    +     * }
    + * + * @implSpec + * This implementation executes {@link #waitFor()} in a separate thread + * repeatedly until it returns successfully. If the execution of + * {@code waitFor} is interrupted, the thread's interrupt status is preserved. + *

    + * When {@link #waitFor()} returns successfully the CompletableFuture is + * {@link java.util.concurrent.CompletableFuture#complete completed} regardless + * of the exit status of the process. + * + * This implementation may consume a lot of memory for thread stacks if a + * large number of processes are waited for concurrently. + *

    + * External implementations should override this method and provide + * a more efficient implementation. For example, to delegate to the underlying + * process, it can do the following: + *

    {@code
    +     *    public CompletableFuture onExit() {
    +     *       return delegate.onExit().thenApply(p -> this);
    +     *    }
    +     * }
    + * + * @return a new {@code CompletableFuture} for the Process + * + * @since 1.9 + */ + public CompletableFuture onExit() { + return CompletableFuture.supplyAsync(this::waitForInternal); + } + + /** + * Wait for the process to exit by calling {@code waitFor}. + * If the thread is interrupted, remember the interrupted state to + * be restored before returning. Use ForkJoinPool.ManagedBlocker + * so that the number of workers in case ForkJoinPool is used is + * compensated when the thread blocks in waitFor(). + * + * @return the Process + */ + private Process waitForInternal() { + boolean interrupted = false; + while (true) { + try { + ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() { + @Override + public boolean block() throws InterruptedException { + waitFor(); + return true; + } + + @Override + public boolean isReleasable() { + return !isAlive(); + } + }); + break; + } catch (InterruptedException x) { + interrupted = true; + } + } + if (interrupted) { + Thread.currentThread().interrupt(); + } + return this; + } + + /** + * Returns a ProcessHandle for the Process. + * + * {@code Process} objects returned by {@link ProcessBuilder#start} and + * {@link Runtime#exec} implement {@code toHandle} as the equivalent of + * {@link ProcessHandle#of(long) ProcessHandle.of(pid)} including the + * check for a SecurityManager and {@code RuntimePermission("manageProcess")}. + * + * @implSpec + * This implementation throws an instance of + * {@link java.lang.UnsupportedOperationException} and performs no other action. + * Subclasses should override this method to provide a ProcessHandle for the + * process. The methods {@link #getPid}, {@link #info}, {@link #children}, + * and {@link #allChildren}, unless overridden, operate on the ProcessHandle. + * + * @return Returns a ProcessHandle for the Process + * @throws UnsupportedOperationException if the Process implementation + * does not support this operation + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @since 1.9 + */ + public ProcessHandle toHandle() { + throw new UnsupportedOperationException(this.getClass() + + ".toHandle() not supported"); + } + + /** + * Returns a snapshot of information about the process. + * + *

    An {@link ProcessHandle.Info} instance has various accessor methods + * that return information about the process, if the process is alive and + * the information is available, otherwise {@code null} is returned. + * + * @implSpec + * This implementation returns information about the process as: + * {@link #toHandle toHandle().info()}. + * + * @return a snapshot of information about the process, always non-null + * @throws UnsupportedOperationException if the Process implementation + * does not support this operation + * @since 1.9 + */ + public ProcessHandle.Info info() { + return toHandle().info(); + } + + /** + * Returns a snapshot of the direct children of the process. + * A process that is {@link #isAlive not alive} has zero children. + *

    + * Note that processes are created and terminate asynchronously. + * There is no guarantee that a process is {@link #isAlive alive}. + * + * + * @implSpec + * This implementation returns the direct children as: + * {@link #toHandle toHandle().children()}. + * + * @return a Stream of ProcessHandles for processes that are direct children + * of the process + * @throws UnsupportedOperationException if the Process implementation + * does not support this operation + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @since 1.9 + */ + public Stream children() { + return toHandle().children(); + } + + /** + * Returns a snapshot of the direct and indirect children of the process. + * A process that is {@link #isAlive not alive} has zero children. + *

    + * Note that processes are created and terminate asynchronously. + * There is no guarantee that a process is {@link #isAlive alive}. + * + * + * @implSpec + * This implementation returns all children as: + * {@link #toHandle toHandle().allChildren()}. + * + * @return a Stream of ProcessHandles for processes that are direct and + * indirect children of the process + * @throws UnsupportedOperationException if the Process implementation + * does not support this operation + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @since 1.9 + */ + public Stream allChildren() { + return toHandle().allChildren(); + } + + } diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java new file mode 100644 index 00000000000..f16fbee20b9 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package java.lang; + +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +/** + * ProcessHandle identifies and provides control of native processes. Each + * individual process can be monitored for liveness, list its children, + * get information about the process or destroy it. + * By comparison, {@link java.lang.Process Process} instances were started + * by the current process and additionally provide access to the process + * input, output, and error streams. + *

    + * The native process ID is an identification number that the + * operating system assigns to the process. + * The range for process id values is dependent on the operating system. + * For example, an embedded system might use a 16-bit value. + * Status information about a process is retrieved from the native system + * and may change asynchronously; processes may be created or terminate + * spontaneously. + * The time between when a process terminates and the process id + * is reused for a new process is unpredictable. + * Race conditions can exist between checking the status of a process and + * acting upon it. When using ProcessHandles avoid assumptions + * about the liveness or identity of the underlying process. + *

    + * Each ProcessHandle identifies and allows control of a process in the native + * system. ProcessHandles are returned from the factory methods {@link #current()}, + * {@link #of(long)}, + * {@link #children}, {@link #allChildren}, {@link #parent()} and + * {@link #allProcesses()}. + *

    + * The {@link Process} instances created by {@link ProcessBuilder} can be queried + * for a ProcessHandle that provides information about the Process. + * ProcessHandle references should not be freely distributed. + * + *

    + * A {@link java.util.concurrent.CompletableFuture} available from {@link #onExit} + * can be used to wait for process termination, and possibly trigger dependent + * actions. + *

    + * The factory methods limit access to ProcessHandles using the + * SecurityManager checking the {@link RuntimePermission RuntimePermission("manageProcess")}. + * The ability to control processes is also restricted by the native system, + * ProcessHandle provides no more access to, or control over, the native process + * than would be allowed by a native application. + *

    + * @implSpec + * In the case where ProcessHandles cannot be supported then the factory + * methods must consistently throw {@link java.lang.UnsupportedOperationException}. + * The methods of this class throw {@link java.lang.UnsupportedOperationException} + * if the operating system does not allow access to query or kill a process. + * + * @see Process + * @since 1.9 + */ +public interface ProcessHandle extends Comparable { + + /** + * Returns the native process ID of the process. The native process ID is an + * identification number that the operating system assigns to the process. + * + * @return the native process ID of the process + * @throws UnsupportedOperationException if the implementation + * does not support this operation + */ + long getPid(); + + /** + * Returns an {@code Optional} for an existing native process. + * + * @param pid a native process ID + * @return an {@code Optional} of the PID for the process; + * the {@code Optional} is empty if the process does not exist + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @throws UnsupportedOperationException if the implementation + * does not support this operation + */ + public static Optional of(long pid) { + return ProcessHandleImpl.get(pid); + } + + /** + * Returns a ProcessHandle for the current process. The ProcessHandle cannot be + * used to destroy the current process, use {@link System#exit System.exit} instead. + * + * @return a ProcessHandle for the current process + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @throws UnsupportedOperationException if the implementation + * does not support this operation + */ + public static ProcessHandle current() { + return ProcessHandleImpl.current(); + } + + /** + * Returns an {@code Optional} for the parent process. + * Note that Processes in a zombie state usually don't have a parent. + * + * @return an {@code Optional} of the parent process; + * the {@code Optional} is empty if the child process does not have a parent + * or if the parent is not available, possibly due to operating system limitations + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + */ + Optional parent(); + + /** + * Returns a snapshot of the current direct children of the process. + * A process that is {@link #isAlive not alive} has zero children. + *

    + * Note that processes are created and terminate asynchronously. + * There is no guarantee that a process is {@link #isAlive alive}. + * + * + * @return a Stream of ProcessHandles for processes that are direct children + * of the process + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + */ + Stream children(); + + /** + * Returns a snapshot of the current direct and indirect children of the process. + * A process that is {@link #isAlive not alive} has zero children. + *

    + * Note that processes are created and terminate asynchronously. + * There is no guarantee that a process is {@link #isAlive alive}. + * + * + * @return a Stream of ProcessHandles for processes that are direct and + * indirect children of the process + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + */ + Stream allChildren(); + + /** + * Returns a snapshot of all processes visible to the current process. + *

    + * Note that processes are created and terminate asynchronously. There + * is no guarantee that a process in the stream is alive or that no other + * processes may have been created since the inception of the snapshot. + * + * + * @return a Stream of ProcessHandles for all processes + * @throws SecurityException if a security manager has been installed and + * it denies RuntimePermission("manageProcess") + * @throws UnsupportedOperationException if the implementation + * does not support this operation + */ + static Stream allProcesses() { + return ProcessHandleImpl.children(0); + } + + /** + * Returns a snapshot of information about the process. + * + *

    An {@code Info} instance has various accessor methods that return + * information about the process, if the process is alive and the + * information is available. + * + * @return a snapshot of information about the process, always non-null + */ + Info info(); + + /** + * Information snapshot about the process. + * The attributes of a process vary by operating system and are not available + * in all implementations. Information about processes is limited + * by the operating system privileges of the process making the request. + * The return types are {@code Optional} allowing explicit tests + * and actions if the value is available. + * @since 1.9 + */ + public interface Info { + /** + * Returns the executable pathname of the process. + * + * @return an {@code Optional} of the executable pathname + * of the process + */ + public Optional command(); + + /** + * Returns an array of Strings of the arguments of the process. + * + * @return an {@code Optional} of the arguments of the process + */ + public Optional arguments(); + + /** + * Returns the start time of the process. + * + * @return an {@code Optional} of the start time of the process + */ + public Optional startInstant(); + + /** + * Returns the total cputime accumulated of the process. + * + * @return an {@code Optional} for the accumulated total cputime + */ + public Optional totalCpuDuration(); + + /** + * Return the user of the process. + * + * @return an {@code Optional} for the user of the process + */ + public Optional user(); + } + + /** + * Returns a {@code CompletableFuture} for the termination + * of the process. + * The {@link java.util.concurrent.CompletableFuture} provides the ability + * to trigger dependent functions or actions that may be run synchronously + * or asynchronously upon process termination. + * When the process terminates the CompletableFuture is + * {@link java.util.concurrent.CompletableFuture#complete completed} regardless + * of the exit status of the process. + * The {@code onExit} method can be called multiple times to invoke + * independent actions when the process exits. + *

    + * Calling {@code onExit().get()} waits for the process to terminate and returns + * the ProcessHandle. The future can be used to check if the process is + * {@link java.util.concurrent.CompletableFuture#isDone done} or to + * {@link java.util.concurrent.Future#get() wait} for it to terminate. + * {@link java.util.concurrent.Future#cancel(boolean) Cancelling} + * the CompleteableFuture does not affect the Process. + *

    + * If the process is {@link #isAlive not alive} the {@link CompletableFuture} + * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. + * + * @return a new {@code CompletableFuture} for the ProcessHandle + * + * @throws IllegalStateException if the process is the current process + */ + CompletableFuture onExit(); + + /** + * Returns {@code true} if the implementation of {@link #destroy} + * normally terminates the process. + * Returns {@code false} if the implementation of {@code destroy} + * forcibly and immediately terminates the process. + * + * @return {@code true} if the implementation of {@link #destroy} + * normally terminates the process; + * otherwise, {@link #destroy} forcibly terminates the process + */ + boolean supportsNormalTermination(); + + /** + * Requests the process to be killed. + * Whether the process represented by this {@code ProcessHandle} object is + * {@link #supportsNormalTermination normally terminated} or not is + * implementation dependent. + * Forcible process destruction is defined as the immediate termination of the + * process, whereas normal termination allows the process to shut down cleanly. + * If the process is not alive, no action is taken. + * The operating system access controls may prevent the process + * from being killed. + *

    + * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is + * {@link java.util.concurrent.CompletableFuture#complete completed} + * when the process has terminated. + *

    + * Note: The process may not terminate immediately. + * For example, {@code isAlive()} may return true for a brief period + * after {@code destroy()} is called. + * + * @return {@code true} if termination was successfully requested, + * otherwise {@code false} + * @throws IllegalStateException if the process is the current process + */ + boolean destroy(); + + /** + * Requests the process to be killed forcibly. + * The process represented by this {@code ProcessHandle} object is + * forcibly terminated. + * Forcible process destruction is defined as the immediate termination of the + * process, whereas normal termination allows the process to shut down cleanly. + * If the process is not alive, no action is taken. + * The operating system access controls may prevent the process + * from being killed. + *

    + * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is + * {@link java.util.concurrent.CompletableFuture#complete completed} + * when the process has terminated. + *

    + * Note: The process may not terminate immediately. + * For example, {@code isAlive()} may return true for a brief period + * after {@code destroyForcibly()} is called. + * + * @return {@code true} if termination was successfully requested, + * otherwise {@code false} + * @throws IllegalStateException if the process is the current process + */ + boolean destroyForcibly(); + + /** + * Tests whether the process represented by this {@code ProcessHandle} is alive. + * Process termination is implementation and operating system specific. + * The process is considered alive as long as the PID is valid. + * + * @return {@code true} if the process represented by this + * {@code ProcessHandle} object has not yet terminated + */ + boolean isAlive(); + + /** + * Compares this ProcessHandle with the specified ProcessHandle for order. + * The order is not specified, but is consistent with {@link Object#equals}, + * which returns {@code true} if and only if two instances of ProcessHandle + * are of the same implementation and represent the same system process. + * Comparison is only supported among objects of same implementation. + * If attempt is made to mutually compare two different implementations + * of {@link ProcessHandle}s, {@link ClassCastException} is thrown. + * + * @param other the ProcessHandle to be compared + * @return a negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + * @throws NullPointerException if the specified object is null + * @throws ClassCastException if the specified object is not of same class + * as this object + */ + @Override + int compareTo(ProcessHandle other); + +} diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java new file mode 100644 index 00000000000..78f22af691a --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package java.lang; + +import java.security.PrivilegedAction; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import sun.misc.InnocuousThread; + +import static java.security.AccessController.doPrivileged; + +/** + * ProcessHandleImpl is the implementation of ProcessHandle. + * + * @see Process + * @since 1.9 + */ +final class ProcessHandleImpl implements ProcessHandle { + + /** + * The thread pool of "process reaper" daemon threads. + */ + private static final Executor processReaperExecutor = + doPrivileged((PrivilegedAction) () -> { + + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + while (tg.getParent() != null) tg = tg.getParent(); + ThreadGroup systemThreadGroup = tg; + + ThreadFactory threadFactory = grimReaper -> { + // Our thread stack requirement is quite modest. + Thread t = new Thread(systemThreadGroup, grimReaper, + "process reaper", 32768); + t.setDaemon(true); + // A small attempt (probably futile) to avoid priority inversion + t.setPriority(Thread.MAX_PRIORITY); + return t; + }; + + return Executors.newCachedThreadPool(threadFactory); + }); + + private static class ExitCompletion extends CompletableFuture { + final boolean isReaping; + + ExitCompletion(boolean isReaping) { + this.isReaping = isReaping; + } + } + + private static final ConcurrentMap + completions = new ConcurrentHashMap<>(); + + /** + * Returns a CompletableFuture that completes with process exit status when + * the process completes. + * + * @param shouldReap true if the exit value should be reaped + */ + static CompletableFuture completion(long pid, boolean shouldReap) { + // check canonicalizing cache 1st + ExitCompletion completion = completions.get(pid); + // re-try until we get a completion that shouldReap => isReaping + while (completion == null || (shouldReap && !completion.isReaping)) { + ExitCompletion newCompletion = new ExitCompletion(shouldReap); + if (completion == null) { + completion = completions.putIfAbsent(pid, newCompletion); + } else { + completion = completions.replace(pid, completion, newCompletion) + ? null : completions.get(pid); + } + if (completion == null) { + // newCompletion has just been installed successfully + completion = newCompletion; + // spawn a thread to wait for and deliver the exit value + processReaperExecutor.execute(() -> { + int exitValue = waitForProcessExit0(pid, shouldReap); + newCompletion.complete(exitValue); + // remove from cache afterwards + completions.remove(pid, newCompletion); + }); + } + } + return completion; + } + + @Override + public CompletableFuture onExit() { + if (this.equals(current)) { + throw new IllegalStateException("onExit for current process not allowed"); + } + + return ProcessHandleImpl.completion(getPid(), false) + .handleAsync((exitStatus, unusedThrowable) -> this); + } + + /** + * Wait for the process to exit, return the value. + * Conditionally reap the value if requested + * @param pid the processId + * @param reapvalue if true, the value is retrieved, + * else return the value and leave the process waitable + * + * @return the value or -1 if an error occurs + */ + private static native int waitForProcessExit0(long pid, boolean reapvalue); + + /** + * Cache the ProcessHandle of this process. + */ + private static final ProcessHandleImpl current = + new ProcessHandleImpl(getCurrentPid0()); + + /** + * The pid of this ProcessHandle. + */ + private final long pid; + + /** + * Private constructor. Instances are created by the {@code get(long)} factory. + * @param pid the pid for this instance + */ + private ProcessHandleImpl(long pid) { + this.pid = pid; + } + + /** + * Returns a ProcessHandle for an existing native process. + * + * @param pid the native process identifier + * @return The ProcessHandle for the pid if the process is alive; + * or {@code null} if the process ID does not exist in the native system. + * @throws SecurityException if RuntimePermission("manageProcess") is not granted + */ + static Optional get(long pid) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + return Optional.ofNullable(isAlive0(pid) ? new ProcessHandleImpl(pid) : null); + } + + /** + * Returns a ProcessHandle corresponding known to exist pid. + * Called from ProcessImpl, it does not perform a security check or check if the process is alive. + * @param pid of the known to exist process + * @return a ProcessHandle corresponding to an existing Process instance + */ + static ProcessHandle getUnchecked(long pid) { + return new ProcessHandleImpl(pid); + } + + /** + * Returns the native process ID. + * A {@code long} is used to be able to fit the system specific binary values + * for the process. + * + * @return the native process ID + */ + @Override + public long getPid() { + return pid; + } + + /** + * Returns the ProcessHandle for the current native process. + * + * @return The ProcessHandle for the OS process. + * @throws SecurityException if RuntimePermission("manageProcess") is not granted + */ + public static ProcessHandleImpl current() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + return current; + } + + /** + * Return the pid of the current process. + * + * @return the pid of the current process + */ + private static native long getCurrentPid0(); + + /** + * Returns a ProcessHandle for the parent process. + * + * @return a ProcessHandle of the parent process; {@code null} is returned + * if the child process does not have a parent + * @throws SecurityException if permission is not granted by the + * security policy + */ + static Optional parent(long pid) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + long ppid = parent0(pid); + if (ppid <= 0) { + return Optional.empty(); + } + return get(ppid); + } + + /** + * Returns the parent of the native pid argument. + * + * @return the parent of the native pid; if any, otherwise -1 + */ + private static native long parent0(long pid); + + /** + * Returns the number of pids filled in to the array. + * @param pid if {@code pid} equals zero, then all known processes are returned; + * otherwise only direct child process pids are returned + * @param pids an allocated long array to receive the pids + * @param ppids an allocated long array to receive the parent pids; may be null + * @return if greater than or equals to zero is the number of pids in the array; + * if greater than the length of the arrays, the arrays are too small + */ + private static native int getProcessPids0(long pid, long[] pids, long[] ppids); + + /** + * Destroy the process for this ProcessHandle. + * @param pid the processs ID to destroy + * @param force {@code true} if the process should be terminated forcibly; + * else {@code false} for a normal termination + */ + static void destroyProcess(long pid, boolean force) { + destroy0(pid, force); + } + + private static native boolean destroy0(long pid, boolean forcibly); + + @Override + public boolean destroy() { + if (this.equals(current)) { + throw new IllegalStateException("destroy of current process not allowed"); + } + return destroy0(getPid(), false); + } + + @Override + public boolean destroyForcibly() { + if (this.equals(current)) { + throw new IllegalStateException("destroy of current process not allowed"); + } + return destroy0(getPid(), true); + } + + + @Override + public boolean supportsNormalTermination() { + return ProcessImpl.SUPPORTS_NORMAL_TERMINATION; + } + + /** + * Tests whether the process represented by this {@code ProcessHandle} is alive. + * + * @return {@code true} if the process represented by this + * {@code ProcessHandle} object has not yet terminated. + * @since 1.9 + */ + @Override + public boolean isAlive() { + return isAlive0(pid); + } + + /** + * Returns true or false depending on whether the pid is alive. + * This must not reap the exitValue like the isAlive method above. + * + * @param pid the pid to check + * @return true or false + */ + private static native boolean isAlive0(long pid); + + @Override + public Optional parent() { + return parent(pid); + } + + @Override + public Stream children() { + return children(pid); + } + + /** + * Returns a Stream of the children of a process or all processes. + * + * @param pid the pid of the process for which to find the children; + * 0 for all processes + * @return a stream of ProcessHandles + */ + static Stream children(long pid) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + int size = 100; + long[] childpids = null; + while (childpids == null || size > childpids.length) { + childpids = new long[size]; + size = getProcessPids0(pid, childpids, null); + } + return Arrays.stream(childpids, 0, size).mapToObj((id) -> new ProcessHandleImpl(id)); + } + + @Override + public Stream allChildren() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + int size = 100; + long[] pids = null; + long[] ppids = null; + while (pids == null || size > pids.length) { + pids = new long[size]; + ppids = new long[size]; + size = getProcessPids0(0, pids, ppids); + } + + int next = 0; // index of next process to check + int count = -1; // count of subprocesses scanned + long ppid = pid; // start looking for this parent + do { + // Scan from next to size looking for ppid + // if found, exchange it to index next + for (int i = next; i < size; i++) { + if (ppids[i] == ppid) { + swap(pids, i, next); + swap(ppids, i, next); + next++; + } + } + ppid = pids[++count]; // pick up the next pid to scan for + } while (count < next); + + return Arrays.stream(pids, 0, count).mapToObj((id) -> new ProcessHandleImpl(id)); + } + + // Swap two elements in an array + private static void swap(long[] array, int x, int y) { + long v = array[x]; + array[x] = array[y]; + array[y] = v; + } + + @Override + public ProcessHandle.Info info() { + return ProcessHandleImpl.Info.info(pid); + } + + @Override + public int compareTo(ProcessHandle other) { + return Long.compare(pid, ((ProcessHandleImpl) other).pid); + } + + @Override + public String toString() { + return Long.toString(pid); + } + + @Override + public int hashCode() { + return Long.hashCode(pid); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof ProcessHandleImpl) && + (pid == ((ProcessHandleImpl) obj).pid); + } + + /** + * Implementation of ProcessHandle.Info. + * Information snapshot about a process. + * The attributes of a process vary by operating system and not available + * in all implementations. Additionally, information about other processes + * is limited by the operating system privileges of the process making the request. + * If a value is not available, either a {@code null} or {@code -1} is stored. + * The accessor methods return {@code null} if the value is not available. + */ + static class Info implements ProcessHandle.Info { + static { + initIDs(); + } + + /** + * Initialization of JNI fieldIDs. + */ + private static native void initIDs(); + + /** + * Fill in this Info instance with information about the native process. + * If values are not available the native code does not modify the field. + * @param pid of the native process + */ + private native void info0(long pid); + + String command; + String[] arguments; + long startTime; + long totalTime; + String user; + + Info() { + command = null; + arguments = null; + startTime = -1L; + totalTime = -1L; + user = null; + } + + /** + * Returns the Info object with the fields from the process. + * Whatever fields are provided by native are returned. + * + * @param pid the native process identifier + * @return ProcessHandle.Info non-null; individual fields may be null + * or -1 if not available. + */ + public static ProcessHandle.Info info(long pid) { + Info info = new Info(); + info.info0(pid); + return info; + } + + @Override + public Optional command() { + return Optional.ofNullable(command); + } + + @Override + public Optional arguments() { + return Optional.ofNullable(arguments); + } + + @Override + public Optional startInstant() { + return (startTime > 0) + ? Optional.of(Instant.ofEpochMilli(startTime)) + : Optional.empty(); + } + + @Override + public Optional totalCpuDuration() { + return (totalTime != -1) + ? Optional.of(Duration.ofNanos(totalTime)) + : Optional.empty(); + } + + @Override + public Optional user() { + return Optional.ofNullable(user); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(60); + sb.append('['); + if (user != null) { + sb.append("user: "); + sb.append(user()); + } + if (command != null) { + if (sb.length() != 0) sb.append(", "); + sb.append("cmd: "); + sb.append(command); + } + if (arguments != null && arguments.length > 0) { + if (sb.length() != 0) sb.append(", "); + sb.append("args: "); + sb.append(Arrays.toString(arguments)); + } + if (startTime != -1) { + if (sb.length() != 0) sb.append(", "); + sb.append("startTime: "); + sb.append(startInstant()); + } + if (totalTime != -1) { + if (sb.length() != 0) sb.append(", "); + sb.append("totalTime: "); + sb.append(totalCpuDuration().toString()); + } + sb.append(']'); + return sb.toString(); + } + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java b/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java index a2ce1e3d837..a9ebed45b72 100644 --- a/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java +++ b/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -333,6 +333,12 @@ import java.util.StringTokenizer; * "../../../technotes/guides/plugin/developer_guide/rsa_how.html#use"> * usePolicy Permission. * + * + * manageProcess + * Native process termination and information about processes + * {@link ProcessHandle}. + * Allows code to identify and terminate processes that it did not create. + * * * * localeServiceProvider diff --git a/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c b/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c new file mode 100644 index 00000000000..d42b10b9a7f --- /dev/null +++ b/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +#include "jni.h" +#include "jni_util.h" +#include "java_lang_ProcessHandleImpl.h" +#include "java_lang_ProcessHandleImpl_Info.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Implementations of ProcessHandleImpl functions that are + * NOT common to all Unix variants: + * - getProcessPids0(pid, pidArray) + * + * Implementations of ProcessHandleImpl_Info + * - totalTime, startTime + * - Command + * - Arguments + */ + +/* + * Signatures for internal OS specific functions. + */ +static pid_t parentPid(JNIEnv *env, pid_t pid); +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid); +static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid); + +extern jstring uidToUser(JNIEnv* env, uid_t uid); + +/* Field id for jString 'command' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_commandID; + +/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_argumentsID; + +/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_totalTimeID; + +/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_startTimeID; + +/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_userID; + +/* static value for clock ticks per second. */ +static long clock_ticks_per_second; + +/************************************************************** + * Static method to initialize field IDs and the ticks per second rate. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_initIDs + (JNIEnv *env, jclass clazz) { + + CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env, + clazz, "command", "Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env, + clazz, "arguments", "[Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env, + clazz, "totalTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env, + clazz, "startTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env, + clazz, "user", "Ljava/lang/String;")); + clock_ticks_per_second = sysconf(_SC_CLK_TCK); +} + +/* + * Returns the parent pid of the requested pid. + * + * Class: java_lang_ProcessHandleImpl + * Method: parent0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_parent0 +(JNIEnv *env, jobject obj, jlong jpid) { + pid_t pid = (pid_t) jpid; + pid_t ppid = -1; + + if (pid == getpid()) { + ppid = getppid(); + } else { + ppid = parentPid(env, pid); + } + return (jlong) ppid; +} + +/* + * Returns the children of the requested pid and optionally each parent. + * + * Class: java_lang_ProcessHandleImpl + * Method: getChildPids + * Signature: (J[J)I + * + * Reads /proc and accumulates any process who parent pid matches. + * The resulting pids are stored into the array of longs. + * The number of pids is returned if they all fit. + * If the array is too short, the desired length is returned. + */ +JNIEXPORT jint JNICALL Java_java_lang_ProcessHandleImpl_getProcessPids0 +(JNIEnv *env, jclass clazz, jlong jpid, + jlongArray jarray, jlongArray jparentArray) +{ + DIR* dir; + struct dirent* ptr; + pid_t pid = (pid_t) jpid; + size_t count = 0; + jlong* pids = NULL; + jlong* ppids = NULL; + size_t parentArraySize = 0; + size_t arraySize = 0; + + arraySize = (*env)->GetArrayLength(env, jarray); + JNU_CHECK_EXCEPTION_RETURN(env, 0); + if (jparentArray != NULL) { + parentArraySize = (*env)->GetArrayLength(env, jparentArray); + JNU_CHECK_EXCEPTION_RETURN(env, 0); + + if (arraySize != parentArraySize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + + /* + * To locate the children we scan /proc looking for files that have a + * positive integer as a filename. + */ + if ((dir = opendir("/proc")) == NULL) { + JNU_ThrowByNameWithLastError(env, + "java/lang/Runtime", "Unable to open /proc"); + return 0; + } + + do { // Block to break out of on Exception + pids = (*env)->GetLongArrayElements(env, jarray, NULL); + if (pids == NULL) { + break; + } + if (jparentArray != NULL) { + ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL); + if (ppids == NULL) { + break; + } + } + + while ((ptr = readdir(dir)) != NULL) { + pid_t ppid; + + /* skip files that aren't numbers */ + pid_t childpid = (pid_t) atoi(ptr->d_name); + if ((int) childpid <= 0) { + continue; + } + + ppid = 0; + if (pid != 0 || jparentArray != NULL) { + // parentPid opens and reads /proc/pid/stat + ppid = parentPid(env, childpid); + } + if (pid == 0 || ppid == pid) { + if (count < arraySize) { + // Only store if it fits + pids[count] = (jlong) childpid; + + if (ppids != NULL) { + // Store the parentPid + ppids[count] = (jlong) ppid; + } + } + count++; // Count to tabulate size needed + } + } + } while (0); + + if (pids != NULL) { + (*env)->ReleaseLongArrayElements(env, jarray, pids, 0); + } + if (ppids != NULL) { + (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0); + } + + closedir(dir); + // If more pids than array had size for; count will be greater than array size + return count; +} + +/* + * Returns the parent pid of a given pid, or -1 if not found + */ +static pid_t parentPid(JNIEnv *env, pid_t pid) { + FILE* fp; + pstatus_t pstatus; + int statlen; + char fn[32]; + int i, p; + char* s; + + /* + * Try to open /proc/%d/status + */ + snprintf(fn, sizeof fn, "/proc/%d/status", pid); + fp = fopen(fn, "r"); + if (fp == NULL) { + return -1; + } + + /* + * The format is: pid (command) state ppid ... + * As the command could be anything we must find the right most + * ")" and then skip the white spaces that follow it. + */ + statlen = fread(&pstatus, 1, (sizeof pstatus), fp); + fclose(fp); + if (statlen < 0) { + return -1; + } + return (pid_t) pstatus.pr_ppid; +} + +/************************************************************** + * Implementation of ProcessHandleImpl_Info native methods. + */ + +/* + * Fill in the Info object from the OS information about the process. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: info0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_info0 + (JNIEnv *env, jobject jinfo, jlong jpid) { + pid_t pid = (pid_t) jpid; + getStatInfo(env, jinfo, pid); + getCmdlineInfo(env, jinfo, pid); +} + +/** + * Read /proc//stat and fill in the fields of the Info object. + * Gather the user and system times. + */ +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid) { + FILE* fp; + pstatus_t pstatus; + struct stat stat_buf; + int ret; + char fn[32]; + int i, p; + char* s; + jlong totalTime; + + /* + * Try to open /proc/%d/status + */ + snprintf(fn, sizeof fn, "/proc/%d/status", pid); + + if (stat(fn, &stat_buf) < 0) { + return; + } + + fp = fopen(fn, "r"); + if (fp == NULL) { + return; + } + + ret = fread(&pstatus, 1, (sizeof pstatus), fp); + fclose(fp); + if (ret < 0) { + return; + } + + totalTime = pstatus.pr_utime.tv_sec * 1000000000L + pstatus.pr_utime.tv_nsec + + pstatus.pr_stime.tv_sec * 1000000000L + pstatus.pr_stime.tv_nsec; + + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime); + JNU_CHECK_EXCEPTION(env); +} + +static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) { + FILE* fp; + psinfo_t psinfo; + int ret; + char fn[32]; + char exePath[PATH_MAX]; + int i, p; + jlong startTime; + jobjectArray cmdArray; + jstring str = NULL; + + /* + * try to open /proc/%d/psinfo + */ + snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid); + fp = fopen(fn, "r"); + if (fp == NULL) { + return; + } + + /* + * The format is: pid (command) state ppid ... + * As the command could be anything we must find the right most + * ")" and then skip the white spaces that follow it. + */ + ret = fread(&psinfo, 1, (sizeof psinfo), fp); + fclose(fp); + if (ret < 0) { + return; + } + + CHECK_NULL((str = uidToUser(env, psinfo.pr_uid))); + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, str); + JNU_CHECK_EXCEPTION(env); + + startTime = (jlong)psinfo.pr_start.tv_sec * (jlong)1000 + + (jlong)psinfo.pr_start.tv_nsec / 1000000; + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime); + JNU_CHECK_EXCEPTION(env); + + /* + * The path to the executable command is the link in /proc//paths/a.out. + */ + snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid); + if ((ret = readlink(fn, exePath, PATH_MAX - 1)) < 0) { + return; + } + + // null terminate and create String to store for command + exePath[ret] = '\0'; + CHECK_NULL(str = JNU_NewStringPlatform(env, exePath)); + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str); + JNU_CHECK_EXCEPTION(env); +} + diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java index 7fa7dfed338..625a0bed15a 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -39,9 +39,7 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.Locale; import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.security.AccessController; import static java.security.AccessController.doPrivileged; @@ -50,8 +48,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; /** - * This java.lang.Process subclass in the UNIX environment is for the exclusive use of - * ProcessBuilder.start() to create new processes. + * java.lang.Process subclass in the UNIX environment. * * @author Mario Wolczko and Ross Knippel. * @author Konstantin Kladko (ported to Linux and Bsd) @@ -63,12 +60,16 @@ final class ProcessImpl extends Process { private static final sun.misc.JavaIOFileDescriptorAccess fdAccess = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + // Linux platforms support a normal (non-forcible) kill signal. + static final boolean SUPPORTS_NORMAL_TERMINATION = true; + private final int pid; + private final ProcessHandle processHandle; private int exitcode; private boolean hasExited; private /* final */ OutputStream stdin; - private /* final */ InputStream stdout; + private /* final */ InputStream stdout; private /* final */ InputStream stderr; // only used on Solaris @@ -97,7 +98,7 @@ final class ProcessImpl extends Process { Platform(LaunchMechanism ... launchMechanisms) { this.defaultLaunchMechanism = launchMechanisms[0]; this.validLaunchMechanisms = - EnumSet.copyOf(Arrays.asList(launchMechanisms)); + EnumSet.copyOf(Arrays.asList(launchMechanisms)); } @SuppressWarnings("fallthrough") @@ -121,43 +122,43 @@ final class ProcessImpl extends Process { String helperPath() { return AccessController.doPrivileged( - (PrivilegedAction) () -> - helperPath(System.getProperty("java.home"), - System.getProperty("os.arch")) + (PrivilegedAction) () -> + helperPath(System.getProperty("java.home"), + System.getProperty("os.arch")) ); } LaunchMechanism launchMechanism() { return AccessController.doPrivileged( - (PrivilegedAction) () -> { - String s = System.getProperty( - "jdk.lang.Process.launchMechanism"); - LaunchMechanism lm; - if (s == null) { - lm = defaultLaunchMechanism; - s = lm.name().toLowerCase(Locale.ENGLISH); - } else { - try { - lm = LaunchMechanism.valueOf( - s.toUpperCase(Locale.ENGLISH)); - } catch (IllegalArgumentException e) { - lm = null; - } + (PrivilegedAction) () -> { + String s = System.getProperty( + "jdk.lang.Process.launchMechanism"); + LaunchMechanism lm; + if (s == null) { + lm = defaultLaunchMechanism; + s = lm.name().toLowerCase(Locale.ENGLISH); + } else { + try { + lm = LaunchMechanism.valueOf( + s.toUpperCase(Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + lm = null; } - if (lm == null || !validLaunchMechanisms.contains(lm)) { - throw new Error( - s + " is not a supported " + - "process launch mechanism on this platform." - ); - } - return lm; } + if (lm == null || !validLaunchMechanisms.contains(lm)) { + throw new Error( + s + " is not a supported " + + "process launch mechanism on this platform." + ); + } + return lm; + } ); } static Platform get() { String osName = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("os.name") + (PrivilegedAction) () -> System.getProperty("os.name") ); if (osName.equals("Linux")) { return LINUX; } @@ -173,17 +174,14 @@ final class ProcessImpl extends Process { private static final LaunchMechanism launchMechanism = platform.launchMechanism(); private static final byte[] helperpath = toCString(platform.helperPath()); - /* this is for the reaping thread */ - private native int waitForProcessExit(int pid); - private static byte[] toCString(String s) { if (s == null) return null; byte[] bytes = s.getBytes(); byte[] result = new byte[bytes.length + 1]; System.arraycopy(bytes, 0, - result, 0, - bytes.length); + result, 0, + bytes.length); result[result.length-1] = (byte)0; return result; } @@ -304,30 +302,7 @@ final class ProcessImpl extends Process { byte[] dir, int[] fds, boolean redirectErrorStream) - throws IOException; - - /** - * The thread pool of "process reaper" daemon threads. - */ - private static final Executor processReaperExecutor = - doPrivileged((PrivilegedAction) () -> { - - ThreadGroup tg = Thread.currentThread().getThreadGroup(); - while (tg.getParent() != null) tg = tg.getParent(); - ThreadGroup systemThreadGroup = tg; - - ThreadFactory threadFactory = grimReaper -> { - // Our thread stack requirement is quite modest. - Thread t = new Thread(systemThreadGroup, grimReaper, - "process reaper", 32768); - t.setDaemon(true); - // A small attempt (probably futile) to avoid priority inversion - t.setPriority(Thread.MAX_PRIORITY); - return t; - }; - - return Executors.newCachedThreadPool(threadFactory); - }); + throws IOException; private ProcessImpl(final byte[] prog, final byte[] argBlock, final int argc, @@ -338,13 +313,14 @@ final class ProcessImpl extends Process { throws IOException { pid = forkAndExec(launchMechanism.ordinal() + 1, - helperpath, - prog, - argBlock, argc, - envBlock, envc, - dir, - fds, - redirectErrorStream); + helperpath, + prog, + argBlock, argc, + envBlock, envc, + dir, + fds, + redirectErrorStream); + processHandle = ProcessHandleImpl.getUnchecked(pid); try { doPrivileged((PrivilegedExceptionAction) () -> { @@ -371,18 +347,16 @@ final class ProcessImpl extends Process { new ProcessPipeOutputStream(fds[0]); stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[1]); + ProcessBuilder.NullInputStream.INSTANCE : + new ProcessPipeInputStream(fds[1]); stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ProcessPipeInputStream(fds[2]); - - processReaperExecutor.execute(() -> { - int exitcode = waitForProcessExit(pid); + ProcessBuilder.NullInputStream.INSTANCE : + new ProcessPipeInputStream(fds[2]); + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> { synchronized (this) { - this.exitcode = exitcode; + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue(); this.hasExited = true; this.notifyAll(); } @@ -395,6 +369,8 @@ final class ProcessImpl extends Process { if (stdin instanceof ProcessPipeOutputStream) ((ProcessPipeOutputStream) stdin).processExited(); + + return null; }); break; @@ -402,18 +378,18 @@ final class ProcessImpl extends Process { stdin = (fds[0] == -1) ? ProcessBuilder.NullOutputStream.INSTANCE : new BufferedOutputStream( - new FileOutputStream(newFileDescriptor(fds[0]))); + new FileOutputStream(newFileDescriptor(fds[0]))); stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new BufferedInputStream( - stdout_inner_stream = - new DeferredCloseInputStream( - newFileDescriptor(fds[1]))); + ProcessBuilder.NullInputStream.INSTANCE : + new BufferedInputStream( + stdout_inner_stream = + new DeferredCloseInputStream( + newFileDescriptor(fds[1]))); stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new DeferredCloseInputStream(newFileDescriptor(fds[2])); + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseInputStream(newFileDescriptor(fds[2])); /* * For each subprocess forked a corresponding reaper task @@ -423,14 +399,13 @@ final class ProcessImpl extends Process { * exitStatus() to be safely executed in parallel (and they * need no native code). */ - processReaperExecutor.execute(() -> { - int exitcode = waitForProcessExit(pid); - + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> { synchronized (this) { - this.exitcode = exitcode; + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue(); this.hasExited = true; this.notifyAll(); } + return null; }); break; @@ -440,18 +415,16 @@ final class ProcessImpl extends Process { new ProcessPipeOutputStream(fds[0]); stdout = (fds[1] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new DeferredCloseProcessPipeInputStream(fds[1]); + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseProcessPipeInputStream(fds[1]); stderr = (fds[2] == -1) ? - ProcessBuilder.NullInputStream.INSTANCE : - new DeferredCloseProcessPipeInputStream(fds[2]); - - processReaperExecutor.execute(() -> { - int exitcode = waitForProcessExit(pid); + ProcessBuilder.NullInputStream.INSTANCE : + new DeferredCloseProcessPipeInputStream(fds[2]); + ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> { synchronized (this) { - this.exitcode = exitcode; + this.exitcode = (exitcode == null) ? -1 : exitcode.intValue(); this.hasExited = true; this.notifyAll(); } @@ -464,6 +437,8 @@ final class ProcessImpl extends Process { if (stdin instanceof ProcessPipeOutputStream) ((ProcessPipeOutputStream) stdin).processExited(); + + return null; }); break; @@ -492,7 +467,7 @@ final class ProcessImpl extends Process { @Override public synchronized boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException + throws InterruptedException { long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions if (hasExited) return true; @@ -517,8 +492,6 @@ final class ProcessImpl extends Process { return exitcode; } - private static native void destroyProcess(int pid, boolean force); - private void destroy(boolean force) { switch (platform) { case LINUX: @@ -532,7 +505,7 @@ final class ProcessImpl extends Process { // soon, so this is quite safe. synchronized (this) { if (!hasExited) - destroyProcess(pid, force); + ProcessHandleImpl.destroyProcess(pid, force); } try { stdin.close(); } catch (IOException ignored) {} try { stdout.close(); } catch (IOException ignored) {} @@ -548,14 +521,14 @@ final class ProcessImpl extends Process { // soon, so this is quite safe. synchronized (this) { if (!hasExited) - destroyProcess(pid, force); + ProcessHandleImpl.destroyProcess(pid, force); try { stdin.close(); if (stdout_inner_stream != null) stdout_inner_stream.closeDeferred(stdout); if (stderr instanceof DeferredCloseInputStream) ((DeferredCloseInputStream) stderr) - .closeDeferred(stderr); + .closeDeferred(stderr); } catch (IOException e) { // ignore } @@ -566,6 +539,27 @@ final class ProcessImpl extends Process { } } + @Override + public CompletableFuture onExit() { + return ProcessHandleImpl.completion(pid, false) + .handleAsync((exitStatus, unusedThrowable) -> this); + } + + @Override + public ProcessHandle toHandle() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + return processHandle; + } + + @Override + public boolean supportsNormalTermination() { + return ProcessImpl.SUPPORTS_NORMAL_TERMINATION; + } + + @Override public void destroy() { destroy(false); } @@ -629,8 +623,8 @@ final class ProcessImpl extends Process { byte[] stragglers = drainInputStream(in); in.close(); this.in = (stragglers == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(stragglers); + ProcessBuilder.NullInputStream.INSTANCE : + new ByteArrayInputStream(stragglers); } } catch (IOException ignored) {} } @@ -797,7 +791,7 @@ final class ProcessImpl extends Process { * */ private static class DeferredCloseProcessPipeInputStream - extends BufferedInputStream { + extends BufferedInputStream { private final Object closeLock = new Object(); private int useCount = 0; diff --git a/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c new file mode 100644 index 00000000000..7b3fa28fe29 --- /dev/null +++ b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +#include "jni.h" +#include "jni_util.h" +#include "java_lang_ProcessHandleImpl.h" +#include "java_lang_ProcessHandleImpl_Info.h" + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/** + * Implementations of ProcessHandleImpl functions that are common to all + * Unix variants: + * - waitForProcessExit0(pid, reap) + * - getCurrentPid0() + * - destroy0(pid, force) + */ + + +#ifndef WIFEXITED +#define WIFEXITED(status) (((status)&0xFF) == 0) +#endif + +#ifndef WEXITSTATUS +#define WEXITSTATUS(status) (((status)>>8)&0xFF) +#endif + +#ifndef WIFSIGNALED +#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0) +#endif + +#ifndef WTERMSIG +#define WTERMSIG(status) ((status)&0x7F) +#endif + +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + +#define RESTARTABLE_RETURN_PTR(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == NULL) && (errno == EINTR)); \ +} while(0) + + +/* Block until a child process exits and return its exit code. + * Note, can only be called once for any given pid if reapStatus = true. + */ +JNIEXPORT jint JNICALL +Java_java_lang_ProcessHandleImpl_waitForProcessExit0(JNIEnv* env, + jclass junk, + jlong jpid, + jboolean reapStatus) +{ + pid_t pid = (pid_t)jpid; + errno = 0; + + if (reapStatus != JNI_FALSE) { + /* Wait for the child process to exit. + * waitpid() is standard, so use it on all POSIX platforms. + * It is known to work when blocking to wait for the pid + * This returns immediately if the child has already exited. + */ + int status; + while (waitpid(pid, &status, 0) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + /* The child exited because of a signal. + * The best value to return is 0x80 + signal number, + * because that is what all Unix shells do, and because + * it allows callers to distinguish between process exit and + * process death by signal. + * Unfortunately, the historical behavior on Solaris is to return + * the signal number, and we preserve this for compatibility. */ +#ifdef __solaris__ + return WTERMSIG(status); +#else + return 0x80 + WTERMSIG(status); +#endif + } else { + return status; + } + } else { + /* + * Wait for the child process to exit without reaping the exitValue. + * waitid() is standard on all POSIX platforms. + * Note: waitid on Mac OS X 10.7 seems to be broken; + * it does not return the exit status consistently. + */ + siginfo_t siginfo; + int options = WEXITED | WNOWAIT; + memset(&siginfo, 0, sizeof siginfo); + while (waitid(P_PID, pid, &siginfo, options) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (siginfo.si_code == CLD_EXITED) { + /* + * The child exited normally; get its exit code. + */ + return siginfo.si_status; + } else if (siginfo.si_code == CLD_KILLED || siginfo.si_code == CLD_DUMPED) { + /* The child exited because of a signal. + * The best value to return is 0x80 + signal number, + * because that is what all Unix shells do, and because + * it allows callers to distinguish between process exit and + * process death by signal. + * Unfortunately, the historical behavior on Solaris is to return + * the signal number, and we preserve this for compatibility. */ + #ifdef __solaris__ + return WTERMSIG(siginfo.si_status); + #else + return 0x80 + WTERMSIG(siginfo.si_status); + #endif + } else { + /* + * Unknown exit code; pass it through. + */ + return siginfo.si_status; + } + } +} + +/* + * Class: java_lang_ProcessHandleImpl + * Method: getCurrentPid0 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_getCurrentPid0 +(JNIEnv *env, jclass clazz) { + pid_t pid = getpid(); + return (jlong) pid; +} + +/* + * Class: java_lang_ProcessHandleImpl + * Method: isAlive0 + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_java_lang_ProcessHandleImpl_isAlive0 +(JNIEnv *env, jobject obj, jlong jpid) { + pid_t pid = (pid_t) jpid; + return (kill(pid, 0) < 0) ? JNI_FALSE : JNI_TRUE; +} + +/* + * Class: java_lang_ProcessHandleImpl + * Method: destroy0 + * Signature: (Z)Z + */ +JNIEXPORT jboolean JNICALL Java_java_lang_ProcessHandleImpl_destroy0 +(JNIEnv *env, jobject obj, jlong jpid, jboolean force) { + pid_t pid = (pid_t) jpid; + int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM; + return (kill(pid, sig) >= 0); + +} + +/** + * Size of password or group entry when not available via sysconf + */ +#define ENT_BUF_SIZE 1024 + +/** + * Return a strong username for the uid_t or null. + */ +jstring uidToUser(JNIEnv* env, uid_t uid) { + int result = 0; + int buflen; + char* pwbuf; + jstring name = NULL; + + /* allocate buffer for password record */ + buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) + buflen = ENT_BUF_SIZE; + pwbuf = (char*)malloc(buflen); + if (pwbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "Unable to open getpwent"); + } else { + struct passwd pwent; + struct passwd* p = NULL; + +#ifdef __solaris__ + RESTARTABLE_RETURN_PTR(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen), p); +#else + RESTARTABLE(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen, &p), result); +#endif + + // Return the Java String if a name was found + if (result == 0 && p != NULL && + p->pw_name != NULL && *(p->pw_name) != '\0') { + name = JNU_NewStringPlatform(env, p->pw_name); + } + free(pwbuf); + } + return name; +} + +/** + * Implementations of ProcessHandleImpl functions that are common to + * (some) Unix variants: + * - getProcessPids0(pid, pidArray, parentArray) + */ + +#if defined(__linux__) || defined(__AIX__) + +/* + * Signatures for internal OS specific functions. + */ +static pid_t parentPid(JNIEnv *env, pid_t pid); +static jint getChildren(JNIEnv *env, jlong jpid, + jlongArray array, jlongArray jparentArray); + +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid); +static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo); +static long long getBoottime(JNIEnv *env); + +jstring uidToUser(JNIEnv* env, uid_t uid); + +/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_commandID; + +/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_argumentsID; + +/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_totalTimeID; + +/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_startTimeID; + +/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */ +static jfieldID ProcessHandleImpl_Info_userID; + +/* static value for clock ticks per second. */ +static long clock_ticks_per_second; + +/* A static offset in milliseconds since boot. */ +static long long bootTime_ms; + +/************************************************************** + * Static method to initialize field IDs and the ticks per second rate. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_initIDs + (JNIEnv *env, jclass clazz) { + + CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env, + clazz, "command", "Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env, + clazz, "arguments", "[Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env, + clazz, "totalTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env, + clazz, "startTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env, + clazz, "user", "Ljava/lang/String;")); + clock_ticks_per_second = sysconf(_SC_CLK_TCK); + bootTime_ms = getBoottime(env); +} + +/* + * Returns the parent pid of the requested pid. + * + * Class: java_lang_ProcessHandleImpl + * Method: parent0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_parent0 +(JNIEnv *env, jobject obj, jlong jpid) { + pid_t pid = (pid_t) jpid; + pid_t ppid = -1; + + pid_t mypid = getpid(); + if (pid == mypid) { + ppid = getppid(); + } else { + ppid = parentPid(env, pid); + } + return (jlong) ppid; +} + +/* + * Returns the children of the requested pid and optionally each parent. + * + * Class: java_lang_ProcessHandleImpl + * Method: getChildPids + * Signature: (J[J[J)I + */ +JNIEXPORT jint JNICALL Java_java_lang_ProcessHandleImpl_getProcessPids0 +(JNIEnv *env, jclass clazz, jlong jpid, + jlongArray jarray, jlongArray jparentArray) { + return getChildren(env, jpid, jarray, jparentArray); +} + +/* + * Reads /proc and accumulates any process who parent pid matches. + * The resulting pids are stored into the array of longs. + * The number of pids is returned if they all fit. + * If the array is too short, the negative of the desired length is returned. + */ +static jint getChildren(JNIEnv *env, jlong jpid, + jlongArray jarray, jlongArray jparentArray) { + DIR* dir; + struct dirent* ptr; + pid_t pid = (pid_t) jpid; + pid_t ppid = 0; + size_t count = 0; + jlong* pids = NULL; + jlong* ppids = NULL; + size_t parentArraySize = 0; + size_t arraySize = 0; + + arraySize = (*env)->GetArrayLength(env, jarray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + if (jparentArray != NULL) { + parentArraySize = (*env)->GetArrayLength(env, jparentArray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + + if (arraySize != parentArraySize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + + /* + * To locate the children we scan /proc looking for files that have a + * position integer as a filename. + */ + if ((dir = opendir("/proc")) == NULL) { + JNU_ThrowByNameWithLastError(env, + "java/lang/Runtime", "Unable to open /proc"); + return -1; + } + + do { // Block to break out of on Exception + pids = (*env)->GetLongArrayElements(env, jarray, NULL); + if (pids == NULL) { + break; + } + if (jparentArray != NULL) { + ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL); + if (ppids == NULL) { + break; + } + } + + while ((ptr = readdir(dir)) != NULL) { + /* skip files that aren't numbers */ + pid_t childpid = (pid_t) atoi(ptr->d_name); + if ((int) childpid <= 0) { + continue; + } + + ppid = 0; + if (pid != 0 || jparentArray != NULL) { + // parentPid opens and reads /proc/pid/stat + ppid = parentPid(env, childpid); + } + if (pid == 0 || ppid == pid) { + if (count < arraySize) { + // Only store if it fits + pids[count] = (jlong) childpid; + + if (ppids != NULL) { + // Store the parentPid + ppids[count] = (jlong) ppid; + } + } + count++; // Count to tabulate size needed + } + } + } while (0); + + if (pids != NULL) { + (*env)->ReleaseLongArrayElements(env, jarray, pids, 0); + } + if (ppids != NULL) { + (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0); + } + + closedir(dir); + // If more pids than array had size for; count will be greater than array size + return count; +} + +/* + * Returns the parent pid of a given pid, or -1 if not found + */ +static pid_t parentPid(JNIEnv *env, pid_t pid) { + char state; + FILE* fp; + char stat[2048]; + int statlen; + char fn[32]; + int i, p; + char* s; + + /* + * try to open /proc/%d/stat + */ + snprintf(fn, sizeof fn, "/proc/%d/stat", pid); + fp = fopen(fn, "r"); + if (fp == NULL) { + return -1; + } + + /* + * The format is: pid (command) state ppid ... + * As the command could be anything we must find the right most + * ")" and then skip the white spaces that follow it. + */ + statlen = fread(stat, 1, (sizeof stat - 1), fp); + fclose(fp); + if (statlen < 0) { + return -1; + } + + stat[statlen] = '\0'; + s = strrchr(stat, ')'); + if (s == NULL) { + return -1; + } + do s++; while (isspace(*s)); + i = sscanf(s, "%c %d", &state, &p); + if (i != 2) { + return (pid_t)-1; + } + return (pid_t) p; +} + +/************************************************************** + * Implementation of ProcessHandleImpl_Info native methods. + */ + +/* + * Fill in the Info object from the OS information about the process. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: info0 + * Signature: (JLjava/lang/ProcessHandle/Info;)I + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_info0 + (JNIEnv *env, jobject jinfo, jlong jpid) { + pid_t pid = (pid_t) jpid; + getStatInfo(env, jinfo, (pid_t)pid); + getCmdlineInfo(env, pid, jinfo); +} + +/** + * Read /proc//stat and fill in the fields of the Info object. + * The executable name, plus the user, system, and start times are gathered. + */ +static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid) { + char state; + FILE* fp; + char buffer[2048]; + struct stat stat_buf; + int statlen; + char fn[32]; + int i, ppid = -2; + char* s; + char *cmd; + jstring name = NULL; + unsigned long userTime = 0; // clock tics + unsigned long totalTime = 0; // clock tics + jlong total = 0; // nano seconds + unsigned long long startTime = 0; // microseconds + + /* + * Try to stat and then open /proc/%d/stat + */ + snprintf(fn, sizeof fn, "/proc/%d/stat", pid); + + if (stat(fn, &stat_buf) < 0) { + return; + } + + CHECK_NULL((name = uidToUser(env, stat_buf.st_uid))); + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name); + JNU_CHECK_EXCEPTION(env); + + fp = fopen(fn, "r"); + if (fp == NULL) { + return; + } + + /* + * The format is: pid (command) state ppid ... + * As the command could be anything we must find the right most + * ")" and then skip the white spaces that follow it. + */ + statlen = fread(buffer, 1, (sizeof buffer - 1), fp); + fclose(fp); + if (statlen < 0) { + return; + } + + buffer[statlen] = '\0'; + s = strchr(buffer, '('); + if (s == NULL) { + return; + } + // Found start of command, skip to end + s++; + s = strrchr(s, ')'); + if (s == NULL) { + return; + } + s++; + + // Scan the needed fields from status, retaining only ppid(4), + // utime (14), stime(15), starttime(22) + i = sscanf(s, " %c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %llu", + &state, &ppid, &userTime, &totalTime, &startTime); + if (i != 5) { + return; // not all values parsed; return error + } + + total = (userTime + totalTime) * (jlong)(1000000000 / clock_ticks_per_second); + + startTime = bootTime_ms + ((startTime * 1000) / clock_ticks_per_second); + + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, total); + JNU_CHECK_EXCEPTION(env); + (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime); + JNU_CHECK_EXCEPTION(env); +} + +/** + * Construct the argument array by parsing the arguments from the sequence + * of arguments. The zero'th arg is the command executable + */ +static int fillArgArray(JNIEnv *env, jobject jinfo, + int nargs, char *cp, char *argsEnd, jstring cmdexe) { + jobject argsArray; + int i; + + if (nargs < 1) { + return 0; + } + + if (cmdexe == NULL) { + // Create a string from arg[0] + CHECK_NULL_RETURN((cmdexe = JNU_NewStringPlatform(env, cp)), -1); + } + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, cmdexe); + JNU_CHECK_EXCEPTION_RETURN(env, -3); + + // Create a String array for nargs-1 elements + argsArray = (*env)->NewObjectArray(env, nargs - 1, JNU_ClassString(env), NULL); + CHECK_NULL_RETURN(argsArray, -1); + + for (i = 0; i < nargs - 1; i++) { + jstring str = NULL; + + cp += strnlen(cp, (argsEnd - cp)) + 1; + if (cp > argsEnd || *cp == '\0') { + return -2; // Off the end pointer or an empty argument is an error + } + + CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1); + + (*env)->SetObjectArrayElement(env, argsArray, i, str); + JNU_CHECK_EXCEPTION_RETURN(env, -3); + } + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray); + JNU_CHECK_EXCEPTION_RETURN(env, -4); + return 0; +} + + +static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo) { + int fd; + int cmdlen = 0; + char *cmdline = NULL, *cmdEnd; // used for command line args and exe + jstring cmdexe = NULL; + char fn[32]; + + /* + * Try to open /proc/%d/cmdline + */ + snprintf(fn, sizeof fn, "/proc/%d/cmdline", pid); + if ((fd = open(fn, O_RDONLY)) < 0) { + return; + } + + do { // Block to break out of on errors + int i; + char *s; + + cmdline = (char*)malloc(PATH_MAX); + if (cmdline == NULL) { + break; + } + + /* + * The path to the executable command is the link in /proc//exe. + */ + snprintf(fn, sizeof fn, "/proc/%d/exe", pid); + if ((cmdlen = readlink(fn, cmdline, PATH_MAX - 1)) > 0) { + // null terminate and create String to store for command + cmdline[cmdlen] = '\0'; + cmdexe = JNU_NewStringPlatform(env, cmdline); + (*env)->ExceptionClear(env); // unconditionally clear any exception + } + + /* + * The buffer format is the arguments nul terminated with an extra nul. + */ + cmdlen = read(fd, cmdline, PATH_MAX-1); + if (cmdlen < 0) { + break; + } + + // Terminate the buffer and count the arguments + cmdline[cmdlen] = '\0'; + cmdEnd = &cmdline[cmdlen + 1]; + for (s = cmdline,i = 0; *s != '\0' && (s < cmdEnd); i++) { + s += strnlen(s, (cmdEnd - s)) + 1; + } + + if (fillArgArray(env, jinfo, i, cmdline, cmdEnd, cmdexe) < 0) { + break; + } + } while (0); + + if (cmdline != NULL) { + free(cmdline); + } + if (fd >= 0) { + close(fd); + } +} + +/** + * Read the boottime from /proc/stat. + */ +static long long getBoottime(JNIEnv *env) { + FILE *fp; + char *line = NULL; + size_t len = 0; + long long bootTime = 0; + + fp = fopen("/proc/stat", "r"); + if (fp == NULL) { + return -1; + } + + while (getline(&line, &len, fp) != -1) { + if (sscanf(line, "btime %llu", &bootTime) == 1) { + break; + } + } + free(line); + + if (fp != 0) { + fclose(fp); + } + + return bootTime * 1000; +} + +#endif // defined(__linux__) || defined(__AIX__) + + +/* Block until a child process exits and return its exit code. + Note, can only be called once for any given pid. */ +JNIEXPORT jint JNICALL +Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env, + jobject junk, + jint pid) +{ + /* We used to use waitid() on Solaris, waitpid() on Linux, but + * waitpid() is more standard, so use it on all POSIX platforms. */ + int status; + /* Wait for the child process to exit. This returns immediately if + the child has already exited. */ + while (waitpid(pid, &status, 0) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (WIFEXITED(status)) { + /* + * The child exited normally; get its exit code. + */ + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + /* The child exited because of a signal. + * The best value to return is 0x80 + signal number, + * because that is what all Unix shells do, and because + * it allows callers to distinguish between process exit and + * process death by signal. + * Unfortunately, the historical behavior on Solaris is to return + * the signal number, and we preserve this for compatibility. */ +#ifdef __solaris__ + return WTERMSIG(status); +#else + return 0x80 + WTERMSIG(status); +#endif + } else { + /* + * Unknown exit code; pass it through. + */ + return status; + } +} + + diff --git a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c index 2c85b9da1cc..44777a43f2e 100644 --- a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -226,52 +226,6 @@ Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz) #define WTERMSIG(status) ((status)&0x7F) #endif -/* Block until a child process exits and return its exit code. - Note, can only be called once for any given pid. */ -JNIEXPORT jint JNICALL -Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env, - jobject junk, - jint pid) -{ - /* We used to use waitid() on Solaris, waitpid() on Linux, but - * waitpid() is more standard, so use it on all POSIX platforms. */ - int status; - /* Wait for the child process to exit. This returns immediately if - the child has already exited. */ - while (waitpid(pid, &status, 0) < 0) { - switch (errno) { - case ECHILD: return 0; - case EINTR: break; - default: return -1; - } - } - - if (WIFEXITED(status)) { - /* - * The child exited normally; get its exit code. - */ - return WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - /* The child exited because of a signal. - * The best value to return is 0x80 + signal number, - * because that is what all Unix shells do, and because - * it allows callers to distinguish between process exit and - * process death by signal. - * Unfortunately, the historical behavior on Solaris is to return - * the signal number, and we preserve this for compatibility. */ -#ifdef __solaris__ - return WTERMSIG(status); -#else - return 0x80 + WTERMSIG(status); -#endif - } else { - /* - * Unknown exit code; pass it through. - */ - return status; - } -} - static const char * getBytes(JNIEnv *env, jbyteArray arr) { @@ -686,12 +640,3 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, goto Finally; } -JNIEXPORT void JNICALL -Java_java_lang_ProcessImpl_destroyProcess(JNIEnv *env, - jobject junk, - jint pid, - jboolean force) -{ - int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM; - kill(pid, sig); -} diff --git a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java index f6ed286d991..d14d1aa0766 100644 --- a/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -34,10 +34,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.Override; import java.lang.ProcessBuilder.Redirect; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -53,6 +55,9 @@ final class ProcessImpl extends Process { private static final sun.misc.JavaIOFileDescriptorAccess fdAccess = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + // Windows platforms support a forcible kill signal. + static final boolean SUPPORTS_NORMAL_TERMINATION = false; + /** * Open a file for writing. If {@code append} is {@code true} then the file * is opened for atomic append directly and a FileOutputStream constructed @@ -306,7 +311,8 @@ final class ProcessImpl extends Process { } - private long handle = 0; + private final long handle; + private final ProcessHandle processHandle; private OutputStream stdin_stream; private InputStream stdout_stream; private InputStream stderr_stream; @@ -385,6 +391,7 @@ final class ProcessImpl extends Process { handle = create(cmdstr, envblock, path, stdHandles, redirectErrorStream); + processHandle = ProcessHandleImpl.getUnchecked(getProcessId0(handle)); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -481,7 +488,30 @@ final class ProcessImpl extends Process { private static native void waitForTimeoutInterruptibly( long handle, long timeout); - public void destroy() { terminateProcess(handle); } + @Override + public void destroy() { + terminateProcess(handle); + } + + @Override + public CompletableFuture onExit() { + return ProcessHandleImpl.completion(getPid(), false) + .handleAsync((exitStatus, unusedThrowable) -> this); + } + + @Override + public ProcessHandle toHandle() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("manageProcess")); + } + return processHandle; + } + + @Override + public boolean supportsNormalTermination() { + return ProcessImpl.SUPPORTS_NORMAL_TERMINATION; + } @Override public Process destroyForcibly() { @@ -493,8 +523,7 @@ final class ProcessImpl extends Process { @Override public long getPid() { - int pid = getProcessId0(handle); - return pid; + return processHandle.getPid(); } private static native int getProcessId0(long handle); @@ -538,7 +567,7 @@ final class ProcessImpl extends Process { * Opens a file for atomic append. The file is created if it doesn't * already exist. * - * @param file the file to open or create + * @param path the file to open or create * @return the native HANDLE */ private static native long openForAtomicAppend(String path) diff --git a/jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c b/jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c new file mode 100644 index 00000000000..23846cfb3e8 --- /dev/null +++ b/jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + + +#include "jni.h" +#include "jvm.h" +#include "jni_util.h" +#include "java_lang_ProcessHandleImpl.h" +#include "java_lang_ProcessHandleImpl_Info.h" + +#include +#include + +static void getStatInfo(JNIEnv *env, HANDLE handle, jobject jinfo); +static void getCmdlineInfo(JNIEnv *env, HANDLE handle, jobject jinfo); +static void procToUser( JNIEnv *env, HANDLE handle, jobject jinfo); + +/************************************************************** + * Implementation of ProcessHandleImpl_Info native methods. + */ + +/* Field id for jString 'command' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_commandID; + +/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_argumentsID; + +/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_totalTimeID; + +/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */ +static jfieldID ProcessHandleImpl_Info_startTimeID; + +/* Field id for jString 'accountName' in java.lang.ProcessHandleImpl.UserPrincipal */ +static jfieldID ProcessHandleImpl_Info_userID; + +/************************************************************** + * Static method to initialize field IDs. + * + * Class: java_lang_ProcessHandleImpl_Info + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_initIDs + (JNIEnv *env, jclass clazz) { + + CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env, + clazz, "command", "Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env, + clazz, "arguments", "[Ljava/lang/String;")); + CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env, + clazz, "totalTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env, + clazz, "startTime", "J")); + CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env, + clazz, "user", "Ljava/lang/String;")); +} + +/* + * Block until a child process exits and return its exit code. + */ +JNIEXPORT jint JNICALL +Java_java_lang_ProcessHandleImpl_waitForProcessExit0(JNIEnv* env, + jclass junk, + jlong jpid, + jboolean reapStatus) { + DWORD pid = (DWORD)jpid; + DWORD exitValue = -1; + HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, + FALSE, pid); + if (handle == NULL) { + return exitValue; // No process with that pid is alive + } + do { + if (!GetExitCodeProcess(handle, &exitValue)) { + JNU_ThrowByNameWithLastError(env, + "java/lang/Runtime", "GetExitCodeProcess"); + break; + } + if (exitValue == STILL_ACTIVE) { + HANDLE events[2]; + events[0] = handle; + events[1] = JVM_GetThreadInterruptEvent(); + + if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, + FALSE, /* Wait for ANY event */ + INFINITE) /* Wait forever */ + == WAIT_FAILED) { + JNU_ThrowByNameWithLastError(env, + "java/lang/Runtime", "WaitForMultipleObjects"); + break; + } + } + } while (exitValue == STILL_ACTIVE); + CloseHandle(handle); // Ignore return code + return exitValue; +} + +/* + * Returns the pid of the caller. + * + * Class: java_lang_ProcessHandleImpl + * Method: getCurrentPid0 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_getCurrentPid0 +(JNIEnv *env, jclass clazz) { + DWORD pid = GetCurrentProcessId(); + return (jlong)pid; +} + +/* + * Returns the parent pid of the requested pid. + * + * Class: java_lang_ProcessHandleImpl + * Method: parent0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_java_lang_ProcessHandleImpl_parent0 +(JNIEnv *env, jclass clazz, jlong jpid) { + + DWORD ppid = -1; + DWORD wpid = (DWORD)jpid; + PROCESSENTRY32 pe32; + HANDLE hProcessSnap; + + // Take a snapshot of all processes in the system. + hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + JNU_ThrowByName(env, + "java/lang/RuntimeException", "snapshot not available"); + return -1; + } + + // Retrieve information about the first process, + pe32.dwSize = sizeof (PROCESSENTRY32); + if (Process32First(hProcessSnap, &pe32)) { + // Now walk the snapshot of processes, and + do { + if (wpid == pe32.th32ProcessID) { + ppid = pe32.th32ParentProcessID; + break; + } + } while (Process32Next(hProcessSnap, &pe32)); + } else { + JNU_ThrowByName(env, + "java/lang/RuntimeException", "snapshot not available"); + return -1; + } + CloseHandle(hProcessSnap); // Ignore return code + return (jlong)ppid; +} + +/* + * Returns the children of the requested pid and optionally each parent. + * + * Class: java_lang_ProcessHandleImpl + * Method: getChildPids + * Signature: (J[J[J)I + */ +JNIEXPORT jint JNICALL Java_java_lang_ProcessHandleImpl_getProcessPids0 +(JNIEnv *env, jclass clazz, jlong jpid, + jlongArray jarray, jlongArray jparentArray) { + + HANDLE hProcessSnap; + PROCESSENTRY32 pe32; + DWORD ppid = (DWORD)jpid; + size_t count = 0; + jlong* pids = NULL; + jlong* ppids = NULL; + size_t parentArraySize = 0; + size_t arraySize = 0; + + arraySize = (*env)->GetArrayLength(env, jarray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + if (jparentArray != NULL) { + parentArraySize = (*env)->GetArrayLength(env, jparentArray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + + if (arraySize != parentArraySize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + + // Take a snapshot of all processes in the system. + hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + JNU_ThrowByName(env, + "java/lang/RuntimeException", "snapshot not available"); + return 0; + } + + // Retrieve information about the first process, + pe32.dwSize = sizeof (PROCESSENTRY32); + if (Process32First(hProcessSnap, &pe32)) { + do { // Block to break out of on Exception + pids = (*env)->GetLongArrayElements(env, jarray, NULL); + if (pids == NULL) { + break; + } + if (jparentArray != NULL) { + ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL); + if (ppids == NULL) { + break; + } + } + // Now walk the snapshot of processes, and + // save information about each process in turn + do { + if (ppid == 0 || + (pe32.th32ParentProcessID > 0 + && (pe32.th32ParentProcessID == ppid))) { + if (count < arraySize) { + // Only store if it fits + pids[count] = (jlong)pe32.th32ProcessID; + if (ppids != NULL) { + // Store the parentPid + ppids[count] = (jlong) pe32.th32ParentProcessID; + } + } + count++; // Count to tabulate size needed + } + } while (Process32Next(hProcessSnap, &pe32)); + } while (0); + + if (pids != NULL) { + (*env)->ReleaseLongArrayElements(env, jarray, pids, 0); + } + if (ppids != NULL) { + (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0); + } + } else { + JNU_ThrowByName(env, + "java/lang/RuntimeException", "snapshot not available"); + return 0; + } + CloseHandle(hProcessSnap); + // If more pids than array had size for; count will be greater than array size + return (jint)count; +} + +/* + * Destroy the process. + * + * Class: java_lang_ProcessHandleImpl + * Method: destroy0 + * Signature: (Z)V + */ +JNIEXPORT jboolean JNICALL Java_java_lang_ProcessHandleImpl_destroy0 +(JNIEnv *env, jclass clazz, jlong jpid, jboolean force) { + DWORD pid = (DWORD)jpid; + HANDLE handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (handle != NULL) { + TerminateProcess(handle, 1); + CloseHandle(handle); // Ignore return code + return JNI_TRUE; + } + return JNI_FALSE; +} + +/* + * Class: java_lang_ProcessHandleImpl + * Method: isAlive0 + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_java_lang_ProcessHandleImpl_isAlive0 +(JNIEnv *env, jclass clazz, jlong jpid) { + DWORD pid = (DWORD)jpid; + + jboolean ret = JNI_FALSE; + HANDLE handle = + OpenProcess(THREAD_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, + FALSE, pid); + if (handle != NULL) { + DWORD dwExitStatus; + + GetExitCodeProcess(handle, &dwExitStatus); + CloseHandle(handle); // Ignore return code + ret = (dwExitStatus == STILL_ACTIVE); + } + return ret; +} + +/** + * Assemble a 64 bit value from two 32 bit values. + */ +static jlong jlong_from(jint high, jint low) { + jlong result = 0; + result = ((jlong)high << 32) | ((0x000000000ffffffff) & (jlong)low); + return result; +} + +/* + * Fill in the Info object from the OS information about the process. + * + * Class: java_lang_ProcessHandleImpl + * Method: info0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_java_lang_ProcessHandleImpl_00024Info_info0 + (JNIEnv *env, jobject jinfo, jlong jpid) { + DWORD pid = (DWORD)jpid; + int ret = 0; + HANDLE handle = + OpenProcess(THREAD_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, + FALSE, pid); + if (handle == NULL) { + return; + } + getStatInfo(env, handle, jinfo); + getCmdlineInfo(env, handle, jinfo); + procToUser(env, handle, jinfo); + + CloseHandle(handle); // Ignore return code +} + +/** + * Read /proc//stat and fill in the fields of the Info object. + * The executable name, plus the user, system, and start times are gathered. + */ +static void getStatInfo(JNIEnv *env, HANDLE handle, jobject jinfo) { + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + jlong userTime; // nanoseconds + jlong totalTime; // nanoseconds + jlong startTime; // nanoseconds + UserTime.dwHighDateTime = 0; + UserTime.dwLowDateTime = 0; + KernelTime.dwHighDateTime = 0; + KernelTime.dwLowDateTime = 0; + CreationTime.dwHighDateTime = 0; + CreationTime.dwLowDateTime = 0; + + if (GetProcessTimes(handle, &CreationTime, &ExitTime, &KernelTime, &UserTime)) { + userTime = jlong_from(UserTime.dwHighDateTime, UserTime.dwLowDateTime); + totalTime = jlong_from( KernelTime.dwHighDateTime, KernelTime.dwLowDateTime); + totalTime = (totalTime + userTime) * 100; // convert sum to nano-seconds + + startTime = jlong_from(CreationTime.dwHighDateTime, + CreationTime.dwLowDateTime) / 10000; + startTime -= 11644473600000L; // Rebase Epoch from 1601 to 1970 + + (*env)->SetLongField(env, jinfo, + ProcessHandleImpl_Info_totalTimeID, totalTime); + JNU_CHECK_EXCEPTION(env); + (*env)->SetLongField(env, jinfo, + ProcessHandleImpl_Info_startTimeID, startTime); + JNU_CHECK_EXCEPTION(env); + } +} + +static void getCmdlineInfo(JNIEnv *env, HANDLE handle, jobject jinfo) { + char exeName[1024]; + int bufsize = sizeof exeName; + jstring commandObj; + + if (QueryFullProcessImageName(handle, 0, exeName, &bufsize)) { + commandObj = (*env)->NewStringUTF(env, exeName); + CHECK_NULL(commandObj); + (*env)->SetObjectField(env, jinfo, + ProcessHandleImpl_Info_commandID, commandObj); + } +} + +static void procToUser( JNIEnv *env, HANDLE handle, jobject jinfo) { +#define TOKEN_LEN 256 + DWORD token_len = TOKEN_LEN; + char token_buf[TOKEN_LEN]; + TOKEN_USER *token_user = (TOKEN_USER*)token_buf; + HANDLE tokenHandle; + WCHAR domain[255]; + WCHAR name[255]; + DWORD domainLen = sizeof(domain); + DWORD nameLen = sizeof(name); + SID_NAME_USE use; + jstring s; + int ret; + + if (!OpenProcessToken(handle, TOKEN_READ, &tokenHandle)) { + return; + } + + ret = GetTokenInformation(tokenHandle, TokenUser, token_user, + token_len, &token_len); + CloseHandle(tokenHandle); // always close handle + if (!ret) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "GetTokenInformation"); + return; + } + + if (LookupAccountSidW(NULL, token_user->User.Sid, &name[0], &nameLen, + &domain[0], &domainLen, &use) == 0) { + // Name not available + return; + } + + s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name)); + CHECK_NULL(s); + (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, s); +} diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index 04b93eb694f..b8b7dc5f3e4 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -12,7 +12,7 @@ keys=2d dnd i18n intermittent randomness # Tests that must run in othervm mode -othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation +othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation java/lang/ProcessHandle # Tests that cannot run concurrently exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream javax/rmi diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index 7977c7ff9d2..585f6764d3f 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -1175,13 +1175,13 @@ public class Basic { equal(actualPid, expectedPid); // Test the default implementation of Process.getPid - try { - DelegatingProcess p = new DelegatingProcess(null); - p.getPid(); - fail("non-overridden Process.getPid method should throw UOE"); - } catch (UnsupportedOperationException uoe) { - // correct - } + DelegatingProcess p = new DelegatingProcess(null); + THROWS(UnsupportedOperationException.class, + () -> p.getPid(), + () -> p.toHandle(), + () -> p.supportsNormalTermination(), + () -> p.children(), + () -> p.allChildren()); } @@ -2604,7 +2604,7 @@ public class Basic { static volatile int passed = 0, failed = 0; static void pass() {passed++;} static void fail() {failed++; Thread.dumpStack();} - static void fail(String msg) {System.out.println(msg); fail();} + static void fail(String msg) {System.err.println(msg); fail();} static void unexpected(Throwable t) {failed++; t.printStackTrace();} static void check(boolean cond) {if (cond) pass(); else fail();} static void check(boolean cond, String m) {if (cond) pass(); else fail(m);} diff --git a/jdk/test/java/lang/ProcessHandle/Basic.java b/jdk/test/java/lang/ProcessHandle/Basic.java new file mode 100644 index 00000000000..3df63e945ee --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/Basic.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014, 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. + */ + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.io.IOException; +import java.util.Optional; +import java.util.List; +import java.util.stream.Collectors; + +import org.testng.TestNG; +import org.testng.annotations.Test; + +/* + * @test + * @summary Basic tests for ProcessHandler + * @author Roger Riggs + */ +public class Basic { + /** + * Tests of ProcessHandle.current. + */ + @Test + public static void test1() { + try { + ProcessHandle self = ProcessHandle.current(); + ProcessHandle self1 = ProcessHandle.current(); + assertEquals(self, self1); //, "get pid twice should be same %d: %d"); + } finally { + // Cleanup any left over processes + ProcessHandle.current().children().forEach(ProcessHandle::destroy); + } + } + + /** + * Tests of ProcessHandle.get. + */ + @Test + public static void test2() { + try { + ProcessHandle self = ProcessHandle.current(); + long pid = self.getPid(); // known native process id + Optional self1 = ProcessHandle.of(pid); + assertEquals(self1.get(), self, + "ProcessHandle.of(x.getPid()) should be equal getPid() %d: %d"); + + Optional ph = ProcessHandle.of(pid); + assertEquals(pid, ph.get().getPid()); + } finally { + // Cleanup any left over processes + ProcessHandle.current().children().forEach(ProcessHandle::destroy); + } + } + + @Test + public static void test3() { + // Test can get parent of current + ProcessHandle ph = ProcessHandle.current(); + try { + Optional pph = ph.parent(); + assertTrue(pph.isPresent(), "Current has a Parent"); + } finally { + // Cleanup any left over processes + ProcessHandle.current().children().forEach(ProcessHandle::destroy); + } + } + + @Test + public static void test4() { + try { + Process p = new ProcessBuilder("sleep", "0").start(); + p.waitFor(); + + long deadPid = p.getPid(); + p = null; // Forget the process + + Optional t = ProcessHandle.of(deadPid); + assertFalse(t.isPresent(), "Handle created for invalid pid:" + t); + } catch (IOException | InterruptedException ex) { + fail("Unexpected exception", ex); + } finally { + // Cleanup any left over processes + ProcessHandle.current().children().forEach(ProcessHandle::destroy); + } + } + + @Test + public static void test5() { + // Always contains itself. + ProcessHandle current = ProcessHandle.current(); + List list = ProcessHandle.allProcesses().collect(Collectors.toList()); + if (!list.stream() + .anyMatch(ph -> ph.equals(ProcessHandle.current()))) { + System.out.printf("current: %s%n", current); + System.out.printf("all processes.size: %d%n", list.size()); + list.forEach(p -> ProcessUtil.printProcess(p, " allProcesses: ")); + fail("current process not found in all processes"); + } + } + + @Test(expectedExceptions = IllegalStateException.class) + public static void test6() { + ProcessHandle.current().onExit(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public static void test7() { + ProcessHandle.current().destroyForcibly(); + } + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + public static void main(String[] args) { + Class[] testclass = {TreeTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } + +} diff --git a/jdk/test/java/lang/ProcessHandle/InfoTest.java b/jdk/test/java/lang/ProcessHandle/InfoTest.java new file mode 100644 index 00000000000..3aa3a438e6b --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2014, 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. + */ + +import java.io.File; +import java.io.BufferedReader; +import java.io.IOException; +import java.lang.ProcessBuilder; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Random; +import java.util.Scanner; +import java.util.StringTokenizer; +import java.util.concurrent.TimeUnit; + +import jdk.testlibrary.Platform; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.TestNG; + +/* + * @test + * @library /lib/testlibrary + * @summary Functions of ProcessHandle.Info + * @author Roger Riggs + */ + +public class InfoTest { + + static String whoami; + + static { + ProcessBuilder pb = new ProcessBuilder("whoami"); + String fullName; + try { + fullName = new Scanner(pb.start().getInputStream()).nextLine(); + StringTokenizer st = new StringTokenizer(fullName, "\\"); + while (st.hasMoreTokens()) { + whoami = st.nextToken(); + } + System.out.printf("whoami: %s, user.name: %s%n", whoami, System.getProperty("user.name")); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + public static void main(String[] args) { + Class[] testclass = {InfoTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } + + /** + * Test that cputime used shows up in ProcessHandle.info + */ + @Test + public static void test1() { + System.out.println("Note: when run in samevm mode the cputime of the " + + "test runner is included."); + ProcessHandle self = ProcessHandle.current(); + + Duration somecpu = Duration.ofMillis(200L); + Instant end = Instant.now().plus(somecpu); + while (Instant.now().isBefore(end)) { + // waste the cpu + } + ProcessHandle.Info info = self.info(); + System.out.printf(" info: %s%n", info); + Optional totalCpu = info.totalCpuDuration(); + if (totalCpu.isPresent() && (totalCpu.get().compareTo(somecpu) < 0)) { + Assert.fail("reported cputime less than expected: " + somecpu + ", " + + "actual: " + info.totalCpuDuration()); + } + } + + /** + * Spawn a child with arguments and check they are visible via the ProcessHandle. + */ + @Test + public static void test2() { + try { + long cpulooptime = 1 << 8; + String[] extraArgs = {"pid", "parent", "stdin"}; + Instant beforeStart = Instant.now().truncatedTo(ChronoUnit.SECONDS); + JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs); + Instant afterStart = Instant.now(); + + try (BufferedReader lines = p1.outputReader()) { + Duration lastCpu = Duration.ofMillis(0L); + for (int j = 0; j < 20; j++) { + + p1.sendAction("cpuloop", cpulooptime); + p1.sendAction("cputime", ""); + + // Read cputime from child + Duration childCpuTime = null; + // Read lines from the child until the result from cputime is returned + String s; + while ((s = lines.readLine()) != null) { + String[] split = s.trim().split(" "); + if (split.length == 3 && split[1].equals("cputime")) { + long nanos = Long.valueOf(split[2]); + childCpuTime = Duration.ofNanos(nanos); + break; // found the result we're looking for + } + } + + + ProcessHandle.Info info = p1.info(); + System.out.printf(" info: %s%n", info); + + if (info.user().isPresent()) { + String user = info.user().get(); + Assert.assertNotNull(user, "User name"); + Assert.assertEquals(user, whoami, "User name"); + } + + Optional command = info.command(); + if (command.isPresent()) { + String javaExe = System.getProperty("test.jdk") + + File.separator + "bin" + File.separator + "java"; + String expected = Platform.isWindows() ? javaExe + ".exe" : javaExe; + Assert.assertEquals(command.get(), expected, + "Command: expected: 'java'" + ", actual: " + command); + } + + if (info.arguments().isPresent()) { + String[] args = info.arguments().get(); + + if (Platform.isLinux() || Platform.isOSX()) { + int offset = args.length - extraArgs.length; + for (int i = 0; i < extraArgs.length; i++) { + Assert.assertEquals(args[offset + i], extraArgs[i], + "Actual argument mismatch, index: " + i); + } + } else if (Platform.isSolaris()) { + Assert.assertEquals(args.length, 1, + "Expected argument list length: 1"); + Assert.assertNotNull(args[0], + "Expected an argument"); + } else { + System.out.printf("No argument test for OS: %s%n", Platform.getOsName()); + } + + // Now check that the first argument is not the same as the executed command + if (args.length > 0) { + Assert.assertNotEquals(args[0], command, + "First argument should not be the executable: args[0]: " + + args[0] + ", command: " + command); + } + } + + if (info.totalCpuDuration().isPresent()) { + Duration totalCPU = info.totalCpuDuration().get(); + Duration epsilon = Duration.ofMillis(200L); + Assert.assertTrue(totalCPU.toNanos() > 0L, + "total cpu time expected > 0ms, actual: " + totalCPU); + Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + 10_000_000_000L, + "total cpu time expected < 10s more than previous iteration, actual: " + totalCPU); + if (childCpuTime != null) { + System.out.printf(" info.totalCPU: %s, childCpuTime: %s, diff: %s%n", + totalCPU.toNanos(), childCpuTime.toNanos(), childCpuTime.toNanos() - totalCPU.toNanos()); + Assert.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon), + childCpuTime + " should be within " + + epsilon + " of " + totalCPU); + } + lastCpu = totalCPU; + } + + if (info.startInstant().isPresent()) { + Instant startTime = info.startInstant().get(); + Assert.assertTrue(startTime.isBefore(afterStart), + "startTime after process spawn completed" + + startTime + " + > " + afterStart); + } + } + } + p1.waitFor(5, TimeUnit.SECONDS); + } catch (IOException | InterruptedException ie) { + ie.printStackTrace(System.out); + Assert.fail("unexpected exception", ie); + } + } + + /** + * Spawn a child with arguments and check they are visible via the ProcessHandle. + */ + @Test + public static void test3() { + try { + for (int sleepTime : Arrays.asList(1, 2)) { + Process p = spawn("sleep", String.valueOf(sleepTime)); + ProcessHandle.Info info = p.info(); + System.out.printf(" info: %s%n", info); + + if (info.user().isPresent()) { + String user = info.user().get(); + Assert.assertNotNull(user); + Assert.assertEquals(user, whoami); + } + if (info.command().isPresent()) { + String command = info.command().get(); + String expected = Platform.isWindows() ? "sleep.exe" : "sleep"; + Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" + + expected + "\', actual: " + command); + + // Verify the command exists and is executable + File exe = new File(command); + Assert.assertTrue(exe.exists(), "command must exist: " + exe); + Assert.assertTrue(exe.canExecute(), "command must be executable: " + exe); + } + if (info.arguments().isPresent()) { + String[] args = info.arguments().get(); + if (args.length > 0) { + Assert.assertEquals(args[0], String.valueOf(sleepTime)); + } + } + Assert.assertTrue(p.waitFor(15, TimeUnit.SECONDS)); + } + } catch (IOException | InterruptedException ex) { + ex.printStackTrace(System.out);; + } finally { + // Destroy any children that still exist + ProcessUtil.destroyProcessTree(ProcessHandle.current()); + } + } + + /** + * Cross check the cputime reported from java.management with that for the current process. + */ + @Test + public static void test4() { + Duration myCputime1 = ProcessUtil.MXBeanCpuTime(); + + Optional dur1 = ProcessHandle.current().info().totalCpuDuration(); + + Duration myCputime2 = ProcessUtil.MXBeanCpuTime(); + + Optional dur2 = ProcessHandle.current().info().totalCpuDuration(); + + if (dur1.isPresent() && dur2.isPresent()) { + Duration total1 = dur1.get(); + Duration total2 = dur2.get(); ; + System.out.printf(" total1 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n", + Objects.toString(total1), myCputime1, myCputime1.minus(total1)); + System.out.printf(" total2 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n", + Objects.toString(total2), myCputime2, myCputime2.minus(total2)); + + Duration epsilon = Duration.ofMillis(200L); // Epsilon is 200ms. + Assert.assertTrue(checkEpsilon(myCputime1, myCputime2, epsilon), + myCputime1.toNanos() + " should be within " + epsilon + + " of " + myCputime2.toNanos()); + Assert.assertTrue(checkEpsilon(total1, total2, epsilon), + total1.toNanos() + " should be within " + epsilon + + " of " + total2.toNanos()); + Assert.assertTrue(checkEpsilon(myCputime1, total1, epsilon), + myCputime1.toNanos() + " should be within " + epsilon + + " of " + total1.toNanos()); + Assert.assertTrue(checkEpsilon(total1, myCputime2, epsilon), + total1.toNanos() + " should be within " + epsilon + + " of " + myCputime2.toNanos()); + Assert.assertTrue(checkEpsilon(myCputime2, total2, epsilon), + myCputime2.toNanos() + " should be within " + epsilon + + " of " + total2.toNanos()); + } + } + + @Test + public static void test5() { + ProcessHandle self = ProcessHandle.current(); + Random r = new Random(); + for (int i = 0; i < 30; i++) { + Instant end = Instant.now().plusMillis(500L); + while (end.isBefore(Instant.now())) { + // burn the cpu time checking the time + long x = r.nextLong(); + } + if (self.info().totalCpuDuration().isPresent()) { + Duration totalCpu = self.info().totalCpuDuration().get(); + long infoTotalCputime = totalCpu.toNanos(); + long beanCputime = ProcessUtil.MXBeanCpuTime().toNanos(); + System.out.printf(" infoTotal: %12d, beanCpu: %12d, diff: %12d%n", + infoTotalCputime, beanCputime, beanCputime - infoTotalCputime); + } else { + break; // nothing to compare; continue + } + } + } + /** + * Check two Durations, the second should be greater than the first or + * within the supplied Epsilon. + * @param d1 a Duration - presumed to be shorter + * @param d2 a 2nd Duration - presumed to be greater (or within Epsilon) + * @param epsilon Epsilon the amount of overlap allowed + * @return + */ + static boolean checkEpsilon(Duration d1, Duration d2, Duration epsilon) { + if (d1.toNanos() <= d2.toNanos()) { + return true; + } + Duration diff = d1.minus(d2).abs(); + return diff.compareTo(epsilon) <= 0; + } + + /** + * Spawn a native process with the provided arguments. + * @param command the executable of native process + * @args + * @return the Process that was started + * @throws IOException thrown by ProcessBuilder.start + */ + static Process spawn(String command, String... args) throws IOException { + ProcessBuilder pb = new ProcessBuilder(); + pb.inheritIO(); + List list = new ArrayList<>(); + list.add(command); + for (String arg : args) + list.add(arg); + pb.command(list); + return pb.start(); + } +} diff --git a/jdk/test/java/lang/ProcessHandle/JavaChild.java b/jdk/test/java/lang/ProcessHandle/JavaChild.java new file mode 100644 index 00000000000..0aed8343242 --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2014, 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. + */ + +import com.sun.management.OperatingSystemMXBean; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintStream; +import java.io.Reader; +import java.io.PrintWriter; +import java.lang.InterruptedException; +import java.lang.Override; +import java.lang.management.ManagementFactory; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + + +/** + * Command driven subprocess with useful child functions. + */ +public class JavaChild extends Process { + +private static volatile int commandSeq = 0; // Command sequence number + private static final ProcessHandle self = ProcessHandle.current(); + private static int finalStatus = 0; + private static final List children = new ArrayList<>(); + private static final Set completedChildren = + Collections.synchronizedSet(new HashSet<>()); + + private final Process delegate; + private final PrintWriter inputWriter; + private final BufferedReader outputReader; + + + /** + * Create a JavaChild control instance that delegates to the spawned process. + * {@link #sendAction} is used to send commands via the processes stdin. + * {@link #forEachOutputLine} can be used to process output from the child + * @param delegate the process to delegate and send commands to and get responses from + */ + private JavaChild(Process delegate) { + this.delegate = delegate; + // Initialize PrintWriter with autoflush (on println) + inputWriter = new PrintWriter(delegate.getOutputStream(), true); + outputReader = new BufferedReader(new InputStreamReader(delegate.getInputStream())); + } + + @Override + public void destroy() { + delegate.destroy(); + } + + @Override + public int exitValue() { + return delegate.exitValue(); + } + + @Override + public int waitFor() throws InterruptedException { + return delegate.waitFor(); + } + + @Override + public OutputStream getOutputStream() { + return delegate.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return delegate.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return delegate.getErrorStream(); + } + + @Override + public ProcessHandle toHandle() { + return delegate.toHandle(); + } + + @Override + public CompletableFuture onExit() { + return delegate.onExit(); + } + @Override + public String toString() { + return "delegate: " + delegate.toString(); + } + + public CompletableFuture onJavaChildExit() { + return onExit().thenApply(ph -> this); + } + + /** + * Send an action and arguments to the child via stdin. + * @param action the action + * @param args additional arguments + * @throws IOException if something goes wrong writing to the child + */ + void sendAction(String action, Object... args) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append(action); + for (Object arg :args) { + sb.append(" "); + sb.append(arg); + } + String cmd = sb.toString(); + synchronized (this) { + inputWriter.println(cmd); + } + } + + public BufferedReader outputReader() { + return outputReader; + } + + /** + * Asynchronously evaluate each line of output received back from the child process. + * @param consumer a Consumer of each line read from the child + * @return a CompletableFuture that is completed when the child closes System.out. + */ + CompletableFuture forEachOutputLine(Consumer consumer) { + final CompletableFuture future = new CompletableFuture<>(); + String name = "OutputLineReader-" + getPid(); + Thread t = new Thread(() -> { + try (BufferedReader reader = outputReader()) { + String line; + while ((line = reader.readLine()) != null) { + consumer.accept(line); + } + } catch (IOException | RuntimeException ex) { + consumer.accept("IOE (" + getPid() + "):" + ex.getMessage()); + future.completeExceptionally(ex); + } + future.complete("success"); + }, name); + t.start(); + return future; + } + + /** + * Spawn a JavaChild with the provided arguments. + * Commands can be send to the child with {@link #sendAction}. + * Output lines from the child can be processed with {@link #forEachOutputLine}. + * System.err is set to inherit and is the unstructured async logging + * output for all subprocesses. + * @param args the command line arguments to JavaChild + * @return the JavaChild that was started + * @throws IOException thrown by ProcessBuilder.start + */ + static JavaChild spawnJavaChild(Object... args) throws IOException { + String[] stringArgs = new String[args.length]; + for (int i = 0; i < args.length; i++) { + stringArgs[i] = args[i].toString(); + } + ProcessBuilder pb = build(stringArgs); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + return new JavaChild(pb.start()); + } + + /** + * Spawn a JavaChild with the provided arguments. + * Sets the process to inherit the I/O channels. + * @param args the command line arguments to JavaChild + * @return the Process that was started + * @throws IOException thrown by ProcessBuilder.start + */ + static Process spawn(String... args) throws IOException { + ProcessBuilder pb = build(args); + pb.inheritIO(); + return pb.start(); + } + + /** + * Return a ProcessBuilder with the javaChildArgs and + * any additional supplied args. + * + * @param args the command line arguments to JavaChild + * @return the ProcessBuilder + */ + static ProcessBuilder build(String ... args) { + ProcessBuilder pb = new ProcessBuilder(); + List list = new ArrayList<>(javaChildArgs); + for (String arg : args) + list.add(arg); + pb.command(list); + return pb; + } + + static final String javaHome = (System.getProperty("test.jdk") != null) + ? System.getProperty("test.jdk") + : System.getProperty("java.home"); + + static final String javaExe = + javaHome + File.separator + "bin" + File.separator + "java"; + + static final String classpath = + System.getProperty("java.class.path"); + + static final List javaChildArgs = + Arrays.asList(javaExe, + "-XX:+DisplayVMOutputToStderr", + "-Dtest.jdk=" + javaHome, + "-classpath", absolutifyPath(classpath), + "JavaChild"); + + private static String absolutifyPath(String path) { + StringBuilder sb = new StringBuilder(); + for (String file : path.split(File.pathSeparator)) { + if (sb.length() != 0) + sb.append(File.pathSeparator); + sb.append(new File(file).getAbsolutePath()); + } + return sb.toString(); + } + + /** + * Main program that interprets commands from the command line args or stdin. + * Each command produces output to stdout confirming the command and + * providing results. + * System.err is used for unstructured information. + * @param args an array of strings to be interpreted as commands; + * each command uses additional arguments as needed + */ + public static void main(String[] args) { + System.out.printf("args: %s %s%n", ProcessHandle.current(), Arrays.toString(args)); + interpretCommands(args); + System.exit(finalStatus); + } + + /** + * Interpret an array of strings as a command line. + * @param args an array of strings to be interpreted as commands; + * each command uses additional arguments as needed + */ + private static void interpretCommands(String[] args) { + try { + int nextArg = 0; + while (nextArg < args.length) { + String action = args[nextArg++]; + switch (action) { + case "help": + sendResult(action, ""); + help(); + break; + case "sleep": + int millis = Integer.valueOf(args[nextArg++]); + Thread.sleep(millis); + sendResult(action, Integer.toString(millis)); + break; + case "cpuloop": + long times = Long.valueOf(args[nextArg++]); + Instant end = Instant.now().plusMillis(times); + while (Instant.now().isBefore(end)) { + // burn the cpu til the time is up + } + sendResult(action, times); + break; + case "cputime": + sendResult(action, getCpuTime()); + break; + case "out": + case "err": + String value = args[nextArg++]; + sendResult(action, value); + if (action.equals("err")) { + System.err.println(value); + } + break; + case "stdin": + // Read commands from stdin; at eof, close stdin of + // children and wait for each to exit + sendResult(action, "start"); + try (Reader reader = new InputStreamReader(System.in); + BufferedReader input = new BufferedReader(reader)) { + String line; + while ((line = input.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty()) { + String[] split = line.split("\\s"); + interpretCommands(split); + } + } + // EOF on stdin, close stdin on all spawned processes + for (JavaChild p : children) { + try { + p.getOutputStream().close(); + } catch (IOException ie) { + sendResult("stdin_closing", p.getPid(), + "exception", ie.getMessage()); + } + } + + for (JavaChild p : children) { + do { + try { + p.waitFor(); + break; + } catch (InterruptedException e) { + // retry + } + } while (true); + } + // Wait for all children to be gone + Instant timeOut = Instant.now().plusSeconds(10L); + while (!completedChildren.containsAll(children)) { + if (Instant.now().isBefore(timeOut)) { + Thread.sleep(100L); + } else { + System.err.printf("Timeout waiting for " + + "children to terminate%n"); + children.removeAll(completedChildren); + for (JavaChild c : children) { + sendResult("stdin_noterm", c.getPid()); + System.err.printf(" Process not terminated: " + + "pid: %d%n", c.getPid()); + } + System.exit(2); + } + } + } + sendResult(action, "done"); + return; // normal exit from JavaChild Process + case "parent": + sendResult(action, self.parent().toString()); + break; + case "pid": + sendResult(action, self.toString()); + break; + case "exit": + int exitValue = (nextArg < args.length) + ? Integer.valueOf(args[nextArg]) : 0; + sendResult(action, exitValue); + System.exit(exitValue); + break; + case "spawn": { + if (args.length - nextArg < 2) { + throw new RuntimeException("not enough args for respawn: " + + (args.length - 2)); + } + // Spawn as many children as requested and + // pass on rest of the arguments + int ncount = Integer.valueOf(args[nextArg++]); + Object[] subargs = new String[args.length - nextArg]; + System.arraycopy(args, nextArg, subargs, 0, subargs.length); + for (int i = 0; i < ncount; i++) { + JavaChild p = spawnJavaChild(subargs); + sendResult(action, p.getPid()); + p.forEachOutputLine(JavaChild::sendRaw); + p.onJavaChildExit().thenAccept((p1) -> { + int excode = p1.exitValue(); + sendResult("child_exit", p1.getPid(), excode); + completedChildren.add(p1); + }); + children.add(p); // Add child to spawned list + } + nextArg = args.length; + break; + } + case "child": { + // Send the command to all the live children; + // ignoring those that are not alive + int sentCount = 0; + Object[] result = + Arrays.copyOfRange(args, nextArg - 1, args.length); + Object[] subargs = + Arrays.copyOfRange(args, nextArg + 1, args.length); + for (JavaChild p : children) { + if (p.isAlive()) { + sentCount++; + // overwrite with current pid + result[0] = Long.toString(p.getPid()); + sendResult(action, result); + p.sendAction(args[nextArg], subargs); + } + } + if (sentCount == 0) { + sendResult(action, "n/a"); + } + nextArg = args.length; + break; + } + case "child_eof" : + // Close the InputStream of all the live children; + // ignoring those that are not alive + for (JavaChild p : children) { + if (p.isAlive()) { + sendResult(action, p.getPid()); + p.getOutputStream().close(); + } + } + break; + case "property": + String name = args[nextArg++]; + sendResult(action, name, System.getProperty(name)); + break; + case "threaddump": + Thread.dumpStack(); + break; + default: + throw new Error("JavaChild action unknown: " + action); + } + } + } catch (Throwable t) { + t.printStackTrace(System.err); + System.exit(1); + } + } + + static synchronized void sendRaw(String s) { + System.out.println(s); + System.out.flush(); + } + static void sendResult(String action, Object... results) { + sendRaw(new Event(action, results).toString()); + } + + static long getCpuTime() { + OperatingSystemMXBean osMbean = + (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean(); + return osMbean.getProcessCpuTime(); + } + + /** + * Print command usage to stderr. + */ + private static void help() { + System.err.println("Commands:"); + System.err.println(" help"); + System.err.println(" pid"); + System.err.println(" parent"); + System.err.println(" cpuloop "); + System.err.println(" cputime"); + System.err.println(" stdin - read commands from stdin"); + System.err.println(" sleep "); + System.err.println(" spawn command... - spawn n new children and send command"); + System.err.println(" child command... - send command to all live children"); + System.err.println(" child_eof - send eof to all live children"); + System.err.println(" exit "); + System.err.println(" out arg..."); + System.err.println(" err arg..."); + } + + static class Event { + long pid; + long seq; + String command; + Object[] results; + Event(String command, Object... results) { + this(self.getPid(), ++commandSeq, command, results); + } + Event(long pid, int seq, String command, Object... results) { + this.pid = pid; + this.seq = seq; + this.command = command; + this.results = results; + } + + /** + * Create a String encoding the pid, seq, command, and results. + * + * @return a String formatted to send to the stream. + */ + String format() { + StringBuilder sb = new StringBuilder(); + sb.append(pid); + sb.append(":"); + sb.append(seq); + sb.append(" "); + sb.append(command); + for (int i = 0; i < results.length; i++) { + sb.append(" "); + sb.append(results[i]); + } + return sb.toString(); + } + + Event(String encoded) { + String[] split = encoded.split("\\s"); + String[] pidSeq = split[0].split(":"); + pid = Long.valueOf(pidSeq[0]); + seq = Integer.valueOf(pidSeq[1]); + command = split[1]; + Arrays.copyOfRange(split, 1, split.length); + } + + public String toString() { + return format(); + } + + } +} diff --git a/jdk/test/java/lang/ProcessHandle/OnExitTest.java b/jdk/test/java/lang/ProcessHandle/OnExitTest.java new file mode 100644 index 00000000000..98e6b9c3b39 --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014, 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. + */ + +import java.io.IOException; +import java.lang.InterruptedException; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import jdk.testlibrary.Platform; +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.TestNG; + +/* + * @test + * @library /lib/testlibrary + * @summary Functions of Process.onExit and ProcessHandle.onExit + * @author Roger Riggs + */ + +public class OnExitTest extends ProcessUtil { + + @SuppressWarnings("raw_types") + public static void main(String[] args) { + Class[] testclass = { OnExitTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } + + /** + * Basic test of exitValue and onExit. + */ + @Test + public static void test1() { + try { + int[] exitValues = {0, 1, 10}; + for (int value : exitValues) { + Process p = JavaChild.spawn("exit", Integer.toString(value)); + CompletableFuture future = p.onExit(); + future.thenAccept( (ph) -> { + int actualExitValue = ph.exitValue(); + printf(" javaChild done: %s, exitStatus: %d%n", + ph, actualExitValue); + Assert.assertEquals(actualExitValue, value, "actualExitValue incorrect"); + Assert.assertEquals(ph, p, "Different Process passed to thenAccept"); + }); + + Process h = future.get(); + Assert.assertEquals(h, p); + Assert.assertEquals(p.exitValue(), value); + Assert.assertFalse(p.isAlive(), "Process should not be alive"); + p.waitFor(); + } + } catch (IOException | InterruptedException | ExecutionException ex) { + Assert.fail(ex.getMessage(), ex); + } finally { + destroyProcessTree(ProcessHandle.current()); + } + } + + /** + * Test of Completion handler when parent is killed. + * Spawn 1 child to spawn 3 children each with 2 children. + */ + @Test + public static void test2() { + try { + ConcurrentHashMap processes = new ConcurrentHashMap<>(); + List children = getChildren(ProcessHandle.current()); + children.forEach(ProcessUtil::printProcess); + Assert.assertEquals(children.size(), 0, + "Expected to start with zero children; " + children); + + JavaChild proc = JavaChild.spawnJavaChild("stdin"); + ProcessHandle procHandle = proc.toHandle(); + printf(" spawned: %d%n", proc.getPid()); + + proc.forEachOutputLine((s) -> { + String[] split = s.trim().split(" "); + if (split.length == 3 && split[1].equals("spawn")) { + Long child = Long.valueOf(split[2]); + Long parent = Long.valueOf(split[0].split(":")[0]); + processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); + } + }); + + proc.sendAction("spawn", "3", "stdin"); + + proc.sendAction("child", "spawn", "2", "stdin"); + + // Poll until all 9 child processes exist or the timeout is reached + int expected = 9; + Instant endTimeout = Instant.now().plusSeconds(10L); + do { + Thread.sleep(200L); + printf(" subprocess count: %d, waiting for %d%n", processes.size(), expected); + } while (processes.size() < expected && + Instant.now().isBefore(endTimeout)); + + children = getAllChildren(procHandle); + + ArrayBlockingQueue completions = new ArrayBlockingQueue<>(expected + 1); + Instant startTime = Instant.now(); + // Create a future for each of the 9 children + processes.forEach( (p, parent) -> { + p.onExit().whenComplete((ph, ex) -> { + Duration elapsed = Duration.between(startTime, Instant.now()); + completions.add(ph); + printf("whenComplete: pid: %s, exception: %s, thread: %s, elapsed: %s%n", + ph, ex, Thread.currentThread(), elapsed); + }); + }); + + // Check that each of the spawned processes is included in the children + List remaining = new ArrayList<>(children); + processes.forEach((p, parent) -> { + Assert.assertTrue(remaining.remove(p), "spawned process should have been in children"); + }); + + // Remove Win32 system spawned conhost.exe processes + remaining.removeIf(ProcessUtil::isWindowsConsole); + + remaining.forEach(p -> printProcess(p, "unexpected: ")); + if (remaining.size() > 0) { + // Show full list for debugging + ProcessUtil.logTaskList(); + } + + proc.destroy(); // kill off the parent + proc.waitFor(); + + // Wait for all the processes to be completed + processes.forEach((p, parent) -> { + try { + p.onExit().get(); + } catch (InterruptedException | ExecutionException ex) { + // ignore + } + }); + + // Verify that all 9 exit handlers were called + processes.forEach((p, parent) -> + Assert.assertTrue(completions.contains(p), "Child onExit not called: " + p + + ", parent: " + parent + + ": " + p.info())); + + // Show the status of the original children + children.forEach(p -> printProcess(p, "after onExit:")); + + Assert.assertEquals(proc.isAlive(), false, "destroyed process is alive:: %s%n" + proc); + + List children2 = getAllChildren(procHandle); + printf(" children2: %s%n", children2.toString()); + Assert.assertEquals(children2.size(), 0, "After onExit, expected no children"); + + Assert.assertEquals(remaining.size(), 0, "Unaccounted for children"); + + } catch (IOException | InterruptedException ex) { + Assert.fail(ex.getMessage()); + } finally { + destroyProcessTree(ProcessHandle.current()); + } + } + +} diff --git a/jdk/test/java/lang/ProcessHandle/PermissionTest.java b/jdk/test/java/lang/ProcessHandle/PermissionTest.java new file mode 100644 index 00000000000..863f421afd7 --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/PermissionTest.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 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. + */ + +import java.io.FilePermission; +import java.io.IOException; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.security.SecurityPermission; +import java.util.Arrays; +import java.util.Optional; +import java.util.PropertyPermission; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +public class PermissionTest { + /** + * Backing up policy. + */ + protected static Policy policy; + + /** + * Backing up security manager. + */ + private static SecurityManager sm; + + /** + * Current process handle. + */ + private final ProcessHandle currentHndl; + + PermissionTest() { + policy = Policy.getPolicy(); + sm = System.getSecurityManager(); + currentHndl = ProcessHandle.current(); + } + + @Test + public void allChildrenWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + currentHndl.allChildren(); + } + + @Test + public void allProcessesWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + ProcessHandle.allProcesses(); + } + + @Test + public void childrenWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + currentHndl.children(); + } + + @Test + public void currentWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + ProcessHandle.current(); + } + + @Test + public void ofWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + ProcessHandle.of(0); + } + + @Test + public void parentWithPermission() { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + currentHndl.parent(); + } + + @Test + public void processToHandleWithPermission() throws IOException { + Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess"))); + Process p = null; + try { + ProcessBuilder pb = new ProcessBuilder("sleep", "30"); + p = pb.start(); + ProcessHandle ph = p.toHandle(); + Assert.assertNotNull(ph, "ProcessHandle expected from Process"); + } finally { + if (p != null) { + p.destroy(); + } + } + } + + @BeforeGroups (groups = {"NoManageProcessPermission"}) + public void noPermissionsSetup(){ + Policy.setPolicy(new TestPolicy()); + SecurityManager sm = new SecurityManager(); + System.setSecurityManager(sm); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionAllChildren() { + currentHndl.allChildren(); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionAllProcesses() { + ProcessHandle.allProcesses(); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionChildren() { + currentHndl.children(); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionCurrent() { + ProcessHandle.current(); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionOf() { + ProcessHandle.of(0); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionParent() { + currentHndl.parent(); + } + + @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class) + public void noPermissionProcessToHandle() throws IOException { + Process p = null; + try { + ProcessBuilder pb = new ProcessBuilder("sleep", "30"); + p = pb.start(); + ProcessHandle ph = p.toHandle(); + Assert.assertNotNull(ph, "ProcessHandle expected from Process"); + } finally { + if (p != null) { + p.destroy(); + } + } + } + + @AfterClass + public void tearDownClass() throws Exception { + System.setSecurityManager(sm); + Policy.setPolicy(policy); + } +} + +class TestPolicy extends Policy { + private final PermissionCollection permissions = new Permissions(); + + public TestPolicy() { + setBasicPermissions(); + } + + /* + * Defines the minimal permissions required by testNG and set security + * manager permission when running these tests. + */ + public void setBasicPermissions() { + permissions.add(new SecurityPermission("getPolicy")); + permissions.add(new SecurityPermission("setPolicy")); + permissions.add(new RuntimePermission("getClassLoader")); + permissions.add(new RuntimePermission("setSecurityManager")); + permissions.add(new RuntimePermission("createSecurityManager")); + permissions.add(new PropertyPermission("testng.show.stack.frames", + "read")); + permissions.add(new PropertyPermission("user.dir", "read")); + permissions.add(new PropertyPermission("test.src", "read")); + permissions.add(new PropertyPermission("file.separator", "read")); + permissions.add(new PropertyPermission("line.separator", "read")); + permissions.add(new PropertyPermission("fileStringBuffer", "read")); + permissions.add(new PropertyPermission("dataproviderthreadcount", "read")); + permissions.add(new FilePermission("<>", "execute")); + } + + public TestPolicy(Permission... ps) { + setBasicPermissions(); + Arrays.stream(ps).forEach(p -> permissions.add(p)); + } + + @Override + public PermissionCollection getPermissions(ProtectionDomain domain) { + return permissions; + } + + @Override + public PermissionCollection getPermissions(CodeSource codesource) { + return permissions; + } + + @Override + public boolean implies(ProtectionDomain domain, Permission perm) { + return permissions.implies(perm); + } +} diff --git a/jdk/test/java/lang/ProcessHandle/ProcessUtil.java b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java new file mode 100644 index 00000000000..328012f1a30 --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 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. + */ + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.ProcessBuilder; +import java.time.Duration; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.sun.management.OperatingSystemMXBean; + +import jdk.testlibrary.Platform; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Useful utilities for testing Process and ProcessHandle. + */ +public abstract class ProcessUtil { + /** + * Constructor + */ + public ProcessUtil() {} + + /** + * Returns the list of direct children. + * WIndows conhost.exe children are filtered out. + * @param ph the Process to get children of + * @return a list of child ProcessHandles + */ + public static List getChildren(ProcessHandle ph) { + return ph.children() + .filter(ProcessUtil::isNotWindowsConsole) + .collect(Collectors.toList()); + } + + /** + * Returns the list of all direct and indirect children. + * WIndows conhost.exe children are filtered out. + * @param ph the Process to get children of + * @return a list of child ProcessHandles + */ + public static List getAllChildren(ProcessHandle ph) { + return ph.allChildren() + .filter(ProcessUtil::isNotWindowsConsole) + .collect(Collectors.toList()); + } + + /** + * Waits for and returns the direct expected Children of a ProcessHandle. + * For Windows, the conhost.exe children are filtered out. + * + * @param ph the process to get the children of + * @param nchildren the minimum number of children to expect + * @return a list of ProcessHandles of the children. + */ + public static List waitForChildren(ProcessHandle ph, long nchildren) { + List subprocesses = null; + long count = 0; + do { + if (subprocesses != null) { + // Only wait if this is not the first time looking + try { + Thread.sleep(500L); // It will happen but don't burn the cpu + } catch (InterruptedException ie) { + // ignore + } + } + subprocesses = getChildren(ph); + count = subprocesses.size(); + System.out.printf(" waiting for subprocesses of %s to start," + + " expected: %d, current: %d%n", ph, nchildren, count); + } while (count < nchildren); + return subprocesses; + } + + /** + * Waits for and returns all expected Children of a ProcessHandle. + * For Windows, the conhost.exe children are filtered out. + * + * @param ph the process to get the children of + * @param nchildren the minimum number of children to expect + * @return a list of ProcessHandles of the children. + */ + public static List waitForAllChildren(ProcessHandle ph, long nchildren) { + List subprocesses = null; + long count = 0; + do { + if (subprocesses != null) { + // Only wait if this is not the first time looking + try { + Thread.sleep(500L); // It will happen but don't burn the cpu + } catch (InterruptedException ie) { + // ignore + } + } + subprocesses = getAllChildren(ph); + count = subprocesses.size(); + System.out.printf(" waiting for subprocesses of %s to start," + + " expected: %d, current: %d%n", ph, nchildren, count); + } while (count < nchildren); + return subprocesses; + } + + /** + * Destroy all children of the ProcessHandle. + * (Except the conhost.exe on Windows) + * + * @param p a ProcessHandle + * @return the ProcessHandle + */ + public static ProcessHandle destroyProcessTree(ProcessHandle p) { + Stream children = p.allChildren().filter(ProcessUtil::isNotWindowsConsole); + children.forEach(ph -> { + System.out.printf("destroyProcessTree destroyForcibly%n"); + printProcess(ph); + ph.destroyForcibly(); + }); + return p; + } + + /** + * The OSMXBean for this process. + */ + public static final OperatingSystemMXBean osMbean = + (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + + /** + * Return the CPU time of the current process according to the OperatingSystemMXBean. + * + * @return the CPU time of the current process + */ + public static Duration MXBeanCpuTime() { + return Duration.ofNanos(osMbean.getProcessCpuTime()); + } + + /** + * Return true if the ProcessHandle is a Windows i586 conhost.exe process. + * + * @param p the processHandle of the Process + * @return Return true if the ProcessHandle is for a Windows i586 conhost.exe process + */ + static boolean isWindowsConsole(ProcessHandle p) { + return Platform.isWindows() && p.info().command().orElse("").endsWith("C:\\Windows\\System32\\conhost.exe"); + } + + /** + * Return true if the ProcessHandle is NOT a Windows i586 conhost.exe process. + * + * @param p the processHandle of the Process + * @return Return true if the ProcessHandle is NOT for a Windows i586 conhost.exe process + */ + static boolean isNotWindowsConsole(ProcessHandle p) { + return !isWindowsConsole(p); + } + + /** + * Print a formatted string to System.out. + * @param format the format + * @param args the argument array + */ + static void printf(String format, Object... args) { + String s = String.format(format, args); + System.out.print(s); + } + + /** + * Print information about a process. + * Prints the pid, if it is alive, and information about the process. + * @param ph the processHandle at the top + */ + static void printProcess(ProcessHandle ph) { + printProcess(ph, ""); + } + + /** + * Print information about a process. + * Prints the pid, if it is alive, and information about the process. + * @param ph the processHandle at the top + * @param prefix the String to prefix the output with + */ + static void printProcess(ProcessHandle ph, String prefix) { + printf("%spid %s, alive: %s; parent: %s, %s%n", prefix, + ph.getPid(), ph.isAlive(), ph.parent(), ph.info()); + } + + /** + * Print the process hierarchy as visible via ProcessHandle. + * Prints the pid, if it is alive, and information about the process. + * @param ph the processHandle at the top + * @param prefix the String to prefix the output with + */ + static void printDeep(ProcessHandle ph, String prefix) { + printProcess(ph, prefix); + ph.children().forEach(p -> printDeep(p, prefix + " ")); + } + + /** + * Use the native command to list the active processes. + */ + static void logTaskList() { + String[] windowsArglist = {"tasklist.exe", "/v"}; + String[] unixArglist = {"ps", "-ef"}; + + String[] argList = null; + if (Platform.isWindows()) { + argList = windowsArglist; + } else if (Platform.isLinux() || Platform.isOSX()) { + argList = unixArglist; + } else { + return; + } + + ProcessBuilder pb = new ProcessBuilder(argList); + pb.inheritIO(); + try { + Process proc = pb.start(); + proc.waitFor(); + } catch (IOException | InterruptedException ex) { + ex.printStackTrace(); + } + } +} diff --git a/jdk/test/java/lang/ProcessHandle/ScaleTest.java b/jdk/test/java/lang/ProcessHandle/ScaleTest.java new file mode 100644 index 00000000000..ffd8e61105e --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/ScaleTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import static org.testng.Assert.assertEquals; +import org.testng.TestNG; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @summary Scalibities test for checking scability of ProcessHandle + * @run testng/othervm ScaleTest + */ +public class ScaleTest { + /** + * Scale max processes number to 5000. + */ + private final static int MAX_PROCESSES_LIMIT = 1000; + + /** + * Create test process number as 1, 2, 5, 10, 20, 50, 100, 200... until it reach + * setting process limit. + * @return iterator on how many processes can be created. + * @throws IOException if can't create processes. + */ + @DataProvider + public Iterator processesNumbers() { + // Limit spawn processes number less than total limitation. + + List testProcesses = new ArrayList<>(); + int i = 1, j = 0; + while (i <= MAX_PROCESSES_LIMIT) { + testProcesses.add(new Object[]{i}); + if ((j % 3) != 1) + i *= 2; + else + i = i * 25 / 10; + j++; + } + return testProcesses.iterator(); + } + + /** + * Start process by given number, compare created processes with + * ProcessHandle.children by order. + * @param processNum processes number that will be created + */ + @Test(dataProvider = "processesNumbers") + public void scaleProcesses(int processNum) { + try { + ProcessBuilder pb = new ProcessBuilder(); + pb.command("sleep", "600"); + List children = new ArrayList<>(); + + int createdProcessNum = 0; + for (int i = 0; i < processNum; i++) { + try { + children.add(pb.start().toHandle()); + createdProcessNum++; + } catch (Throwable ignore) { + // Hard to control how many processes we can generate. + // Ignore every error when create new process + } + } + List phs = ProcessHandle.current().allChildren() + .filter(ph -> ph.info().command().orElse("").contains("sleep")) + .collect(Collectors.toList()); + assertEquals(phs.size(), createdProcessNum, "spawned processes vs allChildren"); + assertEqualsWithoutOrder(phs, children, ProcessHandle::compareTo, processNum); + } finally { + ProcessHandle.current().children().forEach(ProcessHandle::destroyForcibly); + } + } + + /** + * Sort two list by given comparator and compare two list without order + * @param actual Process handle list1 + * @param expected Process handle list1 + * @param comp ProcessHandle comparator for sorting + * @param pn number of processes + */ + private void assertEqualsWithoutOrder(List actual, + List expected, Comparator comp, int pn) { + Collections.sort(actual, comp); + Collections.sort(expected, comp); + + assertEquals(actual, expected); + } + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + public static void main(String[] args) { + Class[] testclass = {ScaleTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } +} diff --git a/jdk/test/java/lang/ProcessHandle/TEST.properties b/jdk/test/java/lang/ProcessHandle/TEST.properties new file mode 100644 index 00000000000..685810a4b60 --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/TEST.properties @@ -0,0 +1,4 @@ +# ProcessHandle tests use TestNG +TestNG.dirs = . +lib.dirs = /lib/testlibrary + diff --git a/jdk/test/java/lang/ProcessHandle/TreeTest.java b/jdk/test/java/lang/ProcessHandle/TreeTest.java new file mode 100644 index 00000000000..5a7928216fd --- /dev/null +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2014, 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. + */ + + +import java.io.IOException; +import java.util.ArrayList; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.concurrent.ExecutionException; +import org.testng.Assert; +import org.testng.TestNG; +import org.testng.annotations.Test; + +/* + * @test + * @library /lib/testlibrary + * Test counting and JavaChild.spawning and counting of Processes. + * @run testng/othervm InfoTest + * @author Roger Riggs + */ +public class TreeTest extends ProcessUtil { + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + public static void main(String[] args) { + Class[] testclass = {TreeTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } + + /** + * Test counting and spawning and counting of Processes. + */ + @Test + public static void test1() { + final int MAXCHILDREN = 2; + List spawned = new ArrayList<>(); + + try { + ProcessHandle self = ProcessHandle.current(); + + printf("self pid: %d%n", self.getPid()); + printDeep(self, ""); + long count = getChildren(self).size(); + Assert.assertEquals(count, 0, "Start with zero children"); + + for (int i = 0; i < MAXCHILDREN; i++) { + // spawn and wait for instructions + spawned.add(JavaChild.spawnJavaChild("pid", "stdin")); + } + + List subprocesses = getChildren(self); + subprocesses.forEach(ProcessUtil::printProcess); + count = subprocesses.size(); + Assert.assertEquals(count, MAXCHILDREN, "Wrong number of spawned children"); + + // Send exit command to each spawned Process + spawned.forEach(p -> { + try { + p.sendAction("exit", ""); + } catch (IOException ex) { + Assert.fail("IOException in sendAction", ex); + } + }); + + // Wait for each Process to exit + spawned.forEach(p -> { + do { + try { + Assert.assertEquals(p.waitFor(), 0, "exit status incorrect"); + break; + } catch (InterruptedException ex) { + continue; // Retry + } + } while (true); + }); + + // Verify that ProcessHandle.isAlive sees each of them as not alive + for (ProcessHandle ph : subprocesses) { + Assert.assertFalse(ph.isAlive(), + "ProcessHandle.isAlive for exited process: " + ph); + } + + // Verify no current children are visible + count = getChildren(self).size(); + Assert.assertEquals(count, 0, "Children destroyed, should be zero"); + + } catch (IOException ioe) { + Assert.fail("unable to spawn process", ioe); + } finally { + // Cleanup any left over processes + spawned.stream().map(Process::toHandle) + .filter(ProcessHandle::isAlive) + .forEach(ph -> printDeep(ph, "test1 cleanup: ")); + destroyProcessTree(ProcessHandle.current()); + } + } + + /** + * Test counting and spawning and counting of Processes. + */ + @Test + public static void test2() { + ProcessHandle p1Handle = null; + try { + ProcessHandle self = ProcessHandle.current(); + List initialChildren = getChildren(self); + long count = initialChildren.size(); + if (count > 0) { + initialChildren.forEach(p -> printDeep(p, "test2 initial unexpected: ")); + Assert.assertEquals(count, 0, "Start with zero children (except Windows conhost.exe)"); + } + + JavaChild p1 = JavaChild.spawnJavaChild("stdin"); + p1Handle = p1.toHandle(); + printf(" p1 pid: %d%n", p1.getPid()); + + int spawnNew = 3; + p1.sendAction("spawn", spawnNew, "stdin"); + + // Wait for direct children to be created and save the list + List subprocesses = waitForAllChildren(p1Handle, spawnNew); + for (ProcessHandle ph : subprocesses) { + Assert.assertTrue(ph.isAlive(), "Child should be alive: " + ph); + } + + // Each child spawns two processes and waits for commands + int spawnNewSub = 2; + p1.sendAction("child", "spawn", spawnNewSub, "stdin"); + + // For each spawned child, wait for its children + for (ProcessHandle p : subprocesses) { + List grandChildren = waitForChildren(p, spawnNewSub); + } + + List allChildren = getAllChildren(p1Handle); + printf(" allChildren: %s%n", + allChildren.stream().map(p -> p.getPid()) + .collect(Collectors.toList())); + for (ProcessHandle ph : allChildren) { + Assert.assertEquals(ph.isAlive(), true, "Child should be alive: " + ph); + } + + // Closing JavaChild's InputStream will cause all children to exit + p1.getOutputStream().close(); + + for (ProcessHandle p : allChildren) { + try { + p.onExit().get(); // wait for the child to exit + } catch (ExecutionException e) { + Assert.fail("waiting for process to exit", e); + } + } + p1.waitFor(); // wait for spawned process to exit + + List remaining = getChildren(self); + remaining.forEach(ph -> Assert.assertFalse(ph.isAlive(), + "process should not be alive: " + ph)); + } catch (IOException | InterruptedException t) { + t.printStackTrace(); + throw new RuntimeException(t); + } finally { + // Cleanup any left over processes + if (p1Handle.isAlive()) { + printDeep(p1Handle, "test2 cleanup: "); + } + destroyProcessTree(ProcessHandle.current()); + } + } + + /** + * Test destroy of processes. + */ + @Test + public static void test3() { + try { + ProcessHandle self = ProcessHandle.current(); + + JavaChild p1 = JavaChild.spawnJavaChild("stdin"); + ProcessHandle p1Handle = p1.toHandle(); + printf(" p1: %s%n", p1.getPid()); + long count = getChildren(self).size(); + Assert.assertEquals(count, 1, "Wrong number of spawned children"); + + int newChildren = 3; + // Spawn children and have them wait + p1.sendAction("spawn", newChildren, "stdin"); + + // Wait for the new processes and save the list + List subprocesses = waitForAllChildren(p1Handle, newChildren); + printDeep(p1Handle, "allChildren"); + + Assert.assertEquals(subprocesses.size(), newChildren, "Wrong number of children"); + + p1.children().filter(TreeTest::isNotWindowsConsole) + .forEach(ProcessHandle::destroyForcibly); + + self.children().filter(TreeTest::isNotWindowsConsole) + .forEach(ProcessHandle::destroyForcibly); + + do { + Thread.sleep(500L); // It will happen but don't burn the cpu + Object[] children = self.allChildren() + .filter(TreeTest::isNotWindowsConsole) + .toArray(); + count = children.length; + printf(" waiting for subprocesses of %s to terminate," + + " expected: 0, current: %d, children: %s%n", self, count, + Arrays.toString(children)); + printDeep(self, ""); + } while (count > 0); + + boolean ex1 = p1.waitFor(5, TimeUnit.SECONDS); + Assert.assertTrue(ex1, "Subprocess should have exited: " + p1); + + for (ProcessHandle p : subprocesses) { + Assert.assertFalse(p.isAlive(), "Destroyed process.isAlive: " + p + + ", parent: " + p.parent() + + ", info: " + p.info().toString()); + } + + } catch (IOException ioe) { + Assert.fail("Spawn of subprocess failed", ioe); + } catch (InterruptedException inte) { + Assert.fail("InterruptedException", inte); + } + } + + /** + * Test (Not really a test) that dumps the list of all Processes. + */ + @Test + public static void test4() { + printf(" Parent Child Info%n"); + Stream s = ProcessHandle.allProcesses(); + ProcessHandle[] processes = s.toArray(ProcessHandle[]::new); + int len = processes.length; + ProcessHandle[] parent = new ProcessHandle[len]; + Set processesSet = + Arrays.stream(processes).collect(Collectors.toSet()); + Integer[] sortindex = new Integer[len]; + for (int i = 0; i < len; i++) { + sortindex[i] = i; + } + for (int i = 0; i < len; i++) { + parent[sortindex[i]] = processes[sortindex[i]].parent().orElse(null); + } + Arrays.sort(sortindex, (i1, i2) -> { + int cmp = Long.compare((parent[i1] == null ? 0L : parent[i1].getPid()), + (parent[i2] == null ? 0L : parent[i2].getPid())); + if (cmp == 0) { + cmp = Long.compare((processes[i1] == null ? 0L : processes[i1].getPid()), + (processes[i2] == null ? 0L : processes[i2].getPid())); + } + return cmp; + }); + boolean fail = false; + for (int i = 0; i < len; i++) { + ProcessHandle p = processes[sortindex[i]]; + ProcessHandle p_parent = parent[sortindex[i]]; + ProcessHandle.Info info = p.info(); + String indent = " "; + if (p_parent != null) { + if (!processesSet.contains(p_parent)) { + fail = true; + indent = "*** "; + } + } + printf("%s %7s, %7s, %s%n", indent, p_parent, p, info); + } + Assert.assertFalse(fail, "Parents missing from all Processes"); + + } + + /** + * A test for scale; launch a large number (39) of subprocesses. + */ + @Test + public static void test5() { + int factor = 2; + ProcessHandle p1Handle = null; + Instant start = Instant.now(); + try { + JavaChild p1 = JavaChild.spawnJavaChild("stdin"); + p1Handle = p1.toHandle(); + + printf("Spawning %d x %d x %d processes, pid: %d%n", + factor, factor, factor, p1.getPid()); + + // Start the first tier of subprocesses + p1.sendAction("spawn", factor, "stdin"); + + // Start the second tier of subprocesses + p1.sendAction("child", "spawn", factor, "stdin"); + + // Start the third tier of subprocesses + p1.sendAction("child", "child", "spawn", factor, "stdin"); + + int newChildren = factor * (1 + factor * (1 + factor)); + List children = ProcessUtil.waitForAllChildren(p1Handle, newChildren); + + Assert.assertEquals(p1.children() + .filter(ProcessUtil::isNotWindowsConsole) + .count(), factor, "expected direct children"); + Assert.assertEquals(p1.allChildren() + .filter(ProcessUtil::isNotWindowsConsole) + .count(), + factor * factor * factor + factor * factor + factor, + "expected all children"); + + List subprocesses = p1.allChildren() + .filter(ProcessUtil::isNotWindowsConsole) + .collect(Collectors.toList()); + printf(" allChildren: %s%n", + subprocesses.stream().map(p -> p.getPid()) + .collect(Collectors.toList())); + + p1.getOutputStream().close(); // Close stdin for the controlling p1 + p1.waitFor(); + } catch (InterruptedException | IOException ex) { + Assert.fail("Unexpected Exception", ex); + } finally { + printf("Duration: %s%n", Duration.between(start, Instant.now())); + // Cleanup any left over processes + if (p1Handle.isAlive()) { + printDeep(p1Handle, "test5 cleanup: "); + } + destroyProcessTree(ProcessHandle.current()); + } + } + +} From b4ff25ecc84c77a5641d1d163e83417709ca6817 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 29 May 2015 15:17:07 -0400 Subject: [PATCH 053/117] 8081536: (process) remove unreliable ScaleTest from ProcessHandle tests Reviewed-by: darcy --- .../java/lang/ProcessHandle/ScaleTest.java | 126 ------------------ 1 file changed, 126 deletions(-) delete mode 100644 jdk/test/java/lang/ProcessHandle/ScaleTest.java diff --git a/jdk/test/java/lang/ProcessHandle/ScaleTest.java b/jdk/test/java/lang/ProcessHandle/ScaleTest.java deleted file mode 100644 index ffd8e61105e..00000000000 --- a/jdk/test/java/lang/ProcessHandle/ScaleTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; -import static org.testng.Assert.assertEquals; -import org.testng.TestNG; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/* - * @test - * @summary Scalibities test for checking scability of ProcessHandle - * @run testng/othervm ScaleTest - */ -public class ScaleTest { - /** - * Scale max processes number to 5000. - */ - private final static int MAX_PROCESSES_LIMIT = 1000; - - /** - * Create test process number as 1, 2, 5, 10, 20, 50, 100, 200... until it reach - * setting process limit. - * @return iterator on how many processes can be created. - * @throws IOException if can't create processes. - */ - @DataProvider - public Iterator processesNumbers() { - // Limit spawn processes number less than total limitation. - - List testProcesses = new ArrayList<>(); - int i = 1, j = 0; - while (i <= MAX_PROCESSES_LIMIT) { - testProcesses.add(new Object[]{i}); - if ((j % 3) != 1) - i *= 2; - else - i = i * 25 / 10; - j++; - } - return testProcesses.iterator(); - } - - /** - * Start process by given number, compare created processes with - * ProcessHandle.children by order. - * @param processNum processes number that will be created - */ - @Test(dataProvider = "processesNumbers") - public void scaleProcesses(int processNum) { - try { - ProcessBuilder pb = new ProcessBuilder(); - pb.command("sleep", "600"); - List children = new ArrayList<>(); - - int createdProcessNum = 0; - for (int i = 0; i < processNum; i++) { - try { - children.add(pb.start().toHandle()); - createdProcessNum++; - } catch (Throwable ignore) { - // Hard to control how many processes we can generate. - // Ignore every error when create new process - } - } - List phs = ProcessHandle.current().allChildren() - .filter(ph -> ph.info().command().orElse("").contains("sleep")) - .collect(Collectors.toList()); - assertEquals(phs.size(), createdProcessNum, "spawned processes vs allChildren"); - assertEqualsWithoutOrder(phs, children, ProcessHandle::compareTo, processNum); - } finally { - ProcessHandle.current().children().forEach(ProcessHandle::destroyForcibly); - } - } - - /** - * Sort two list by given comparator and compare two list without order - * @param actual Process handle list1 - * @param expected Process handle list1 - * @param comp ProcessHandle comparator for sorting - * @param pn number of processes - */ - private void assertEqualsWithoutOrder(List actual, - List expected, Comparator comp, int pn) { - Collections.sort(actual, comp); - Collections.sort(expected, comp); - - assertEquals(actual, expected); - } - - // Main can be used to run the tests from the command line with only testng.jar. - @SuppressWarnings("raw_types") - public static void main(String[] args) { - Class[] testclass = {ScaleTest.class}; - TestNG testng = new TestNG(); - testng.setTestClasses(testclass); - testng.run(); - } -} From 783a654b1781d2f2e143b8c291cf1ef96f6e693c Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 29 May 2015 14:04:57 -0700 Subject: [PATCH 054/117] 8073372: Redundant CONSTANT_Class entry not generated for inlined constant Reviewed-by: jjg --- .../classes/com/sun/tools/javac/jvm/Gen.java | 8 +- .../CPoolRefClassContainingInlinedCts.java | 115 +++++++++++++----- ...java => ClassToBeStaticallyImportedA.java} | 6 +- .../pkg/ClassToBeStaticallyImportedB.java | 29 +++++ 4 files changed, 125 insertions(+), 33 deletions(-) rename langtools/test/tools/javac/7153958/pkg/{ClassToBeStaticallyImported.java => ClassToBeStaticallyImportedA.java} (87%) create mode 100644 langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index f90c6c28ae3..039a1f46ac1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -470,6 +470,10 @@ public class Gen extends JCTree.Visitor { clinitTAs.addAll(getAndRemoveNonFieldTAs(sym)); } else { checkStringConstant(vdef.init.pos(), sym.getConstValue()); + /* if the init contains a reference to an external class, add it to the + * constant's pool + */ + vdef.init.accept(classReferenceVisitor); } } break; @@ -2337,9 +2341,11 @@ public class Gen extends JCTree.Visitor { ClassSymbol c = cdef.sym; this.toplevel = env.toplevel; this.endPosTable = toplevel.endPositions; - cdef.defs = normalizeDefs(cdef.defs, c); c.pool = pool; pool.reset(); + /* method normalizeDefs() can add references to external classes into the constant pool + */ + cdef.defs = normalizeDefs(cdef.defs, c); generateReferencesToPrunedTree(c, pool); Env localEnv = new Env<>(cdef, new GenContext()); localEnv.toplevel = env.toplevel; diff --git a/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java b/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java index 7b233d8af6e..89994f0f5e2 100644 --- a/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java +++ b/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java @@ -25,10 +25,10 @@ /* * @test - * @bug 7153958 + * @bug 7153958 8073372 * @summary add constant pool reference to class containing inlined constants * @modules jdk.jdeps/com.sun.tools.classfile - * @compile pkg/ClassToBeStaticallyImported.java CPoolRefClassContainingInlinedCts.java + * @compile pkg/ClassToBeStaticallyImportedA.java pkg/ClassToBeStaticallyImportedB.java CPoolRefClassContainingInlinedCts.java * @run main CPoolRefClassContainingInlinedCts */ @@ -39,7 +39,8 @@ import com.sun.tools.classfile.ConstantPoolException; import java.io.File; import java.io.IOException; -import static pkg.ClassToBeStaticallyImported.staticField; +import static pkg.ClassToBeStaticallyImportedA.staticFieldA; +import static pkg.ClassToBeStaticallyImportedB.staticFieldB; public class CPoolRefClassContainingInlinedCts { @@ -55,10 +56,14 @@ public class CPoolRefClassContainingInlinedCts { void checkClassName(String className) { switch (className) { - case "SimpleAssignClass" : case "BinaryExpClass": - case "UnaryExpClass" : case "CastClass": - case "ParensClass" : case "CondClass": - case "IfClass" : case "pkg/ClassToBeStaticallyImported": + case "SimpleAssignClassA" : case "BinaryExpClassA": + case "UnaryExpClassA" : case "CastClassA": + case "ParensClassA" : case "CondClassA": + case "IfClassA" : case "pkg/ClassToBeStaticallyImportedA": + case "SimpleAssignClassB" : case "BinaryExpClassB": + case "UnaryExpClassB" : case "CastClassB": + case "ParensClassB" : case "CondClassB": + case "IfClassB" : case "pkg/ClassToBeStaticallyImportedB": numberOfReferencedClassesToBeChecked++; } } @@ -77,59 +82,111 @@ public class CPoolRefClassContainingInlinedCts { } i += cpInfo.size(); } - if (numberOfReferencedClassesToBeChecked != 8) { + if (numberOfReferencedClassesToBeChecked != 16) { throw new AssertionError("Class reference missing in the constant pool"); } } - private int assign = SimpleAssignClass.x; - private int binary = BinaryExpClass.x + 1; - private int unary = -UnaryExpClass.x; - private int cast = (int)CastClass.x; - private int parens = (ParensClass.x); - private int cond = (CondClass.x == 1) ? 1 : 2; - private static int ifConstant; - private static int importStatic; + private int assignA = SimpleAssignClassA.x; + private int binaryA = BinaryExpClassA.x + 1; + private int unaryA = -UnaryExpClassA.x; + private int castA = (int)CastClassA.x; + private int parensA = (ParensClassA.x); + private int condA = (CondClassA.x == 1) ? 1 : 2; + private static int ifConstantA; + private static int importStaticA; static { - if (IfClass.x == 1) { - ifConstant = 1; + if (IfClassA.x == 1) { + ifConstantA = 1; } else { - ifConstant = 2; + ifConstantA = 2; } } static { - if (staticField == 1) { - importStatic = 1; + if (staticFieldA == 1) { + importStaticA = 1; } else { - importStatic = 2; + importStaticA = 2; + } + } + + // now as final constants + private static final int assignB = SimpleAssignClassB.x; + private static final int binaryB = BinaryExpClassB.x + 1; + private static final int unaryB = -UnaryExpClassB.x; + private static final int castB = (int)CastClassB.x; + private static final int parensB = (ParensClassB.x); + private static final int condB = (CondClassB.x == 1) ? 1 : 2; + private static final int ifConstantB; + private static final int importStaticB; + static { + if (IfClassB.x == 1) { + ifConstantB = 1; + } else { + ifConstantB = 2; + } + } + static { + if (staticFieldB == 1) { + importStaticB = 1; + } else { + importStaticB = 2; } } } -class SimpleAssignClass { +class SimpleAssignClassA { public static final int x = 1; } -class BinaryExpClass { +class SimpleAssignClassB { public static final int x = 1; } -class UnaryExpClass { +class BinaryExpClassA { public static final int x = 1; } -class CastClass { +class BinaryExpClassB { public static final int x = 1; } -class ParensClass { +class UnaryExpClassA { public static final int x = 1; } -class CondClass { +class UnaryExpClassB { public static final int x = 1; } -class IfClass { +class CastClassA { + public static final int x = 1; +} + +class CastClassB { + public static final int x = 1; +} + +class ParensClassA { + public static final int x = 1; +} + +class ParensClassB { + public static final int x = 1; +} + +class CondClassA { + public static final int x = 1; +} + +class CondClassB { + public static final int x = 1; +} + +class IfClassA { + public static final int x = 1; +} + +class IfClassB { public static final int x = 1; } diff --git a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedA.java similarity index 87% rename from langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java rename to langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedA.java index 801098d0293..b8fb39f4ff3 100644 --- a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java +++ b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,6 +24,6 @@ */ package pkg; -public class ClassToBeStaticallyImported { - public static final int staticField = 1; +public class ClassToBeStaticallyImportedA { + public static final int staticFieldA = 1; } diff --git a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java new file mode 100644 index 00000000000..d05c6fbab07 --- /dev/null +++ b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java @@ -0,0 +1,29 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package pkg; + +public class ClassToBeStaticallyImportedB { + public static final int staticFieldB = 1; +} From c8f110edb6dee4b20cc6096b338d699b3d62974f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 29 May 2015 15:50:31 -0700 Subject: [PATCH 055/117] 8081541: @ignore CheckEBCDICLocaleTest Reviewed-by: vromero --- .../javac/4846262/CheckEBCDICLocaleTest.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java index 03355aeef66..a111e68ecca 100644 --- a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java +++ b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java @@ -29,11 +29,13 @@ * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file * jdk.compiler/com.sun.tools.javac.main + * @ignore 8081538 test CheckEBCDICLocaleTest is failing * @build ToolBox * @run main CheckEBCDICLocaleTest */ import java.io.File; +import java.io.PrintStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; @@ -87,16 +89,21 @@ public class CheckEBCDICLocaleTest { try { tb.checkEqual(expectLines, actualLines); } catch (Throwable tt) { - System.err.println("current ouput don't have the expected number of lines. See output below"); + PrintStream out = tb.out; + out.println("Output mismatch:"); - System.err.println("Expected output:"); - System.err.println(TestOutTemplate); - System.err.println(); - System.err.println("Actual output:"); - for (String s : actualLines) { - System.err.println(s); + out.println("Expected output:"); + for (String s: expectLines) { + out.println(s); } - System.err.println(); + out.println(); + + out.println("Actual output:"); + for (String s : actualLines) { + out.println(s); + } + out.println(); + throw tt; } } From 1b685e4aa7913ff373aa73dd58d10ae88888f604 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 29 May 2015 17:15:10 -0700 Subject: [PATCH 056/117] 8081538: test CheckEBCDICLocaleTest is failing Reviewed-by: vromero --- .../javac/4846262/CheckEBCDICLocaleTest.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java index a111e68ecca..52c5e598d68 100644 --- a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java +++ b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java @@ -29,16 +29,17 @@ * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file * jdk.compiler/com.sun.tools.javac.main - * @ignore 8081538 test CheckEBCDICLocaleTest is failing * @build ToolBox * @run main CheckEBCDICLocaleTest */ import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; import java.io.PrintStream; +import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; @@ -70,16 +71,19 @@ public class CheckEBCDICLocaleTest { tb.writeFile("Test.java", TestSrc); tb.createDirectories("output"); - Native2Ascii n2a = new Native2Ascii(Charset.forName("IBM1047")); + Charset ebcdic = Charset.forName("IBM1047"); + Native2Ascii n2a = new Native2Ascii(ebcdic); n2a.asciiToNative(Paths.get("Test.java"), Paths.get("output", "Test.java")); - tb.new JavacTask(ToolBox.Mode.EXEC) - .redirect(ToolBox.OutputKind.STDERR, "Test.tmp") - .options("-J-Duser.language=en", - "-J-Duser.region=US", - "-J-Dfile.encoding=IBM1047") - .files("output/Test.java") - .run(ToolBox.Expect.FAIL); + // Use -encoding to specify the encoding with which to read source files + // Use a suitable configured output stream for javac diagnostics + int rc; + try (PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("Test.tmp"), ebcdic))) { + String[] args = { "-encoding", ebcdic.name(), "output/Test.java" }; + rc = com.sun.tools.javac.Main.compile(args, out); + if (rc != 1) + throw new Exception("unexpected exit from javac: " + rc); + } n2a.nativeToAscii(Paths.get("Test.tmp"), Paths.get("Test.out")); From 1a5f839adc6383b2f6991fae0cb597bcebb906ef Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Sat, 30 May 2015 06:17:50 +0530 Subject: [PATCH 057/117] 8077667: 'variable may not have been initialized' error for parameter in lambda function JDK-8077667: Fix bogus diagnostic about lambda parameter not being initialized Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Flow.java | 2 + .../LambdaParameterNeedsNoInitTest.java | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 langtools/test/tools/javac/lambda/LambdaParameterNeedsNoInitTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index da70bcc9c0e..ad82a1e8a1b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2270,6 +2270,7 @@ public class Flow { final Bits prevUninits = new Bits(uninits); final Bits prevInits = new Bits(inits); int returnadrPrev = returnadr; + int nextadrPrev = nextadr; ListBuffer prevPending = pendingExits; try { returnadr = nextadr; @@ -2291,6 +2292,7 @@ public class Flow { uninits.assign(prevUninits); inits.assign(prevInits); pendingExits = prevPending; + nextadr = nextadrPrev; } } diff --git a/langtools/test/tools/javac/lambda/LambdaParameterNeedsNoInitTest.java b/langtools/test/tools/javac/lambda/LambdaParameterNeedsNoInitTest.java new file mode 100644 index 00000000000..4fb5d15f2ca --- /dev/null +++ b/langtools/test/tools/javac/lambda/LambdaParameterNeedsNoInitTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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 8077667 + * @summary Eliminate bogus error about lambda parameter not being initialized. + * @compile LambdaParameterNeedsNoInitTest.java + */ +import java.util.function.Predicate; + +public class LambdaParameterNeedsNoInitTest { + + public static void main(String[] args) { + new Inner(); + } + + private static class Inner { + Predicate synonymComparator = a -> a.isEmpty(); + Inner() { + if (true) { + return; + } + synonymComparator.test(""); + } + } +} From efaa3744a21063dc2e81b160adb65480ccdf66c0 Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Sat, 30 May 2015 15:19:15 +0300 Subject: [PATCH 058/117] 7011441: jndi/ldap/Connection.java needs to avoid spurious wakeup Reviewed-by: dholmes --- .../classes/com/sun/jndi/ldap/Connection.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java index c50d3f19ddb..3b51603ee92 100644 --- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java +++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java @@ -393,9 +393,14 @@ public final class Connection implements Runnable { BerDecoder readReply(LdapRequest ldr) throws IOException, NamingException { BerDecoder rber; - boolean waited = false; - while (((rber = ldr.getReplyBer()) == null) && !waited) { + // Track down elapsed time to workaround spurious wakeups + long elapsedMilli = 0; + long elapsedNano = 0; + + while (((rber = ldr.getReplyBer()) == null) && + (readTimeout <= 0 || elapsedMilli < readTimeout)) + { try { // If socket closed, don't even try synchronized (this) { @@ -409,11 +414,15 @@ public final class Connection implements Runnable { rber = ldr.getReplyBer(); if (rber == null) { if (readTimeout > 0) { // Socket read timeout is specified + long beginNano = System.nanoTime(); - // will be woken up before readTimeout only if reply is + // will be woken up before readTimeout if reply is // available - ldr.wait(readTimeout); - waited = true; + ldr.wait(readTimeout - elapsedMilli); + elapsedNano += (System.nanoTime() - beginNano); + elapsedMilli += elapsedNano / 1000_000; + elapsedNano %= 1000_000; + } else { // no timeout is set so we wait infinitely until // a response is received @@ -430,7 +439,7 @@ public final class Connection implements Runnable { } } - if ((rber == null) && waited) { + if ((rber == null) && (elapsedMilli >= readTimeout)) { abandonRequest(ldr, null); throw new NamingException("LDAP response read timed out, timeout used:" + readTimeout + "ms." ); From 4a9502a06af8c2d1628de2e01430ae5a7b947ee2 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Mon, 1 Jun 2015 15:01:36 +0200 Subject: [PATCH 059/117] 8066218: UTF-32LE mistakenly detected as UTF-16LE Reviewed-by: lagergren, sundar --- .../classes/jdk/nashorn/internal/runtime/Source.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java index 06b77b9da3e..7599ff4028f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java @@ -934,14 +934,16 @@ public final class Source implements Loggable { start = 2; cs = StandardCharsets.UTF_16BE; } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) { - start = 2; - cs = StandardCharsets.UTF_16LE; + if (bytes.length > 3 && bytes[2] == 0 && bytes[3] == 0) { + start = 4; + cs = Charset.forName("UTF-32LE"); + } else { + start = 2; + cs = StandardCharsets.UTF_16LE; + } } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) { start = 3; cs = StandardCharsets.UTF_8; - } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) { - start = 4; - cs = Charset.forName("UTF-32LE"); } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) { start = 4; cs = Charset.forName("UTF-32BE"); From 0b4d0d4fec6ce8dea613343234e22f2e44767869 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 1 Jun 2015 10:27:24 -0400 Subject: [PATCH 060/117] 8081565: javac lint warnings in jdk testlibrary Reviewed-by: lancea --- .../lib/security/CheckBlacklistedCerts.java | 2 +- jdk/test/lib/testlibrary/AssertsTest.java | 17 ++++++++++------- .../testlibrary/jdk/testlibrary/JarUtils.java | 4 ++-- .../jdk/testlibrary/OutputBuffer.java | 2 ++ .../testlibrary/ParentLastURLClassLoader.java | 2 +- .../jdk/testlibrary/ProcessTools.java | 4 +++- .../jdk/testlibrary/StreamPumper.java | 2 +- 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/jdk/test/lib/security/CheckBlacklistedCerts.java b/jdk/test/lib/security/CheckBlacklistedCerts.java index 7489febe348..a281a0460d8 100644 --- a/jdk/test/lib/security/CheckBlacklistedCerts.java +++ b/jdk/test/lib/security/CheckBlacklistedCerts.java @@ -45,7 +45,7 @@ public class CheckBlacklistedCerts { File file = new File(home, "lib/security/cacerts"); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); try (FileInputStream fis = new FileInputStream(file)) { - ks.load(new FileInputStream(file), null); + ks.load(fis, null); } System.out.println("Check for cacerts: " + ks.size()); for (String alias: Collections.list(ks.aliases())) { diff --git a/jdk/test/lib/testlibrary/AssertsTest.java b/jdk/test/lib/testlibrary/AssertsTest.java index a9efe219465..9fef92ee8b6 100644 --- a/jdk/test/lib/testlibrary/AssertsTest.java +++ b/jdk/test/lib/testlibrary/AssertsTest.java @@ -21,6 +21,8 @@ * questions. */ +import java.lang.SuppressWarnings; + import static jdk.testlibrary.Asserts.*; /* @test @@ -75,7 +77,7 @@ public class AssertsTest { private static void testEquals() throws Exception { expectPass(Assertion.EQ, 1, 1); - expectPass(Assertion.EQ, (Comparable)null, (Comparable)null); + expectPass(Assertion.EQ, (Integer)null, (Integer)null); Foo f1 = new Foo(1); expectPass(Assertion.EQ, f1, f1); @@ -112,13 +114,13 @@ public class AssertsTest { Foo f2 = new Foo(1); expectPass(Assertion.NE, f1, f2); - expectFail(Assertion.NE, (Comparable)null, (Comparable)null); + expectFail(Assertion.NE, (Integer)null, (Integer)null); expectFail(Assertion.NE, f1, f1); expectFail(Assertion.NE, 1, 1); } private static void testNull() throws Exception { - expectPass(Assertion.NULL, (Comparable)null); + expectPass(Assertion.NULL, (Integer)null); expectFail(Assertion.NULL, 1); } @@ -126,7 +128,7 @@ public class AssertsTest { private static void testNotNull() throws Exception { expectPass(Assertion.NOTNULL, 1); - expectFail(Assertion.NOTNULL, (Comparable)null); + expectFail(Assertion.NOTNULL, (Integer)null); } private static void testTrue() throws Exception { @@ -169,13 +171,13 @@ public class AssertsTest { } } - - + @SuppressWarnings("unchecked") private static > void expectPass(Assertion assertion, T ... args) throws Exception { Assertion.run(assertion, args); } + @SuppressWarnings("unchecked") private static > void expectFail(Assertion assertion, T ... args) throws Exception { try { @@ -192,8 +194,9 @@ public class AssertsTest { enum Assertion { LT, LTE, EQ, GTE, GT, NE, NULL, NOTNULL, FALSE, TRUE; + @SuppressWarnings("unchecked") public static > void run(Assertion assertion, T ... args) { - String msg = "Expected " + format(assertion, args) + " to pass"; + String msg = "Expected " + format(assertion, (Object[])args) + " to pass"; switch (assertion) { case LT: assertLessThan(args[0], args[1], msg); diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java index 69c21011ad4..fab9b8a930e 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java @@ -72,9 +72,9 @@ public final class JarUtils { // is in the updated list List updatedFiles = new ArrayList<>(); try (JarFile srcJarFile = new JarFile(src)) { - Enumeration entries = srcJarFile.entries(); + Enumeration entries = srcJarFile.entries(); while (entries.hasMoreElements()) { - JarEntry entry = (JarEntry) entries.nextElement(); + JarEntry entry = entries.nextElement(); String name = entry.getName(); boolean found = false; for (String file : files) { diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java index c104e81207e..5595d5cb35c 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java @@ -30,6 +30,8 @@ import java.util.concurrent.Future; class OutputBuffer { private static class OutputBufferException extends RuntimeException { + private static final long serialVersionUID = 8528687792643129571L; + public OutputBufferException(Throwable cause) { super(cause); } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java index 203db612bf3..5537ebd3047 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java @@ -38,7 +38,7 @@ public class ParentLastURLClassLoader extends URLClassLoader { @Override public Class loadClass(String name) throws ClassNotFoundException { try { - Class c = findClass(name); + Class c = findClass(name); if (c != null) { return c; } diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index a9697025318..207d18099b6 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -72,7 +72,7 @@ public final class ProcessTools { public static Process startProcess(String name, ProcessBuilder processBuilder) throws IOException { - return startProcess(name, processBuilder, (Consumer)null); + return startProcess(name, processBuilder, (Consumer)null); } /** @@ -85,6 +85,7 @@ public final class ProcessTools { * @return Returns the initialized process * @throws IOException */ + @SuppressWarnings("overloads") public static Process startProcess(String name, ProcessBuilder processBuilder, Consumer consumer) @@ -239,6 +240,7 @@ public final class ProcessTools { * @throws InterruptedException * @throws TimeoutException */ + @SuppressWarnings("overloads") public static Process startProcess(String name, ProcessBuilder processBuilder, final Predicate linePredicate) diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java index 224dcb28247..7f76c6912b9 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java @@ -77,7 +77,7 @@ public final class StreamPumper implements Runnable { private final Set linePumps = new HashSet<>(); private final AtomicBoolean processing = new AtomicBoolean(false); - private final FutureTask processingTask = new FutureTask(this, null); + private final FutureTask processingTask = new FutureTask<>(this, null); public StreamPumper(InputStream in) { this.in = in; From ea68abc64ea0cd0418bfd207cf1fa5c0979cca64 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 1 Jun 2015 10:29:06 -0400 Subject: [PATCH 061/117] 8081566: java/lang/ProcessHandle/InfoTest.java failed on case sensitive command Reviewed-by: lancea, alanb --- jdk/test/java/lang/ProcessHandle/InfoTest.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/lang/ProcessHandle/InfoTest.java b/jdk/test/java/lang/ProcessHandle/InfoTest.java index 3aa3a438e6b..51254f12167 100644 --- a/jdk/test/java/lang/ProcessHandle/InfoTest.java +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java @@ -25,6 +25,9 @@ import java.io.File; import java.io.BufferedReader; import java.io.IOException; import java.lang.ProcessBuilder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -148,8 +151,10 @@ public class InfoTest { String javaExe = System.getProperty("test.jdk") + File.separator + "bin" + File.separator + "java"; String expected = Platform.isWindows() ? javaExe + ".exe" : javaExe; - Assert.assertEquals(command.get(), expected, - "Command: expected: 'java'" + ", actual: " + command); + Path expectedPath = Paths.get(expected); + Path actualPath = Paths.get(command.get()); + Assert.assertTrue(Files.isSameFile(expectedPath, actualPath), + "Command: expected: " + javaExe + ", actual: " + command.get()); } if (info.arguments().isPresent()) { From 98062e8bd15b8f47dd078339a86088b2e0e92984 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 1 Jun 2015 15:19:54 -0700 Subject: [PATCH 062/117] 8075546: Add tiered testing definitions to the langtools repo Reviewed-by: jjg --- langtools/test/ProblemList.txt | 26 +++++++++++++++ langtools/test/TEST.ROOT | 18 +++++++++-- langtools/test/TEST.groups | 32 +++++++++++++++++++ .../api/basic/GetTask_DocletClassTest.java | 1 + 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 langtools/test/ProblemList.txt create mode 100644 langtools/test/TEST.groups diff --git a/langtools/test/ProblemList.txt b/langtools/test/ProblemList.txt new file mode 100644 index 00000000000..434b3ff4d20 --- /dev/null +++ b/langtools/test/ProblemList.txt @@ -0,0 +1,26 @@ +########################################################################### +# +# Copyright (c) 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. +# +########################################################################### + +# No langtools tests are on the problem list. diff --git a/langtools/test/TEST.ROOT b/langtools/test/TEST.ROOT index 6512c34009f..f26bcb43d83 100644 --- a/langtools/test/TEST.ROOT +++ b/langtools/test/TEST.ROOT @@ -1,6 +1,18 @@ # This file identifies the root of the test-suite hierarchy. # It also contains test-suite configuration information. -# DO NOT EDIT without first contacting jdk-regtest@sun.com. -# The list of keywords supported in the entire test suite -keys=2d dnd i18n +# The list of keywords supported in the entire test suite. The +# "intermittent" keyword marks tests known to fail intermittently. +# The "randomness" keyword marks tests using randomness with test +# cases differing from run to run. (A test using a fixed random seed +# would not count as "randomness" by this definition.) Extra care +# should be taken to handle test failures of intermittent or +# randomness tests. + +keys=intermittent randomness + +# Group definitions +groups=TEST.groups + +# Tests using jtreg 4.1 b11 features +requiredVersion=4.1 b11 diff --git a/langtools/test/TEST.groups b/langtools/test/TEST.groups new file mode 100644 index 00000000000..bf049864771 --- /dev/null +++ b/langtools/test/TEST.groups @@ -0,0 +1,32 @@ +# Copyright (c) 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. +# + +# Tiered testing definitions + +# All langtools tests are tier 1 +tier1 = \ + tools \ + com \ + lib + +# No langtools tests are tier 2 +tier2 = diff --git a/langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java b/langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java index 1c9a053a354..275c19b02f5 100644 --- a/langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java +++ b/langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java @@ -28,6 +28,7 @@ * @modules jdk.javadoc * @build APITest * @run main GetTask_DocletClassTest + * @key randomness */ import com.sun.javadoc.DocErrorReporter; From 1c1c11d919766cfa743334dd8c9ebd72ca447122 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 1 Jun 2015 17:31:45 -0700 Subject: [PATCH 063/117] 8075551: Add tiered testing definitions to the jaxp repo Reviewed-by: joehw --- jaxp/test/ProblemList.txt | 26 ++++++++++++++++++++++++++ jaxp/test/TEST.ROOT | 13 +++++++++++++ jaxp/test/TEST.groups | 11 ++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 jaxp/test/ProblemList.txt diff --git a/jaxp/test/ProblemList.txt b/jaxp/test/ProblemList.txt new file mode 100644 index 00000000000..e3dcd5e75b9 --- /dev/null +++ b/jaxp/test/ProblemList.txt @@ -0,0 +1,26 @@ +########################################################################### +# +# Copyright (c) 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. +# +########################################################################### + +# No jaxp tests are on the problem list. diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT index a098ba22044..a90bd60ac34 100644 --- a/jaxp/test/TEST.ROOT +++ b/jaxp/test/TEST.ROOT @@ -1,8 +1,21 @@ # This file identifies the root of the test-suite hierarchy. # It also contains test-suite configuration information. +# The list of keywords supported in the entire test suite. The +# "intermittent" keyword marks tests known to fail intermittently. +# The "randomness" keyword marks tests using randomness with test +# cases differing from run to run. (A test using a fixed random seed +# would not count as "randomness" by this definition.) Extra care +# should be taken to handle test failures of intermittent or +# randomness tests. + +keys=intermittent randomness + # Tests that must run in othervm mode othervm.dirs=javax/xml/jaxp # Group definitions groups=TEST.groups + +# Minimum jtreg version +requiredVersion=4.1 b11 diff --git a/jaxp/test/TEST.groups b/jaxp/test/TEST.groups index 50751d4d7eb..2b9b934e77b 100644 --- a/jaxp/test/TEST.groups +++ b/jaxp/test/TEST.groups @@ -1,4 +1,4 @@ -# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 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 @@ -20,5 +20,14 @@ # questions. # +# Tiered testing definitions + +# No jaxp tests are tier 1. +tier1 = + +# All jaxp tests are tier 2. +tier2 = \ + :jaxp_all + jaxp_all = \ javax/xml/jaxp From 0f1698f9068b0ffd2b09692c2d22bc2ddbd243b6 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Tue, 2 Jun 2015 04:01:04 +0000 Subject: [PATCH 064/117] 8043758: Datagram Transport Layer Security (DTLS) Reviewed-by: jnimeh, weijun, mullan, wetmore --- .../javax/net/ssl/ExtendedSSLSession.java | 14 +- .../classes/javax/net/ssl/SNIServerName.java | 4 +- .../classes/javax/net/ssl/SSLContext.java | 64 +- .../classes/javax/net/ssl/SSLContextSpi.java | 40 +- .../classes/javax/net/ssl/SSLEngine.java | 314 ++-- .../javax/net/ssl/SSLEngineResult.java | 145 +- .../classes/javax/net/ssl/SSLParameters.java | 146 +- .../classes/javax/net/ssl/SSLSession.java | 36 +- .../net/ssl/X509ExtendedTrustManager.java | 73 +- .../sun/security/ssl/AppInputStream.java | 105 +- .../sun/security/ssl/AppOutputStream.java | 79 +- .../sun/security/ssl/Authenticator.java | 154 +- .../classes/sun/security/ssl/CipherBox.java | 146 +- .../classes/sun/security/ssl/CipherSuite.java | 81 +- .../classes/sun/security/ssl/Ciphertext.java | 145 ++ .../sun/security/ssl/ClientAuthType.java | 36 + .../sun/security/ssl/ClientHandshaker.java | 251 +++- .../sun/security/ssl/DTLSInputRecord.java | 1265 +++++++++++++++++ .../sun/security/ssl/DTLSOutputRecord.java | 597 ++++++++ .../classes/sun/security/ssl/DTLSRecord.java | 87 ++ .../share/classes/sun/security/ssl/Debug.java | 46 + .../classes/sun/security/ssl/EngineArgs.java | 238 ---- .../sun/security/ssl/EngineInputRecord.java | 427 ------ .../sun/security/ssl/EngineOutputRecord.java | 329 ----- .../sun/security/ssl/EngineWriter.java | 244 ---- .../sun/security/ssl/HandshakeHash.java | 113 +- .../sun/security/ssl/HandshakeInStream.java | 171 +-- .../sun/security/ssl/HandshakeMessage.java | 272 +++- .../sun/security/ssl/HandshakeOutStream.java | 183 +-- .../security/ssl/HandshakeStateManager.java | 925 ++++++++++++ .../classes/sun/security/ssl/Handshaker.java | 303 ++-- .../sun/security/ssl/HelloCookieManager.java | 144 ++ .../sun/security/ssl/HelloExtensions.java | 2 + .../classes/sun/security/ssl/InputRecord.java | 1059 ++++++-------- .../share/classes/sun/security/ssl/MAC.java | 54 +- .../ssl/MaxFragmentLengthExtension.java | 139 ++ .../sun/security/ssl/OutputRecord.java | 755 +++++----- .../classes/sun/security/ssl/Plaintext.java | 77 + .../sun/security/ssl/ProtocolList.java | 7 +- .../sun/security/ssl/ProtocolVersion.java | 131 +- .../security/ssl/RSAClientKeyExchange.java | 10 +- .../sun/security/ssl/RandomCookie.java | 10 +- .../classes/sun/security/ssl/Record.java | 103 +- .../classes/sun/security/ssl/RecordType.java | 122 ++ .../sun/security/ssl/SSLContextImpl.java | 496 +++++-- .../sun/security/ssl/SSLEngineImpl.java | 1255 ++++++++-------- .../security/ssl/SSLEngineInputRecord.java | 409 ++++++ .../security/ssl/SSLEngineOutputRecord.java | 570 ++++++++ .../classes/sun/security/ssl/SSLRecord.java | 117 ++ .../sun/security/ssl/SSLServerSocketImpl.java | 16 +- .../sun/security/ssl/SSLSessionImpl.java | 88 +- .../sun/security/ssl/SSLSocketImpl.java | 1220 ++++++++-------- .../security/ssl/SSLSocketInputRecord.java | 441 ++++++ .../security/ssl/SSLSocketOutputRecord.java | 383 +++++ .../sun/security/ssl/ServerHandshaker.java | 258 ++-- .../classes/sun/security/ssl/SunJSSE.java | 9 +- .../sun/security/ssl/X509KeyManagerImpl.java | 4 +- .../security/ssl/X509TrustManagerImpl.java | 4 +- .../share/conf/security/java.security | 6 +- jdk/test/javax/net/ssl/DTLS/CipherSuite.java | 75 + jdk/test/javax/net/ssl/DTLS/ClientAuth.java | 57 + .../javax/net/ssl/DTLS/DTLSOverDatagram.java | 602 ++++++++ .../javax/net/ssl/DTLS/InvalidCookie.java | 66 + .../javax/net/ssl/DTLS/InvalidRecords.java | 78 + .../net/ssl/DTLS/NoMacInitialClientHello.java | 65 + jdk/test/javax/net/ssl/DTLS/Reordered.java | 65 + .../javax/net/ssl/DTLS/Retransmission.java | 79 + .../javax/net/ssl/DTLS/WeakCipherSuite.java | 69 + .../javax/net/ssl/SSLEngine/CheckStatus.java | 18 +- .../javax/net/ssl/SSLEngine/LargeBufs.java | 2 +- .../javax/net/ssl/TLS/CipherTestUtils.java | 1 + .../net/ssl/TLSv11/ExportableBlockCipher.java | 11 +- .../ssl/TLSv11/ExportableStreamCipher.java | 11 +- .../templates/SSLSocketSSLEngineTemplate.java | 14 + .../ssl/AppInputStream/ReadHandshake.java | 13 +- .../ssl/ClientHandshaker/LengthCheckTest.java | 4 +- 76 files changed, 11196 insertions(+), 4956 deletions(-) create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/Ciphertext.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/ClientAuthType.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/DTLSRecord.java delete mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/EngineArgs.java delete mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/EngineInputRecord.java delete mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/EngineOutputRecord.java delete mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/EngineWriter.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/HandshakeStateManager.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/MaxFragmentLengthExtension.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/Plaintext.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/RecordType.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/SSLRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java create mode 100644 jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java create mode 100644 jdk/test/javax/net/ssl/DTLS/CipherSuite.java create mode 100644 jdk/test/javax/net/ssl/DTLS/ClientAuth.java create mode 100644 jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java create mode 100644 jdk/test/javax/net/ssl/DTLS/InvalidCookie.java create mode 100644 jdk/test/javax/net/ssl/DTLS/InvalidRecords.java create mode 100644 jdk/test/javax/net/ssl/DTLS/NoMacInitialClientHello.java create mode 100644 jdk/test/javax/net/ssl/DTLS/Reordered.java create mode 100644 jdk/test/javax/net/ssl/DTLS/Retransmission.java create mode 100644 jdk/test/javax/net/ssl/DTLS/WeakCipherSuite.java diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java b/jdk/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java index 70f98ce221d..bc9b012db8c 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -28,7 +28,7 @@ package javax.net.ssl; import java.util.List; /** - * Extends the SSLSession interface to support additional + * Extends the {@code SSLSession} interface to support additional * session attributes. * * @since 1.7 @@ -39,8 +39,8 @@ public abstract class ExtendedSSLSession implements SSLSession { * is willing to use. *

    * Note: this method is used to indicate to the peer which signature - * algorithms may be used for digital signatures in TLS 1.2. It is - * not meaningful for TLS versions prior to 1.2. + * algorithms may be used for digital signatures in TLS/DTLS 1.2. It is + * not meaningful for TLS/DTLS versions prior to 1.2. *

    * The signature algorithm name must be a standard Java Security * name (such as "SHA1withRSA", "SHA256withECDSA", and so on). @@ -52,7 +52,7 @@ public abstract class ExtendedSSLSession implements SSLSession { * Note: the local supported signature algorithms should conform to * the algorithm constraints specified by * {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()} - * method in SSLParameters. + * method in {@code SSLParameters}. * * @return An array of supported signature algorithms, in descending * order of preference. The return value is an empty array if @@ -67,8 +67,8 @@ public abstract class ExtendedSSLSession implements SSLSession { * able to use. *

    * Note: this method is used to indicate to the local side which signature - * algorithms may be used for digital signatures in TLS 1.2. It is - * not meaningful for TLS versions prior to 1.2. + * algorithms may be used for digital signatures in TLS/DTLS 1.2. It is + * not meaningful for TLS/DTLS versions prior to 1.2. *

    * The signature algorithm name must be a standard Java Security * name (such as "SHA1withRSA", "SHA256withECDSA", and so on). diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SNIServerName.java b/jdk/src/java.base/share/classes/javax/net/ssl/SNIServerName.java index 1ef9d05c21e..9df92d75db8 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SNIServerName.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SNIServerName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -31,7 +31,7 @@ import java.util.Arrays; * Instances of this class represent a server name in a Server Name * Indication (SNI) extension. *

    - * The SNI extension is a feature that extends the SSL/TLS protocols to + * The SNI extension is a feature that extends the SSL/TLS/DTLS protocols to * indicate what server name the client is attempting to connect to during * handshaking. See section 3, "Server Name Indication", of TLS Extensions (RFC 6066). diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java index c40d7060c39..ebdae178fd8 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -32,12 +32,12 @@ import sun.security.jca.GetInstance; /** * Instances of this class represent a secure socket protocol * implementation which acts as a factory for secure socket - * factories or SSLEngines. This class is initialized + * factories or {@code SSLEngine}s. This class is initialized * with an optional set of key and trust managers and source of * secure random bytes. * *

    Every implementation of the Java platform is required to support the - * following standard SSLContext protocol: + * following standard {@code SSLContext} protocol: *

      *
    • TLSv1
    • *
    @@ -79,7 +79,7 @@ public class SSLContext { *

    If a default context was set using the {@link #setDefault * SSLContext.setDefault()} method, it is returned. Otherwise, the first * call of this method triggers the call - * SSLContext.getInstance("Default"). + * {@code SSLContext.getInstance("Default")}. * If successful, that object is made the default SSL context and returned. * *

    The default context is immediately @@ -106,8 +106,8 @@ public class SSLContext { * @param context the SSLContext * @throws NullPointerException if context is null * @throws SecurityException if a security manager exists and its - * checkPermission method does not allow - * SSLPermission("setDefaultSSLContext") + * {@code checkPermission} method does not allow + * {@code SSLPermission("setDefaultSSLContext")} * @since 1.6 */ public static synchronized void setDefault(SSLContext context) { @@ -122,7 +122,7 @@ public class SSLContext { } /** - * Returns a SSLContext object that implements the + * Returns a {@code SSLContext} object that implements the * specified secure socket protocol. * *

    This method traverses the list of registered security Providers, @@ -141,7 +141,7 @@ public class SSLContext { * Documentation * for information about standard protocol names. * - * @return the new SSLContext object. + * @return the new {@code SSLContext} object. * * @exception NoSuchAlgorithmException if no Provider supports a * SSLContextSpi implementation for the @@ -159,7 +159,7 @@ public class SSLContext { } /** - * Returns a SSLContext object that implements the + * Returns a {@code SSLContext} object that implements the * specified secure socket protocol. * *

    A new SSLContext object encapsulating the @@ -179,7 +179,7 @@ public class SSLContext { * * @param provider the name of the provider. * - * @return the new SSLContext object. + * @return the new {@code SSLContext} object. * * @throws NoSuchAlgorithmException if a SSLContextSpi * implementation for the specified protocol is not @@ -202,7 +202,7 @@ public class SSLContext { } /** - * Returns a SSLContext object that implements the + * Returns a {@code SSLContext} object that implements the * specified secure socket protocol. * *

    A new SSLContext object encapsulating the @@ -219,7 +219,7 @@ public class SSLContext { * * @param provider an instance of the provider. * - * @return the new SSLContext object. + * @return the new {@code SSLContext} object. * * @throws NoSuchAlgorithmException if a SSLContextSpi * implementation for the specified protocol is not available @@ -239,22 +239,22 @@ public class SSLContext { } /** - * Returns the protocol name of this SSLContext object. + * Returns the protocol name of this {@code SSLContext} object. * *

    This is the same name that was specified in one of the - * getInstance calls that created this - * SSLContext object. + * {@code getInstance} calls that created this + * {@code SSLContext} object. * - * @return the protocol name of this SSLContext object. + * @return the protocol name of this {@code SSLContext} object. */ public final String getProtocol() { return this.protocol; } /** - * Returns the provider of this SSLContext object. + * Returns the provider of this {@code SSLContext} object. * - * @return the provider of this SSLContext object + * @return the provider of this {@code SSLContext} object */ public final Provider getProvider() { return this.provider; @@ -283,31 +283,35 @@ public class SSLContext { } /** - * Returns a SocketFactory object for this + * Returns a {@code SocketFactory} object for this * context. * - * @return the SocketFactory object + * @return the {@code SocketFactory} object + * @throws UnsupportedOperationException if the underlying provider + * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the init() has not been called + * initialization and the {@code init()} has not been called */ public final SSLSocketFactory getSocketFactory() { return contextSpi.engineGetSocketFactory(); } /** - * Returns a ServerSocketFactory object for + * Returns a {@code ServerSocketFactory} object for * this context. * - * @return the ServerSocketFactory object + * @return the {@code ServerSocketFactory} object + * @throws UnsupportedOperationException if the underlying provider + * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the init() has not been called + * initialization and the {@code init()} has not been called */ public final SSLServerSocketFactory getServerSocketFactory() { return contextSpi.engineGetServerSocketFactory(); } /** - * Creates a new SSLEngine using this context. + * Creates a new {@code SSLEngine} using this context. *

    * Applications using this factory method are providing no hints * for an internal session reuse strategy. If hints are desired, @@ -317,11 +321,11 @@ public class SSLContext { * Some cipher suites (such as Kerberos) require remote hostname * information, in which case this factory method should not be used. * - * @return the SSLEngine object + * @return the {@code SSLEngine} object * @throws UnsupportedOperationException if the underlying provider * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the init() has not been called + * initialization and the {@code init()} has not been called * @since 1.5 */ public final SSLEngine createSSLEngine() { @@ -338,7 +342,7 @@ public class SSLContext { } /** - * Creates a new SSLEngine using this context using + * Creates a new {@code SSLEngine} using this context using * advisory peer information. *

    * Applications using this factory method are providing hints @@ -349,11 +353,11 @@ public class SSLContext { * * @param peerHost the non-authoritative name of the host * @param peerPort the non-authoritative port - * @return the new SSLEngine object + * @return the new {@code SSLEngine} object * @throws UnsupportedOperationException if the underlying provider * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the init() has not been called + * initialization and the {@code init()} has not been called * @since 1.5 */ public final SSLEngine createSSLEngine(String peerHost, int peerPort) { diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java index 269ed8502e6..966524da9fb 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -29,7 +29,7 @@ import java.security.*; /** * This class defines the Service Provider Interface (SPI) - * for the SSLContext class. + * for the {@code SSLContext} class. * *

    All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation @@ -52,31 +52,35 @@ public abstract class SSLContextSpi { SecureRandom sr) throws KeyManagementException; /** - * Returns a SocketFactory object for this + * Returns a {@code SocketFactory} object for this * context. * - * @return the SocketFactory object + * @return the {@code SocketFactory} object + * @throws UnsupportedOperationException if the underlying provider + * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the engineInit() + * initialization and the {@code engineInit()} * has not been called * @see javax.net.ssl.SSLContext#getSocketFactory() */ protected abstract SSLSocketFactory engineGetSocketFactory(); /** - * Returns a ServerSocketFactory object for + * Returns a {@code ServerSocketFactory} object for * this context. * - * @return the ServerSocketFactory object + * @return the {@code ServerSocketFactory} object + * @throws UnsupportedOperationException if the underlying provider + * does not implement the operation. * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the engineInit() + * initialization and the {@code engineInit()} * has not been called * @see javax.net.ssl.SSLContext#getServerSocketFactory() */ protected abstract SSLServerSocketFactory engineGetServerSocketFactory(); /** - * Creates a new SSLEngine using this context. + * Creates a new {@code SSLEngine} using this context. *

    * Applications using this factory method are providing no hints * for an internal session reuse strategy. If hints are desired, @@ -86,9 +90,9 @@ public abstract class SSLContextSpi { * Some cipher suites (such as Kerberos) require remote hostname * information, in which case this factory method should not be used. * - * @return the SSLEngine Object + * @return the {@code SSLEngine} Object * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the engineInit() + * initialization and the {@code engineInit()} * has not been called * * @see SSLContext#createSSLEngine() @@ -98,7 +102,7 @@ public abstract class SSLContextSpi { protected abstract SSLEngine engineCreateSSLEngine(); /** - * Creates a SSLEngine using this context. + * Creates a {@code SSLEngine} using this context. *

    * Applications using this factory method are providing hints * for an internal session reuse strategy. @@ -108,9 +112,9 @@ public abstract class SSLContextSpi { * * @param host the non-authoritative name of the host * @param port the non-authoritative port - * @return the SSLEngine Object + * @return the {@code SSLEngine} Object * @throws IllegalStateException if the SSLContextImpl requires - * initialization and the engineInit() + * initialization and the {@code engineInit()} * has not been called * * @see SSLContext#createSSLEngine(String, int) @@ -120,19 +124,19 @@ public abstract class SSLContextSpi { protected abstract SSLEngine engineCreateSSLEngine(String host, int port); /** - * Returns a server SSLSessionContext object for + * Returns a server {@code SSLSessionContext} object for * this context. * - * @return the SSLSessionContext object + * @return the {@code SSLSessionContext} object * @see javax.net.ssl.SSLContext#getServerSessionContext() */ protected abstract SSLSessionContext engineGetServerSessionContext(); /** - * Returns a client SSLSessionContext object for + * Returns a client {@code SSLSessionContext} object for * this context. * - * @return the SSLSessionContext object + * @return the {@code SSLSessionContext} object * @see javax.net.ssl.SSLContext#getClientSessionContext() */ protected abstract SSLSessionContext engineGetClientSessionContext(); diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java index 64110880258..4539513c74b 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,15 +37,15 @@ import java.nio.ReadOnlyBufferException; *

    * The secure communications modes include: