From d66549f6f6097f1bb11e7b8b1be404c0ef1bb9de Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 27 Jan 2016 14:12:05 +0530 Subject: [PATCH 01/44] 8147077: IllegalArgumentException thrown by api/java_awt/Component/FlipBufferStrategy/indexTGF_General Reviewed-by: flar, arapte --- .../unix/classes/sun/awt/X11GraphicsConfig.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 1b3c4fa2e23..27b97818dee 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsConfig.java @@ -452,8 +452,12 @@ public class X11GraphicsConfig extends GraphicsConfiguration public VolatileImage createBackBufferImage(Component target, long backBuffer) { + // it is possible for the component to have size 0x0, adjust it to + // be at least 1x1 to avoid IAE + int w = Math.max(1, target.getWidth()); + int h = Math.max(1, target.getHeight()); return new SunVolatileImage(target, - target.getWidth(), target.getHeight(), + w, h, Long.valueOf(backBuffer)); } From a03c63e14607ae968353de58518f96ea9e3f0d19 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 27 Jan 2016 14:13:48 +0530 Subject: [PATCH 02/44] 8148127: IllegalArgumentException thrown by JCK test api/java_awt/Component/FlipBufferStrategy/indexTGF_General in opengl pipeline Reviewed-by: flar, arapte --- .../classes/sun/java2d/opengl/WGLGraphicsConfig.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java b/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java index ec42d3142ad..1e78384130c 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java @@ -323,8 +323,12 @@ public class WGLGraphicsConfig @Override public VolatileImage createBackBuffer(WComponentPeer peer) { Component target = (Component)peer.getTarget(); + // it is possible for the component to have size 0x0, adjust it to + // be at least 1x1 to avoid IAE + int w = Math.max(1, target.getWidth()); + int h = Math.max(1, target.getHeight()); return new SunVolatileImage(target, - target.getWidth(), target.getHeight(), + w, h, Boolean.TRUE); } From b0fddb9f8045cca10b4e757d8d187af7fb117405 Mon Sep 17 00:00:00 2001 From: Manajit Halder Date: Fri, 29 Jan 2016 15:21:55 +0530 Subject: [PATCH 03/44] 8075964: Test java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.html fails intermittently with timeout error Reviewed-by: arapte, ssadetsky --- .../java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/test/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java b/jdk/test/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java index 2f959ef73ab..53824a14ebf 100644 --- a/jdk/test/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java +++ b/jdk/test/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java @@ -71,7 +71,6 @@ public class TitleBarDoubleClick extends Applet implements MouseListener, frame.addMouseListener(this); frame.addWindowListener(this); frame.setVisible(true); - Util.waitForIdle(robot); }// start() // Move the mouse into the title bar and double click to maximize the From 25f9c2a19685cc4ce0b46c9ab9114a4d7cceaa9f Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Mon, 1 Feb 2016 15:39:02 +0530 Subject: [PATCH 04/44] 8022640: ServiceRegistry (used by ImageIO) lack synchronization Reviewed-by: prr, psadhukhan --- .../javax/imageio/spi/ServiceRegistry.java | 24 ++-- .../imageio/spi/ServiceRegistrySyncTest.java | 131 ++++++++++++++++++ 2 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 jdk/test/javax/imageio/spi/ServiceRegistrySyncTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java b/jdk/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java index a68978d074d..abe85a2a79d 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java @@ -759,7 +759,7 @@ class SubRegistry { this.category = category; } - public boolean registerServiceProvider(Object provider) { + public synchronized boolean registerServiceProvider(Object provider) { Object oprovider = map.get(provider.getClass()); boolean present = oprovider != null; @@ -781,7 +781,7 @@ class SubRegistry { * * @return true if the provider was previously registered. */ - public boolean deregisterServiceProvider(Object provider) { + public synchronized boolean deregisterServiceProvider(Object provider) { Object oprovider = map.get(provider.getClass()); if (provider == oprovider) { @@ -797,22 +797,23 @@ class SubRegistry { return false; } - public boolean contains(Object provider) { + public synchronized boolean contains(Object provider) { Object oprovider = map.get(provider.getClass()); return oprovider == provider; } - public boolean setOrdering(Object firstProvider, - Object secondProvider) { + public synchronized boolean setOrdering(Object firstProvider, + Object secondProvider) { return poset.setOrdering(firstProvider, secondProvider); } - public boolean unsetOrdering(Object firstProvider, - Object secondProvider) { + public synchronized boolean unsetOrdering(Object firstProvider, + Object secondProvider) { return poset.unsetOrdering(firstProvider, secondProvider); } - public Iterator getServiceProviders(boolean useOrdering) { + public synchronized Iterator getServiceProviders + (boolean useOrdering) { if (useOrdering) { return poset.iterator(); } else { @@ -821,11 +822,12 @@ class SubRegistry { } @SuppressWarnings("unchecked") - public T getServiceProviderByClass(Class providerClass) { + public synchronized T getServiceProviderByClass + (Class providerClass) { return (T)map.get(providerClass); } - public void clear() { + public synchronized void clear() { Iterator iter = map.values().iterator(); while (iter.hasNext()) { Object provider = iter.next(); @@ -839,7 +841,7 @@ class SubRegistry { poset.clear(); } - public void finalize() { + public synchronized void finalize() { clear(); } } diff --git a/jdk/test/javax/imageio/spi/ServiceRegistrySyncTest.java b/jdk/test/javax/imageio/spi/ServiceRegistrySyncTest.java new file mode 100644 index 00000000000..5fa90a227bd --- /dev/null +++ b/jdk/test/javax/imageio/spi/ServiceRegistrySyncTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8022640 + * @summary Test verifies whether ServiceProvider API's of + * ServiceRegistry are safe for concurrent access. + * @run main ServiceRegistrySyncTest + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Locale; +import javax.imageio.spi.ImageInputStreamSpi; +import javax.imageio.spi.ServiceRegistry; +import javax.imageio.stream.ImageInputStream; + +public class ServiceRegistrySyncTest { + public static void main(String[] args) throws InterruptedException { + + final ArrayList> services = new ArrayList>(); + services.add(ImageInputStreamSpi.class); + + final ServiceRegistry reg = new ServiceRegistry(services.iterator()); + + //create new thread for Registerer and Consumer Class + Thread registerer = new Thread(new Registerer(reg)); + Thread consumer = new Thread(new Consumer(reg)); + + //run both registerer and consumer thread parallely + registerer.start(); + consumer.start(); + } + + static class Consumer implements Runnable { + private final ServiceRegistry reg; + boolean go = true; + int duration; + long start, end; + + public Consumer(ServiceRegistry r) { + reg = r; + //set 5000ms duration to run the test + duration = 5000; + } + + @Override + public void run() { + start = System.currentTimeMillis(); + end = start + duration; + while (start < end) { + //access the ServiceProvider API + reg.getServiceProviders(ImageInputStreamSpi.class, true); + start = System.currentTimeMillis(); + } + } + } + + static class Registerer implements Runnable { + private final ServiceRegistry reg; + boolean go = true; + int duration; + long start, end; + + public Registerer(ServiceRegistry r) { + reg = r; + //set 5000ms duration to run the test + duration = 5000; + } + + @Override + public void run() { + final int N = 20; + + MyService[] services = new MyService[N]; + for (int i = 0; i < N; i++) { + services[i] = new MyService(); + } + start = System.currentTimeMillis(); + end = start + duration; + while (start < end) { + //access the ServiceProvider API's + for (int i = 0; i < N; i++) { + reg.registerServiceProvider(services[i]); + } + for (int i = 0; i < N; i++) { + reg.deregisterServiceProvider(services[i]); + } + start = System.currentTimeMillis(); + } + } + } +} + +class MyService extends ImageInputStreamSpi { + public MyService() { + } + + @Override + public String getDescription(Locale locale) { + return null; + } + + @Override + public ImageInputStream createInputStreamInstance + (Object input, boolean useCache, File cacheDir) throws IOException { + return null; + } +} From 8148b2b20393b7cd083d70d88b28c9712a43370a Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 2 Feb 2016 11:50:24 +0530 Subject: [PATCH 05/44] 8147413: api/java_awt/Image/MultiResolutionImage/index.html\#MultiResolutionRenderingHints[test_VALUE_RESOLUTION_VARIANT_BASE] started to fail Reviewed-by: alexsch, flar --- .../java.desktop/share/classes/sun/java2d/SunGraphics2D.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 869271d1e0c..967077d6585 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -3118,8 +3118,7 @@ public final class SunGraphics2D invalidateTransform(); } return result; - } else if (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_BASE - && (img instanceof MultiResolutionImage)) { + } else if (img instanceof MultiResolutionImage) { // get scaled destination image size int width = img.getWidth(observer); From c453a540b5e015254a551c9619b78bda24c084bb Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Tue, 2 Feb 2016 14:19:55 +0530 Subject: [PATCH 06/44] 6180449: PIT: Text in TextArea scrolls to its left one char when selecting the text from the end Reviewed-by: ssadetsky, psadhukhan --- .../native/libawt/windows/awt_TextArea.cpp | 3 - .../TextAreaScrolling/TextAreaScrolling.java | 107 ++++++++++++++++++ 2 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp index 427a0b8e3e8..0b96ad99a4b 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp @@ -73,10 +73,7 @@ AwtTextArea* AwtTextArea::Create(jobject peer, jobject parent) } void AwtTextArea::EditSetSel(CHARRANGE &cr) { - // Fix for 5003402: added restoring/hiding selection to enable automatic scrolling - SendMessage(EM_HIDESELECTION, FALSE, TRUE); SendMessage(EM_EXSETSEL, 0, reinterpret_cast(&cr)); - SendMessage(EM_HIDESELECTION, TRUE, TRUE); // 6417581: force expected drawing if (IS_WINVISTA && cr.cpMin == cr.cpMax) { ::InvalidateRect(GetHWnd(), NULL, TRUE); diff --git a/jdk/test/java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java b/jdk/test/java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java new file mode 100644 index 00000000000..15508492d65 --- /dev/null +++ b/jdk/test/java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6180449 + @summary TextArea scrolls to its left when selecting the text from the end. + @run main TextAreaScrolling + */ + +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.event.InputEvent; + +public class TextAreaScrolling { + Frame mainFrame; + TextArea textArea; + Robot robot; + + TextAreaScrolling() { + mainFrame = new Frame(); + mainFrame.setSize(200, 200); + mainFrame.setLocation(200, 200); + + textArea = new TextArea(); + textArea.setText("1234 5678"); + textArea.setSelectionStart(3); + textArea.setSelectionStart(4); + mainFrame.add(textArea); + mainFrame.setVisible(true); + textArea.requestFocusInWindow(); + + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + } catch (Exception ex) { + dispose(); + System.exit(0); + throw new RuntimeException("Robot Creation Failed"); + } + } + + public void dispose() { + if (mainFrame != null) { + mainFrame.dispose(); + } + } + + public void performTest() { + Point loc = textArea.getLocationOnScreen(); + Rectangle textAreaBounds = new Rectangle(); + textArea.getBounds(textAreaBounds); + + // Move mouse at center in first row of TextArea. + robot.mouseMove(loc.x + textAreaBounds.width / 2, loc.y + 5); + + // Perform selection by scrolling to left from end of char sequence. + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseMove(textAreaBounds.x - 5, loc.y + 5); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + // Perform double click on beginning word of TextArea + robot.mouseMove(loc.x + 5, loc.y + 5); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(100); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(100); + + if (textArea.getSelectedText().contentEquals("5678")) { + dispose(); + throw new RuntimeException ("TextArea over scrolled towards left" + + "Expected selected text: '1234 ' and for mac '1234'" + + "Actual selected text: 5678"); + } + } + + public static void main(String argv[]) throws RuntimeException { + TextAreaScrolling test = new TextAreaScrolling(); + test.performTest(); + test.dispose(); + } +} From 51296cb329d18378ae868139d2276145aee6a047 Mon Sep 17 00:00:00 2001 From: Ajit Ghaisas Date: Tue, 2 Feb 2016 15:57:42 +0530 Subject: [PATCH 07/44] 8005918: [TESTBUG] There are no 'Frame Enter' messages for both frames, only 'Button Enter' message Reviewed-by: arapte, alexsch --- .../LightweightEventTest.java | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 jdk/test/java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java diff --git a/jdk/test/java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java b/jdk/test/java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java new file mode 100644 index 00000000000..4c729282101 --- /dev/null +++ b/jdk/test/java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Test of mouse move messages to lightweight components + * @library ../../regtesthelpers + * @build Util + * @compile LightweightEventTest.java + * @run main LightweightEventTest + */ +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.AWTException; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.SwingUtilities; +import test.java.awt.regtesthelpers.Util; + + +/* +There are 3 steps to this test : +1. Two frames are created one with heavy weight component and + another with light weight component. Each frame has a centrally placed + button +2. Mouse is dragged along diagonals of each window using Robot object +3. Events are noted for mouse in and out of frames & buttons and asserted +*/ + +public class LightweightEventTest { + + private static EventBug HeavyComponent; + private static EventBug LightComponent; + private static Robot testRobot; + + public static void main(String[] args) throws Throwable { + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + + try { + testRobot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Could not initiate a drag operation"); + } + + testRobot.waitForIdle(); + + // Method performing auto test operation + boolean result = test(); + + disposeTestUI(); + + if (result == false) { + throw new RuntimeException("Test FAILED!"); + } + } + + private static boolean test() { + // Test events for HeavyComponent + Point loc = HeavyComponent.getLocationOnScreen(); + Dimension size = HeavyComponent.getSize(); + + Util.mouseMove(testRobot, + new Point((int) loc.x + 4, (int) loc.y + 4), + new Point((int) loc.x + size.width, (int) loc.y + size.height)); + + testRobot.waitForIdle(); + + boolean HeavyComponentAssert = HeavyComponent.assertEvents(2, 1); + + // Test events for LightComponent + loc = LightComponent.getLocationOnScreen(); + size = LightComponent.getSize(); + + Util.mouseMove(testRobot, + new Point((int) loc.x + 4, (int) loc.y + 4), + new Point((int) loc.x + size.width, (int) loc.y + size.height)); + + testRobot.waitForIdle(); + + boolean LightComponentAssert = LightComponent.assertEvents(2, 1); + + return (HeavyComponentAssert && LightComponentAssert); + } + + private static void constructTestUI() { + // here, create the items that will be tested for correct behavior + HeavyComponent = new EventBug(); + Button b = (Button) HeavyComponent.add("Center", new Button("Heavy")); + + LightComponent = new EventBug(); + BorderedLabel b1 = (BorderedLabel) LightComponent.add("Center", + new BorderedLabel("Lite")); + + HeavyComponent.addListeners(b); + LightComponent.addListeners(b1); + + LightComponent.setLocation(200, 0); + HeavyComponent.setVisible(true); + LightComponent.setVisible(true); + } + + private static void disposeTestUI() { + HeavyComponent.setVisible(false); + LightComponent.setVisible(false); + + HeavyComponent.dispose(); + LightComponent.dispose(); + } +} + +/* + * Lightweight component + */ +class BorderedLabel extends Component { + + boolean superIsButton = false; + String labelString; + + BorderedLabel(String labelString) { + this.labelString = labelString; + + Component thisComponent = this; + superIsButton = (thisComponent instanceof Button); + if (superIsButton) { + ((Button) thisComponent).setLabel(labelString); + } + } + + @Override + public Dimension getMinimumSize() { + Dimension minSize = new Dimension(); + + if (superIsButton) { + minSize = super.getMinimumSize(); + } else { + + Graphics g = getGraphics(); + FontMetrics metrics = g.getFontMetrics(); + + minSize.width = metrics.stringWidth(labelString) + 14; + minSize.height = metrics.getMaxAscent() + + metrics.getMaxDescent() + 9; + + g.dispose(); + g = null; + } + return minSize; + } + + @Override + public Dimension getPreferredSize() { + Dimension prefSize; + if (superIsButton) { + prefSize = super.getPreferredSize(); + } else { + prefSize = getMinimumSize(); + } + return prefSize; + } + + @Override + public void paint(Graphics g) { + + super.paint(g); + Rectangle bounds = getBounds(); + if (superIsButton) { + return; + } + Dimension size = getSize(); + Color oldColor = g.getColor(); + + // draw border + g.setColor(getBackground()); + g.fill3DRect(0, 0, size.width, size.height, false); + g.fill3DRect(3, 3, size.width - 6, size.height - 6, true); + + // draw text + FontMetrics metrics = g.getFontMetrics(); + int centerX = size.width / 2; + int centerY = size.height / 2; + int textX = centerX - (metrics.stringWidth(labelString) / 2); + int textY = centerY + + ((metrics.getMaxAscent() + metrics.getMaxDescent()) / 2); + g.setColor(getForeground()); + g.drawString(labelString, textX, textY); + + g.setColor(oldColor); + } +} // class BorderedLabel + +class EventBug extends Container { + + Frame testFrame; + int frameEnters = 0; + int frameExits = 0; + int buttonEnters = 0; + int buttonExits = 0; + + public EventBug() { + super(); + testFrame = new Frame(); + testFrame.setLayout(new BorderLayout()); + this.setLayout(new BorderLayout()); + testFrame.add("Center", this); + testFrame.pack(); + testFrame.setVisible(true); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100, 100); + } + + @Override + public Insets getInsets() { + return new Insets(20, 20, 20, 20); + } + + public boolean assertEvents(int expectedFrameEnterEvents, + int expectedButtonEnterEvents) { + return (frameEnters == expectedFrameEnterEvents) + && (buttonEnters == expectedButtonEnterEvents); + } + + // Forward to the Window + @Override + public void setLocation(int x, int y) { + testFrame.setLocation(x, y); + } + + @Override + public void setVisible(boolean b) { + testFrame.setVisible(b); + } + + public void dispose() { + testFrame.dispose(); + } + + // Add listeners to Frame and button + public void addListeners(Component b) { + b.setName("Button"); + b.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + buttonEnters++; + } + + @Override + public void mouseExited(MouseEvent e) { + buttonExits++; + } + + }); + testFrame.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + frameEnters++; + } + + @Override + public void mouseExited(MouseEvent e) { + frameExits++; + } + }); + } +} // class EventBug From f7b4333c0b75c13bbb36d2edd589e593ca986167 Mon Sep 17 00:00:00 2001 From: Anton Litvinov Date: Tue, 2 Feb 2016 16:33:03 +0300 Subject: [PATCH 08/44] 8139581: AWT components are not drawn after removal and addition to a container Reviewed-by: ssadetsky, alexsch --- .../unix/classes/sun/awt/X11/XBaseWindow.java | 4 - ...ComponentIsNotDrawnAfterRemoveAddTest.java | 187 ++++++++++++++++++ 2 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 jdk/test/java/awt/Paint/ComponentIsNotDrawnAfterRemoveAddTest/ComponentIsNotDrawnAfterRemoveAddTest.java diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java index c8534aa36e3..221093fa66b 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java @@ -79,7 +79,6 @@ public class XBaseWindow { static enum InitialiseState { INITIALISING, - NOT_INITIALISED, INITIALISED, FAILED_INITIALISATION }; @@ -122,7 +121,6 @@ public class XBaseWindow { */ void instantPreInit(XCreateWindowParams params) { state_lock = new StateLock(); - initialising = InitialiseState.NOT_INITIALISED; } /** @@ -131,7 +129,6 @@ public class XBaseWindow { */ void preInit(XCreateWindowParams params) { state_lock = new StateLock(); - initialising = InitialiseState.NOT_INITIALISED; embedded = Boolean.TRUE.equals(params.get(EMBEDDED)); visible = Boolean.TRUE.equals(params.get(VISIBLE)); @@ -223,7 +220,6 @@ public class XBaseWindow { return false; } return true; - case NOT_INITIALISED: case FAILED_INITIALISATION: return false; default: diff --git a/jdk/test/java/awt/Paint/ComponentIsNotDrawnAfterRemoveAddTest/ComponentIsNotDrawnAfterRemoveAddTest.java b/jdk/test/java/awt/Paint/ComponentIsNotDrawnAfterRemoveAddTest/ComponentIsNotDrawnAfterRemoveAddTest.java new file mode 100644 index 00000000000..186b572df44 --- /dev/null +++ b/jdk/test/java/awt/Paint/ComponentIsNotDrawnAfterRemoveAddTest/ComponentIsNotDrawnAfterRemoveAddTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 8139581 + @summary AWT components are not drawn after removal and addition to a container + @author Anton Litvinov + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Canvas; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.util.ArrayList; + +public class ComponentIsNotDrawnAfterRemoveAddTest { + private final Frame frame; + private final Panel panel; + private final ArrayList compList = new ArrayList(); + + public ComponentIsNotDrawnAfterRemoveAddTest() { + frame = new Frame("ComponentIsNotDrawnAfterRemoveAddTest"); + frame.setSize(500, 500); + frame.setLocation(200, 200); + frame.setLayout(null); + frame.setBackground(Color.RED); + + panel = new Panel(); + panel.setLayout(null); + panel.setBounds(25, 100, 455, 295); + panel.setBackground(Color.GREEN); + + for (int i = 0; i < 10; i++) { + TestCanvas canv1 = new TestCanvas(); + canv1.setBounds(i * 45 + 5, 15, 30 + i, 30 + i); + panel.add(canv1); + compList.add(canv1); + + TestButton btn1 = new TestButton(); + btn1.setBounds(i * 45 + 5, 60, 30 + i, 30 + i); + panel.add(btn1); + compList.add(btn1); + + TestCanvas canv2 = new TestCanvas(); + canv2.setBounds(i * 45 + 5, 105, 30 + i, 30 + i); + panel.add(canv2); + compList.add(canv2); + + TestButton btn2 = new TestButton(); + btn2.setBounds(i * 45 + 5, 150, 30 + i, 30 + i); + panel.add(btn2); + compList.add(btn2); + + TestCanvas canv3 = new TestCanvas(); + canv3.setBounds(i * 45 + 5, 195, 30 + i, 30 + i); + panel.add(canv3); + compList.add(canv3); + + TestButton btn3 = new TestButton(); + btn3.setBounds(i * 45 + 5, 240, 30 + i, 30 + i); + panel.add(btn3); + compList.add(btn3); + } + + frame.add(panel); + frame.setVisible(true); + } + + private void runTest() { + try { + doSleep(1500); + checkTestableComponents(); + + for (int i = 0; i < 5; i++) { + System.err.println(String.format("Test iteration #%d:", i)); + + frame.remove(panel); + frame.invalidate(); + frame.validate(); + frame.add(panel); + + doSleep(1500); + checkTestableComponents(); + } + } finally { + frame.dispose(); + } + } + + private void doSleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + private void checkTestableComponents() throws RuntimeException { + int notDrawnCompsCount = 0; + for (Testable comp : compList) { + if (!comp.wasPaintCalled()) { + notDrawnCompsCount++; + } else { + comp.resetPaintCalledFlag(); + } + } + if (notDrawnCompsCount > 0) { + throw new RuntimeException(String.format( + "'paint' method of %d components was not called.", notDrawnCompsCount)); + } + } + + private interface Testable { + boolean wasPaintCalled(); + void resetPaintCalledFlag(); + } + + private static class TestCanvas extends Canvas implements Testable { + private volatile boolean paintWasCalled = false; + + @Override + public void paint(Graphics g) { + paintWasCalled = true; + super.paint(g); + g.setColor(Color.BLUE); + g.fillRect(0, 0, getWidth(), getHeight()); + } + + @Override + public boolean wasPaintCalled() { + return paintWasCalled; + } + + @Override + public void resetPaintCalledFlag() { + paintWasCalled = false; + } + } + + private static class TestButton extends Button implements Testable { + private volatile boolean paintWasCalled = false; + + @Override + public void paint(Graphics g) { + paintWasCalled = true; + super.paint(g); + g.setColor(Color.YELLOW); + g.fillRect(0, 0, 15, 15); + } + + @Override + public boolean wasPaintCalled() { + return paintWasCalled; + } + + @Override + public void resetPaintCalledFlag() { + paintWasCalled = false; + } + } + + public static void main(String[] args) { + new ComponentIsNotDrawnAfterRemoveAddTest().runTest(); + } +} From aedb4650c96c24a067949a57595134c81af7b5eb Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Tue, 2 Feb 2016 17:14:00 -0500 Subject: [PATCH 09/44] 8079408: Reimplement TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData with Unified Logging TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData have been reimplemented using Unified logging. Reviewed-by: iklam, coleenp, dholmes, jiangli, hseigel, rprotacio --- jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh | 4 ++-- jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh | 4 ++-- .../instrument/appendToClassLoaderSearch/ClassUnloadTest.sh | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh index a70e6019eaa..3872f813ffd 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -XX:+TraceClassLoading -cp . \ + -verbose:class -Xlog:classload -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter cross # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh index 678b98e5be0..198cd70827a 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -XX:+TraceClassLoading -cp . \ + -verbose:class -Xlog:classload -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter one-way # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh index 1b93b3043a9..f5bb3b83179 100644 --- a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh +++ b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -80,5 +80,5 @@ $JAR ${TESTTOOLVMOPTS} -cfm "${TESTCLASSES}"/ClassUnloadTest.jar "${MANIFEST}" \ # Finally we run the test (cd "${TESTCLASSES}"; \ - $JAVA ${TESTVMOPTS} -Xverify:none -XX:+TraceClassUnloading \ + $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:classunload \ -javaagent:ClassUnloadTest.jar ClassUnloadTest "${OTHERDIR}" Bar.jar) From cec98119816517ee2b88215cb711930b85213740 Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Thu, 4 Feb 2016 11:16:23 +0530 Subject: [PATCH 10/44] 8062946: Transparent JDialog will lose transparency upon iconify/deiconify sequence Reviewed-by: arapte, alexsch --- .../native/libawt/windows/awt_Window.cpp | 3 + .../Transparency/TransparencyTest.java | 119 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 jdk/test/javax/swing/JDialog/Transparency/TransparencyTest.java diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index 096bf4f9f14..8e066a3396b 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -382,6 +382,9 @@ MsgRouting AwtWindow::WmWindowPosChanged(LPARAM windowPos) { if (wp->flags & SWP_HIDEWINDOW) { EnableTranslucency(FALSE); } + if (wp->flags & SWP_SHOWWINDOW) { + EnableTranslucency(TRUE); + } return mrDoDefault; } diff --git a/jdk/test/javax/swing/JDialog/Transparency/TransparencyTest.java b/jdk/test/javax/swing/JDialog/Transparency/TransparencyTest.java new file mode 100644 index 00000000000..cb2ba23041d --- /dev/null +++ b/jdk/test/javax/swing/JDialog/Transparency/TransparencyTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + @test + @bug 8062946 + @summary Verify Transparency upon iconify/deiconify sequence + @run main TransparencyTest + */ +import java.awt.Color; +import java.awt.Point; +import java.awt.Robot; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class TransparencyTest { + + private static JFrame frame; + private static JDialog dialog; + private static JDialog backgroundDialog; + private static final int WIDTH = 250; + private static final int HEIGHT = 250; + private static final float OPACITY = 0.60f; + private static Point dlgPos; + + public static void createAndShowGUI() { + frame = new JFrame("JFrame"); + frame.setSize(WIDTH, HEIGHT); + frame.setLocation(100, 300); + + dialog = new JDialog(frame, false); + dialog.setSize(250, 250); + dialog.setUndecorated(true); + dialog.setLocation(400, 300); + dlgPos = dialog.getLocation(); + backgroundDialog = new JDialog(frame, false); + backgroundDialog.setSize(250, 250); + backgroundDialog.getContentPane().setBackground(Color.red); + backgroundDialog.setLocation(dlgPos.x, dlgPos.y); + + frame.setVisible(true); + backgroundDialog.setVisible(true); + dialog.setVisible(true); + } + + public static void main(String[] args) throws Exception { + + Robot robot = new Robot(); + // create a GUI + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + robot.waitForIdle(); + Color opaque = robot.getPixelColor(dlgPos.x + 100, dlgPos.y + 100); + + // set Dialog Opacity + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + dialog.setOpacity(OPACITY); + } + }); + robot.waitForIdle(); + + // iconify frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(JFrame.ICONIFIED); + } + }); + robot.waitForIdle(); + + // deiconify frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(JFrame.NORMAL); + } + }); + robot.waitForIdle(); + + Color transparent = robot.getPixelColor(dlgPos.x + 100, dlgPos.y + 100); + if (transparent.equals(opaque)) { + frame.dispose(); + throw new RuntimeException("JDialog transparency lost " + + "upon iconify/deiconify sequence"); + } + frame.dispose(); + } +} From 5b2d0bfd39505ef936f90d3ad1125e51a1dba0bb Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Thu, 4 Feb 2016 14:27:16 +0300 Subject: [PATCH 11/44] 8145780: create a simple test for TIFF tag sets Reviewed-by: bpb, yan --- .../imageio/plugins/tiff/TIFFTagSetTest.java | 367 ++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 jdk/test/javax/imageio/plugins/tiff/TIFFTagSetTest.java diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFTagSetTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFTagSetTest.java new file mode 100644 index 00000000000..8ac980ec890 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFTagSetTest.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8145780 + * @author a.stepanov + * @summary Some checks for TIFFTag, TIFFTagSet + * @run main TIFFTagSetTest + */ + + +import javax.imageio.plugins.tiff.*; + +import java.lang.reflect.Method; +import java.util.*; + + +public class TIFFTagSetTest { + + public static class TestSet extends TIFFTagSet { + + public static final TIFFTagSet SOME_SET = + new TIFFTagSet(new ArrayList()); + + private static TestSet theInstance = null; + + public static final int TAG_NUM_1 = 0; + public static final int TAG_NUM_2 = 666; + public static final int TAG_NUM_3 = Integer.MAX_VALUE; + + public static final String TAG_NAME_1 = "tag-1"; + public static final String TAG_NAME_2 = "tag-2"; + public static final String TAG_NAME_3 = "tag-3"; + + public static final int VALUE_1 = 123; + public static final int VALUE_2 = 321; + + public static final String VALUE_NAME_1 = "value-1"; + public static final String VALUE_NAME_2 = "value-2"; + + public static final int VALUE_COUNT = 500; + + + static class Tag1 extends TIFFTag { + public Tag1() { + super(TAG_NAME_1, + TAG_NUM_1, + 1 << TIFF_SHORT | 1 << TIFF_LONG, + VALUE_COUNT); + } + } + + static class Tag2 extends TIFFTag { + public Tag2() { + super(TAG_NAME_2, + TAG_NUM_2, + 1 << TIFF_DOUBLE); + + addValueName(VALUE_1, VALUE_NAME_1); + addValueName(VALUE_2, VALUE_NAME_2); + } + } + + static class Tag3 extends TIFFTag { + public Tag3() { + super(TAG_NAME_3, + TAG_NUM_3, + SOME_SET); + } + } + + private static List tags; + + private static void initTags() { + + tags = new ArrayList(); + + tags.add(new TestSet.Tag1()); + tags.add(new TestSet.Tag2()); + tags.add(new TestSet.Tag3()); + } + + private TestSet() { super(tags); } + + public synchronized static TestSet getInstance() { + + if (theInstance == null) { + initTags(); + theInstance = new TestSet(); + tags = null; + } + return theInstance; + } + } + + + private static void checkEq(String what, Object v, Object ref) { + if (v == null) { + throw new RuntimeException(what + " is null"); + } else if (!v.equals(ref)) { + throw new RuntimeException("invalid " + what + + ", expected: " + ref + ", got: " + v); + } + } + + + + + private final String className; + public TIFFTagSetTest(String cName) { className = cName; } + + public void testNamesNumbers() throws ReflectiveOperationException { + + Class c = Class.forName(className); + + Method getInstance = c.getMethod("getInstance", new Class[]{}); + Object o = getInstance.invoke(new Object[]{}); + + TIFFTagSet tagSet = (TIFFTagSet) o; + SortedSet tagNames = tagSet.getTagNames(); + SortedSet tagNumbers = tagSet.getTagNumbers(); + + int nTagNames = tagNames.size(); + if (nTagNames != tagNumbers.size()) { + throw new RuntimeException("Error: unequal sizes for tag names set " + + "and tag numbers set"); + } + System.out.println("\n" + nTagNames + " tag names/numbers\n"); + + for (final Iterator itName = tagNames.iterator(); itName.hasNext(); ) { + + String tagName = (String) itName.next(); + // just in case + if (tagName == null) { + throw new RuntimeException("null tag name"); + } + + TIFFTag tagByName = tagSet.getTag(tagName); + System.out.println( + "name/number: \t" + tagName + "/" + tagByName.getNumber()); + checkEq("tag name", tagByName.getName(), tagName); + TIFFTag tagByNum = tagSet.getTag(tagByName.getNumber()); + checkEq("tag name", tagByNum.getName(), tagName); + + if (tagByName.isIFDPointer() && + !tagByName.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER)) { + throw new RuntimeException("Error: " + tagName + + "must be an IFD pointer"); + } + } + System.out.println(""); + + for (final Iterator itNum = tagNumbers.iterator(); itNum.hasNext(); ) { + + int tagNum = (int) itNum.next(); + // just in case + if (tagNum < 0) { + throw new RuntimeException("negative tag number"); + } + TIFFTag tagByNum = tagSet.getTag(tagNum); + + System.out.println( + "number/name: \t" + tagNum + "/" + tagByNum.getName()); + checkEq("tag number", tagByNum.getNumber(), tagNum); + TIFFTag tagByName = tagSet.getTag(tagByNum.getName()); + checkEq("tag number", tagByName.getNumber(), tagNum); + } + + System.out.println(""); + } + + + private static void testUserDefTagSet() { + + TIFFTagSet set = TestSet.getInstance(); + + SortedSet tagNames = set.getTagNames(); + checkEq("tagNames set size", tagNames.size(), 3); + if (! (tagNames.contains(TestSet.TAG_NAME_1) && + tagNames.contains(TestSet.TAG_NAME_2) && + tagNames.contains(TestSet.TAG_NAME_3)) ) { + throw new RuntimeException("invalid tag names"); + } + + SortedSet tagNumbers = set.getTagNumbers(); + checkEq("tagNumbers set size", tagNumbers.size(), 3); + if (! (tagNumbers.contains(TestSet.TAG_NUM_1) && + tagNumbers.contains(TestSet.TAG_NUM_2) && + tagNumbers.contains(TestSet.TAG_NUM_3)) ) { + throw new RuntimeException("invalid tag numbers"); + } + + TIFFTag t1 = set.getTag(TestSet.TAG_NUM_1), + t2 = set.getTag(TestSet.TAG_NUM_2), + t3 = set.getTag(TestSet.TAG_NUM_3); + + checkEq(TestSet.TAG_NAME_1 + " name", t1.getName(), TestSet.TAG_NAME_1); + checkEq(TestSet.TAG_NAME_2 + " name", t2.getName(), TestSet.TAG_NAME_2); + checkEq(TestSet.TAG_NAME_3 + " name", t3.getName(), TestSet.TAG_NAME_3); + + // check count + // was set + checkEq(TestSet.TAG_NAME_1 + " count", + t1.getCount(), TestSet.VALUE_COUNT); + // undefined + checkEq(TestSet.TAG_NAME_2 + " count", t2.getCount(), -1); + // see docs for constructor TIFFTag(String, int, TIFFTagSet) + checkEq(TestSet.TAG_NAME_3 + " count", t3.getCount(), 1); + + // check datatypes + checkEq(TestSet.TAG_NAME_1 + " datatypes", t1.getDataTypes(), + 1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG); + boolean ok = t1.isDataTypeOK(TIFFTag.TIFF_SHORT) && + t1.isDataTypeOK(TIFFTag.TIFF_LONG) && + !t1.isDataTypeOK(TIFFTag.TIFF_DOUBLE) && + !t1.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER); + if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_1 + ": " + + "isDataTypeOK check failed"); } + checkEq(TestSet.TAG_NAME_1 + ".isIFDPointer()", t1.isIFDPointer(), false); + + checkEq(TestSet.TAG_NAME_2 + " datatypes", t2.getDataTypes(), + 1 << TIFFTag.TIFF_DOUBLE); + ok = !t2.isDataTypeOK(TIFFTag.TIFF_SHORT) && + !t2.isDataTypeOK(TIFFTag.TIFF_LONG) && + t2.isDataTypeOK(TIFFTag.TIFF_DOUBLE) && + !t2.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER); + if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_2 + ": " + + "isDataTypeOK check failed"); } + checkEq(TestSet.TAG_NAME_2 + ".isIFDPointer()", t2.isIFDPointer(), false); + + // see docs for constructor TIFFTag(String, int, TIFFTagSet) + checkEq(TestSet.TAG_NAME_3 + " datatypes", t3.getDataTypes(), + 1 << TIFFTag.TIFF_LONG | 1 << TIFFTag.TIFF_IFD_POINTER); + ok = !t3.isDataTypeOK(TIFFTag.TIFF_SHORT) && + t3.isDataTypeOK(TIFFTag.TIFF_LONG) && + !t3.isDataTypeOK(TIFFTag.TIFF_DOUBLE) && + t3.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER); + if (!ok) { throw new RuntimeException(TestSet.TAG_NAME_3 + ": " + + "isDataTypeOK check failed"); } + checkEq(TestSet.TAG_NAME_3 + ".isIFDPointer()", t3.isIFDPointer(), true); + + // check value names + checkEq(TestSet.TAG_NAME_1 + ".hasValueNames()", + t1.hasValueNames(), false); + checkEq(TestSet.TAG_NAME_2 + ".hasValueNames()", + t2.hasValueNames(), true); + checkEq(TestSet.TAG_NAME_3 + ".hasValueNames()", + t3.hasValueNames(), false); + + if (t1.getNamedValues() != null && t3.getNamedValues() != null) { + throw new RuntimeException(TestSet.TAG_NAME_1 + " and " + + TestSet.TAG_NAME_3 + " must have null value names arrays"); + } + + checkEq("number of " + TestSet.TAG_NAME_2 + " values", + t2.getNamedValues().length, 2); + checkEq("name of value " + TestSet.VALUE_1, + t2.getValueName(TestSet.VALUE_1), TestSet.VALUE_NAME_1); + checkEq("name of value " + TestSet.VALUE_2, + t2.getValueName(TestSet.VALUE_2), TestSet.VALUE_NAME_2); + + // check tag sets + if (!(t1.getTagSet() == null && t2.getTagSet() == null) && + t3.getTagSet().equals(TestSet.SOME_SET)) { + throw new RuntimeException("invalid containing tag set"); + } + } + + private static void checkArgs() { + + boolean ok = false; + try { + TIFFTag t = new TIFFTag(null, 0, 1 << TIFFTag.TIFF_LONG); + } catch (Exception e) { + ok = true; + } + if (!ok) { + throw new RuntimeException("null names should not be allowed"); + } + + ok = false; + try { + TIFFTag t = new TIFFTag("abc", -1, 1 << TIFFTag.TIFF_LONG); + } catch (Exception e) { + ok = true; + } + if (!ok) { + throw new RuntimeException("negative numbers should not be allowed"); + } + + ok = false; + try { + TIFFTag t = new TIFFTag("abc", 666, ~0x3fff); + } catch (Exception e) { + ok = true; + } + if (!ok) { + throw new RuntimeException("disallowed data types were set"); + } + + ok = false; + try { + TIFFTag.getSizeOfType(TIFFTag.MIN_DATATYPE - 1); + } catch (Exception e) { + ok = true; + } + if (!ok) { throw new RuntimeException( + "missing data types check for getSizeOfType()"); } + + ok = false; + try { + TIFFTag.getSizeOfType(TIFFTag.MAX_DATATYPE + 1); + } catch (Exception e) { + ok = true; + } + if (!ok) { throw new RuntimeException( + "missing data types check for getSizeOfType()"); } + + } + + + public static void main(String[] args) throws ReflectiveOperationException { + + String classNames[] = {"BaselineTIFFTagSet", + "ExifGPSTagSet", + "ExifInteroperabilityTagSet", + "ExifParentTIFFTagSet", + "ExifTIFFTagSet", + "FaxTIFFTagSet", + "GeoTIFFTagSet"}; + + for (String cn: classNames) { + System.out.println("Testing " + cn + ":"); + (new TIFFTagSetTest( + "javax.imageio.plugins.tiff." + cn)).testNamesNumbers(); + } + + System.out.println("\nTesting user-defined tag set:"); + testUserDefTagSet(); + (new TIFFTagSetTest("TIFFTagSetTest$TestSet")).testNamesNumbers(); + + System.out.println("\nSome additional argument checks..."); + checkArgs(); + System.out.println("done"); + } +} From 437d2158fa247221406210a6e91fa7a6a6c6f3da Mon Sep 17 00:00:00 2001 From: David Simms Date: Thu, 4 Feb 2016 18:33:02 +0100 Subject: [PATCH 12/44] 8149025: JFR - Event based tracing should cover monitor inflation Reviewed-by: dcubed, egahlin, mgronlun --- .../runtime/TestJavaMonitorInflateEvent.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java diff --git a/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java b/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java new file mode 100644 index 00000000000..dc6f754a8b2 --- /dev/null +++ b/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import jrockit.Asserts; +import jrockit.TestThread; +import jrockit.XRun; +import jrockit.jfr.TestRecording; +import jrockit.jfr.ValueFilter; +import oracle.jrockit.jfr.parser.FLREvent; +import oracle.jrockit.jfr.parser.FLRStruct; + +/* + * @test TestJavaMonitorInflateEvent + * @key jfr + * @library ../common + * @modules jdk.jfr/oracle.jrockit.jfr + * jdk.jfr/oracle.jrockit.jfr.parser + * @build jrockit.* jrockit.jfr.* + * @run main/othervm -XX:+UnlockCommercialFeatures -XX:+FlightRecorder TestJavaMonitorInflateEvent + */ +public class TestJavaMonitorInflateEvent { + + private static final String FIELD_CLASS_NAME = "name"; + private static final String FIELD_KLASS = "klass"; + private static final String FIELD_ADDRESS = "address"; + private static final String FIELD_CAUSE = "cause"; + + private final static String EVENT_PATH = "java/monitor_inflate"; + + static class Lock { + } + + public static void main(String[] args) throws Exception { + TestRecording r = new TestRecording(); + try { + r.createJVMSetting(EVENT_PATH, true, true, 0, 0); + + final Lock lock = new Lock(); + final CountDownLatch latch = new CountDownLatch(1); + + // create a thread that waits + TestThread waitThread = new TestThread(new XRun() { + @Override + public void xrun() throws Throwable { + synchronized (lock) { + latch.countDown(); + lock.wait(123456); + } + } + }); + try { + r.start(); + waitThread.start(); + latch.await(); + synchronized (lock) { + lock.notifyAll(); + } + } finally { + waitThread.join(); + r.stop(); + } + + List events = r.parser().findJVMEvents(EVENT_PATH); + System.out.println(events); + if (events.isEmpty()) { + throw new Exception("Expected event"); + } + + String thisThreadName = Thread.currentThread().getName(); + String waitThreadName = waitThread.getName(); + + // Find at least one event with the correct monitor class and check the other fields + boolean foundEvent = false; + for (FLREvent event : events) { + if (!String.valueOf(event.getThread().getResolvedValue("name")).equals(waitThreadName)) { + continue; + } + // Check lock class + FLRStruct klassStruct = (FLRStruct) event.getResolvedValue(FIELD_KLASS); + String recordedLockClass = String.valueOf(klassStruct.getResolvedValue(FIELD_CLASS_NAME)); + String lockClass = lock.getClass().getName(); + if (!recordedLockClass.equals(lockClass)) { + continue; + } + + foundEvent = true; + // Check address + Asserts.assertNotEquals(0L, event.getResolvedValue(FIELD_ADDRESS), FIELD_ADDRESS + " should not be 0"); + // Check cause + Asserts.assertNotNull(event.getValue(FIELD_CAUSE), FIELD_CAUSE + " should not be null"); + } + Asserts.assertTrue(foundEvent, "Excepted event from test thread"); + } catch (Throwable e) { + r.copyTo("failed.jfr"); + throw e; + } finally { + r.close(); + } + } +} From c0623d66812cc141fc80134854bc3b20a97b6a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 4 Feb 2016 23:30:48 +0100 Subject: [PATCH 13/44] 8149062: Remove misplaced integration of test code after 8149025 Reviewed-by: coleenp --- .../runtime/TestJavaMonitorInflateEvent.java | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java diff --git a/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java b/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java deleted file mode 100644 index dc6f754a8b2..00000000000 --- a/jdk/com/oracle/jfr/runtime/TestJavaMonitorInflateEvent.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import jrockit.Asserts; -import jrockit.TestThread; -import jrockit.XRun; -import jrockit.jfr.TestRecording; -import jrockit.jfr.ValueFilter; -import oracle.jrockit.jfr.parser.FLREvent; -import oracle.jrockit.jfr.parser.FLRStruct; - -/* - * @test TestJavaMonitorInflateEvent - * @key jfr - * @library ../common - * @modules jdk.jfr/oracle.jrockit.jfr - * jdk.jfr/oracle.jrockit.jfr.parser - * @build jrockit.* jrockit.jfr.* - * @run main/othervm -XX:+UnlockCommercialFeatures -XX:+FlightRecorder TestJavaMonitorInflateEvent - */ -public class TestJavaMonitorInflateEvent { - - private static final String FIELD_CLASS_NAME = "name"; - private static final String FIELD_KLASS = "klass"; - private static final String FIELD_ADDRESS = "address"; - private static final String FIELD_CAUSE = "cause"; - - private final static String EVENT_PATH = "java/monitor_inflate"; - - static class Lock { - } - - public static void main(String[] args) throws Exception { - TestRecording r = new TestRecording(); - try { - r.createJVMSetting(EVENT_PATH, true, true, 0, 0); - - final Lock lock = new Lock(); - final CountDownLatch latch = new CountDownLatch(1); - - // create a thread that waits - TestThread waitThread = new TestThread(new XRun() { - @Override - public void xrun() throws Throwable { - synchronized (lock) { - latch.countDown(); - lock.wait(123456); - } - } - }); - try { - r.start(); - waitThread.start(); - latch.await(); - synchronized (lock) { - lock.notifyAll(); - } - } finally { - waitThread.join(); - r.stop(); - } - - List events = r.parser().findJVMEvents(EVENT_PATH); - System.out.println(events); - if (events.isEmpty()) { - throw new Exception("Expected event"); - } - - String thisThreadName = Thread.currentThread().getName(); - String waitThreadName = waitThread.getName(); - - // Find at least one event with the correct monitor class and check the other fields - boolean foundEvent = false; - for (FLREvent event : events) { - if (!String.valueOf(event.getThread().getResolvedValue("name")).equals(waitThreadName)) { - continue; - } - // Check lock class - FLRStruct klassStruct = (FLRStruct) event.getResolvedValue(FIELD_KLASS); - String recordedLockClass = String.valueOf(klassStruct.getResolvedValue(FIELD_CLASS_NAME)); - String lockClass = lock.getClass().getName(); - if (!recordedLockClass.equals(lockClass)) { - continue; - } - - foundEvent = true; - // Check address - Asserts.assertNotEquals(0L, event.getResolvedValue(FIELD_ADDRESS), FIELD_ADDRESS + " should not be 0"); - // Check cause - Asserts.assertNotNull(event.getValue(FIELD_CAUSE), FIELD_CAUSE + " should not be null"); - } - Asserts.assertTrue(foundEvent, "Excepted event from test thread"); - } catch (Throwable e) { - r.copyTo("failed.jfr"); - throw e; - } finally { - r.close(); - } - } -} From f9d86905098adf696916fbc7f5b942dfebb48f26 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 5 Feb 2016 14:03:05 +0100 Subject: [PATCH 14/44] 8144916: Decrease PerfDataMemorySize back to 32K Reviewed-by: mlarsson, sla --- .../jvmstat/perfdata/PrologSanity/PrologSizeSanityCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/sun/jvmstat/perfdata/PrologSanity/PrologSizeSanityCheck.java b/jdk/test/sun/jvmstat/perfdata/PrologSanity/PrologSizeSanityCheck.java index 0fd5cce5c41..95c54917d59 100644 --- a/jdk/test/sun/jvmstat/perfdata/PrologSanity/PrologSizeSanityCheck.java +++ b/jdk/test/sun/jvmstat/perfdata/PrologSanity/PrologSizeSanityCheck.java @@ -25,7 +25,7 @@ * @test * @bug 4990825 * @modules jdk.jvmstat/sun.jvmstat.monitor - * @run main/othervm -XX:+UsePerfData -XX:PerfDataMemorySize=64k PrologSizeSanityCheck + * @run main/othervm -XX:+UsePerfData PrologSizeSanityCheck * @summary prolog size and overflow sanity checks */ From db7eb9de4c8fb6ecf4d6bd1242655a0f69066477 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 5 Feb 2016 08:12:42 -0500 Subject: [PATCH 15/44] 8148785: Update class file version to 53 for JDK-9 Change max support class file veriosn to 53 Reviewed-by: alanb, coleenp, shade --- jdk/src/java.base/share/native/libjava/System.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/native/libjava/System.c b/jdk/src/java.base/share/native/libjava/System.c index 8304efba944..80ab07191de 100644 --- a/jdk/src/java.base/share/native/libjava/System.c +++ b/jdk/src/java.base/share/native/libjava/System.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,7 @@ Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x) #define VENDOR_URL_BUG "http://bugreport.java.com/bugreport/" #endif -#define JAVA_MAX_SUPPORTED_VERSION 52 +#define JAVA_MAX_SUPPORTED_VERSION 53 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 #ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ From 6620405d4157c1d7a11cabbe515f3223c6ad4060 Mon Sep 17 00:00:00 2001 From: Yuji Kubota Date: Fri, 5 Feb 2016 17:49:36 +0300 Subject: [PATCH 16/44] 8149099: jcmd -help mention non-existent option Fix typo -p to -l Reviewed-by: dsamersoff, jbachorik --- jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java index d8c581efe55..fbd4ca9aae4 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java @@ -119,7 +119,7 @@ class Arguments { System.out.println(" If the pid is 0, commands will be sent to all Java processes. "); System.out.println(" The main class argument will be used to match (either partially "); System.out.println(" or fully) the class used to start Java. "); - System.out.println(" If no options are given, lists Java processes (same as -p). "); + System.out.println(" If no options are given, lists Java processes (same as -l). "); System.out.println(" "); System.out.println(" PerfCounter.print display the counters exposed by this process "); System.out.println(" -f read and execute commands from the file "); From 034d9dddfc8e97ae2804f9d69d129f7d7e9f5551 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sat, 6 Feb 2016 14:22:51 +0300 Subject: [PATCH 17/44] 8149174: [TESTBUG] TestJcmdDefaults.java: ouput should contain all content of jcmd/usage.out Fixed typoeo in expected output Reviewed-by: sspitsyn --- jdk/test/sun/tools/jcmd/usage.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/sun/tools/jcmd/usage.out b/jdk/test/sun/tools/jcmd/usage.out index 48efa40ce12..c1aef0fc88e 100644 --- a/jdk/test/sun/tools/jcmd/usage.out +++ b/jdk/test/sun/tools/jcmd/usage.out @@ -7,7 +7,7 @@ Usage: jcmd If the pid is 0, commands will be sent to all Java processes. The main class argument will be used to match (either partially or fully) the class used to start Java. - If no options are given, lists Java processes (same as -p). + If no options are given, lists Java processes (same as -l). PerfCounter.print display the counters exposed by this process -f read and execute commands from the file From 27d7551b1300d1f388b572e8228e2dd4d5d57f21 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Sat, 6 Feb 2016 09:25:56 -0800 Subject: [PATCH 18/44] 8149151: Use local GraphicsEnvironment to get screen size in WToolkit Reviewed-by: prr, serb --- .../classes/sun/awt/windows/WToolkit.java | 15 +++++- .../native/libawt/windows/awt_Toolkit.cpp | 47 ------------------- .../GetSizeTest/GetScreenSizeTest.java | 2 +- 3 files changed, 14 insertions(+), 50 deletions(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index c7c463a8754..66d8338be29 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -641,10 +641,21 @@ public final class WToolkit extends SunToolkit implements Runnable { GraphicsEnvironment.getLocalGraphicsEnvironment(); return ge.getXResolution(); } + @Override - protected native int getScreenWidth(); + protected int getScreenWidth() { + return GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration() + .getBounds().width; + } + @Override - protected native int getScreenHeight(); + protected int getScreenHeight() { + return GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration() + .getBounds().height; + } + private native Insets getScreenInsets(int screen); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp index 1f5a72620a3..f4240ee41ce 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp @@ -2345,53 +2345,6 @@ Java_sun_awt_windows_WToolkit_getMaximumCursorColors(JNIEnv *env, jobject self) CATCH_BAD_ALLOC_RET(0); } -/* - * Class: sun_awt_windows_WToolkit - * Method: getScreenWidth - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_sun_awt_windows_WToolkit_getScreenWidth(JNIEnv *env, jobject self) -{ - TRY; - - int width = ::GetSystemMetrics(SM_CXSCREEN); - - if (!Devices::GetInstance()) { - Devices::UpdateInstance(env); - } - Devices::InstanceAccess devices; - AwtWin32GraphicsDevice *device = devices->GetDevice( - AwtWin32GraphicsDevice::GetDefaultDeviceIndex()); - - return (device == NULL) ? width : device->ScaleDownX(width); - CATCH_BAD_ALLOC_RET(0); -} - -/* - * Class: sun_awt_windows_WToolkit - * Method: getScreenHeight - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self) -{ - TRY; - - int height = ::GetSystemMetrics(SM_CYSCREEN); - - if (!Devices::GetInstance()) { - Devices::UpdateInstance(env); - } - Devices::InstanceAccess devices; - AwtWin32GraphicsDevice *device = devices->GetDevice( - AwtWin32GraphicsDevice::GetDefaultDeviceIndex()); - - return (device == NULL) ? height : device->ScaleDownY(height); - - CATCH_BAD_ALLOC_RET(0); -} - /* * Class: sun_awt_windows_WToolkit * Method: getSreenInsets diff --git a/jdk/test/java/awt/Toolkit/GetSizeTest/GetScreenSizeTest.java b/jdk/test/java/awt/Toolkit/GetSizeTest/GetScreenSizeTest.java index 202a740bdfd..b38a31c67a6 100644 --- a/jdk/test/java/awt/Toolkit/GetSizeTest/GetScreenSizeTest.java +++ b/jdk/test/java/awt/Toolkit/GetSizeTest/GetScreenSizeTest.java @@ -23,7 +23,7 @@ /* @test - @bug 8144074 8145785 + @bug 8144074 8145785 8149151 @summary Crash while getting screen size during Toolkit initialisation @run main/othervm GetScreenSizeTest */ From f83f5e5ef9b8a447ca0ec5ac833674c3d3548a0a Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Mon, 8 Feb 2016 11:43:08 +0300 Subject: [PATCH 19/44] 8142861: [TEST] MultiResolution image: add a manual test for two-display configuration (HiDPI + non-HiDPI) Reviewed-by: alexsch --- .../MultiDisplayTest/MultiDisplayTest.html | 62 ++++++++ .../MultiDisplayTest/MultiDisplayTest.java | 147 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.html create mode 100644 jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.java diff --git a/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.html b/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.html new file mode 100644 index 00000000000..49989cd9ceb --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.html @@ -0,0 +1,62 @@ + + + + + MultiDisplayTest + + + + +This test is for OS X or Windows only. +For other OSes please simply push "Pass". + +The test requires two-display configuration, where + +- 1st display is operating in HiDPI mode; +- 2nd display is non-HiDPI. + +In other cases please simply push "Pass". + + +To run test please push "Start". + +Then drag parent / child to different displays and check +that the proper image is shown for every window +(must be "black 1x" for non-HiDPI and "blue 2x" for HiDPI). + +Please try to drag both parent and child, +do it fast several times and check if no artefacts occur. + +Try to switch display resolution (high to low and back). + +For Mac OS X please check also the behavior for +translucent windows appearing on the 2nd (non-active) display +and Mission Control behavior. + +Close the windows. + +In case if no issues occur please push "Pass", otherwise "Fail". + + + diff --git a/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.java b/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.java new file mode 100644 index 00000000000..19136c1e678 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiDisplayTest/MultiDisplayTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 8142861 8143062 8147016 + @summary Check if multiresolution image behaves properly + on HiDPI + non-HiDPI display pair. + @author a.stepanov + @library /lib/testlibrary + @build jdk.testlibrary.OSInfo + @run applet/manual=yesno MultiDisplayTest.html +*/ + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import jdk.testlibrary.OSInfo; + + +public class MultiDisplayTest extends Applet { + + private static final int W = 200, H = 200; + + private static final BaseMultiResolutionImage IMG = + new BaseMultiResolutionImage(new BufferedImage[]{ + generateImage(1, Color.BLACK), generateImage(2, Color.BLUE)}); + + private static boolean checkOS() { + OSInfo.OSType os = OSInfo.getOSType(); + return (os.equals(OSInfo.OSType.WINDOWS) || + os.equals(OSInfo.OSType.MACOSX)); + } + + public void init() { this.setLayout(new BorderLayout()); } + + public void start() { + + Button b = new Button("Start"); + b.setEnabled(checkOS()); + + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + ParentFrame p = new ParentFrame(); + new ChildDialog(p); + } + }); + + add(b, BorderLayout.CENTER); + + validate(); + setVisible(true); + } + + + private static BufferedImage generateImage(int scale, Color c) { + + BufferedImage image = new BufferedImage( + scale * W, scale * H, BufferedImage.TYPE_INT_RGB); + Graphics g = image.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, scale * W, scale * H); + + g.setColor(Color.WHITE); + Font f = g.getFont(); + g.setFont(new Font(f.getName(), Font.BOLD, scale * 48)); + g.drawChars((scale + "X").toCharArray(), 0, 2, scale * W / 2, scale * H / 2); + + return image; + } + + private static class ParentFrame extends Frame { + + public ParentFrame() { + EventQueue.invokeLater(this::CreateUI); + } + + private void CreateUI() { + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { dispose(); } + }); + setSize(W, H); + setLocation(50, 50); + setTitle("parent"); + setResizable(false); + setVisible(true); + } + + @Override + public void paint(Graphics gr) { + gr.drawImage(IMG, 0, 0, this); + } + } + + private static class ChildDialog extends Dialog { + + public ChildDialog(Frame f) { + super(f); + EventQueue.invokeLater(this::CreateUI); + } + + private void CreateUI() { + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { dispose(); } + }); + setSize(W, H); + setTitle("child"); + setResizable(false); + setModal(true); + setVisible(true); + } + + @Override + public void paint(Graphics gr) { + gr.drawImage(IMG, 0, 0, this); + } + } +} From b4006c54e8ce4239539bf04d339b687fd4e0c388 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 9 Feb 2016 18:42:07 -0500 Subject: [PATCH 20/44] 8072777: java/lang/ref/ReferenceEnqueuePending.java: some references aren't queued Wait for enqueuing. Reviewed-by: plevart, mchung --- .../lang/ref/ReferenceEnqueuePending.java | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/jdk/test/java/lang/ref/ReferenceEnqueuePending.java b/jdk/test/java/lang/ref/ReferenceEnqueuePending.java index 19e960edac0..50bec341b40 100644 --- a/jdk/test/java/lang/ref/ReferenceEnqueuePending.java +++ b/jdk/test/java/lang/ref/ReferenceEnqueuePending.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,35 +94,52 @@ public class ReferenceEnqueuePending { } // Do a final collection to discover and process all - // Reference objects created above, allowing enough time + // Reference objects created above, allowing some time // for the ReferenceHandler thread to queue the References. forceGc(100); forceGc(100); // Verify that all WeakReference objects ended up queued. - checkResult(refQueue, obj, iterations-1); + checkResult(refQueue, iterations-1); + + // Ensure the final weaky is live but won't be enqueued during + // result checking, by ensuring its referent remains live. + // This eliminates behavior changes resulting from different + // compiler optimizations. + Reference.reachabilityFence(weaky); + Reference.reachabilityFence(obj); + System.out.println("Test passed."); } + private static NumberedWeakReference waitForReference(ReferenceQueue queue) { + try { + return (NumberedWeakReference) queue.remove(30000); // 30sec + } catch (InterruptedException ie) { + return null; + } + } + private static void checkResult(ReferenceQueue queue, - Integer obj, int expected) { if (debug) { System.out.println("Reading the queue"); } // Empty the queue and record numbers into a[]; - NumberedWeakReference weakRead = (NumberedWeakReference) queue.poll(); + NumberedWeakReference weakRead = waitForReference(queue); int length = 0; while (weakRead != null) { a[length++] = weakRead.number; - weakRead = (NumberedWeakReference) queue.poll(); + if (length < expected) { + weakRead = waitForReference(queue); + } else { // Check for unexpected extra entries. + weakRead = (NumberedWeakReference) queue.poll(); + } } if (debug) { System.out.println("Reference Queue had " + length + " elements"); } - // Use the last Reference object of those created above, so as to keep it "alive". - System.out.println("I must write " + obj + " to prevent compiler optimizations."); // verify the queued references: all but the last Reference object From 7f395c26ab406d415f7a52f05fdbc0bbb13b795f Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 10 Feb 2016 15:20:41 -0800 Subject: [PATCH 21/44] 8141491: Unaligned memory access in Bits.c Introduce alignment-safe Copy::conjoint_swap and j.i.m.Unsafe.copySwapMemory Reviewed-by: jrose, dholmes, psandoz --- jdk/make/lib/CoreLibraries.gmk | 8 +- jdk/make/mapfiles/libjava/mapfile-vers | 8 +- .../share/classes/java/nio/Bits.java | 142 +++++++++-- .../classes/jdk/internal/misc/Unsafe.java | 74 +++++- jdk/src/java.base/share/native/libjava/Bits.c | 233 ------------------ 5 files changed, 196 insertions(+), 269 deletions(-) delete mode 100644 jdk/src/java.base/share/native/libjava/Bits.c diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 5cbeb4b03f7..18143462338 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -137,12 +137,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) endif endif -ifeq ($(OPENJDK_TARGET_OS), linux) - ifeq ($(OPENJDK_TARGET_CPU), x86_64) - BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM) - endif -endif - $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBRARY := java, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index faf1cc130fe..22d99e7bfcf 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -229,12 +229,6 @@ SUNWprivate_1.1 { Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_nio_Bits_copyFromShortArray; - Java_java_nio_Bits_copyToShortArray; - Java_java_nio_Bits_copyFromIntArray; - Java_java_nio_Bits_copyToIntArray; - Java_java_nio_Bits_copyFromLongArray; - Java_java_nio_Bits_copyToLongArray; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2; diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java index 09623eab845..ea4ba276e88 100644 --- a/jdk/src/java.base/share/classes/java/nio/Bits.java +++ b/jdk/src/java.base/share/classes/java/nio/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -807,31 +807,131 @@ class Bits { // package-private } } - static void copyFromCharArray(Object src, long srcPos, long dstAddr, - long length) - { - copyFromShortArray(src, srcPos, dstAddr, length); + /** + * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 16-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2); } - static void copyToCharArray(long srcAddr, Object dst, long dstPos, - long length) - { - copyToShortArray(srcAddr, dst, dstPos, length); + /** + * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 16-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2); } - static native void copyFromShortArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToShortArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 16-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2); + } - static native void copyFromIntArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToIntArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 16-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2); + } - static native void copyFromLongArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToLongArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 32-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4); + } + /** + * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 32-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4); + } + + /** + * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 64-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8); + } + + /** + * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 64-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8); + } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index f130d383a84..f17111691f2 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -458,6 +458,78 @@ public final class Unsafe { copyMemory(null, srcAddress, null, destAddress, bytes); } + private boolean isPrimitiveArray(Class c) { + Class componentType = c.getComponentType(); + return componentType != null && componentType.isPrimitive(); + } + + private native void copySwapMemory0(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize); + + /** + * Copies all elements from one block of memory to another block, + * *unconditionally* byte swapping the elements on the fly. + * + *

This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a double-register addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * @since 9 + */ + public void copySwapMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize) { + if (bytes < 0) { + throw new IllegalArgumentException(); + } + if (elemSize != 2 && elemSize != 4 && elemSize != 8) { + throw new IllegalArgumentException(); + } + if (bytes % elemSize != 0) { + throw new IllegalArgumentException(); + } + if ((srcBase == null && srcOffset == 0) || + (destBase == null && destOffset == 0)) { + throw new NullPointerException(); + } + + // Must be off-heap, or primitive heap arrays + if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) { + throw new IllegalArgumentException(); + } + if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) { + throw new IllegalArgumentException(); + } + + // Sanity check size and offsets on 32-bit platforms. Most + // significant 32 bits must be zero. + if (ADDRESS_SIZE == 4 && + (bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) { + throw new IllegalArgumentException(); + } + + if (bytes == 0) { + return; + } + + copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); + } + + /** + * Copies all elements from one block of memory to another block, byte swapping the + * elements on the fly. + * + * This provides a single-register addressing mode, as + * discussed in {@link #getInt(Object,long)}. + * + * Equivalent to {@code copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize)}. + */ + public void copySwapMemory(long srcAddress, long destAddress, long bytes, long elemSize) { + copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize); + } + /** * Disposes of a block of native memory, as obtained from {@link * #allocateMemory} or {@link #reallocateMemory}. The address passed to diff --git a/jdk/src/java.base/share/native/libjava/Bits.c b/jdk/src/java.base/share/native/libjava/Bits.c deleted file mode 100644 index f3780199718..00000000000 --- a/jdk/src/java.base/share/native/libjava/Bits.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2002, 2010, 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 "jlong.h" -#include - -#define MBYTE 1048576 - -#define GETCRITICAL_OR_RETURN(bytes, env, obj) { \ - bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \ - if (bytes == NULL) { \ - if ((*env)->ExceptionOccurred(env) == NULL) \ - JNU_ThrowInternalError(env, "Unable to get array"); \ - return; \ - } \ -} - -#define RELEASECRITICAL(bytes, env, obj, mode) { \ - (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \ -} - -#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff))) -#define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \ - (SWAPSHORT((jshort)((x) >> 16)) & 0xffff))) -#define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \ - ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff))) - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - dstShort = (jshort *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcShort = (jshort *)(bytes + srcPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - srcShort = (jshort *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstShort = (jshort *)(bytes + dstPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - dstInt = (jint *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcInt = (jint *)(bytes + srcPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - srcInt = (jint *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstInt = (jint *)(bytes + dstPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - dstLong = (jlong *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcLong = (jlong *)(bytes + srcPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - srcLong = (jlong *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstLong = (jlong *)(bytes + dstPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} From 243c8598d5af47d47f82195afaa91d14877f95f6 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 10 Feb 2016 19:55:57 -0800 Subject: [PATCH 22/44] 8149611: Add tests for Unsafe.copySwapMemory Reviewed-by: dholmes --- .../jdk/internal/misc/Unsafe/CopySwap.java | 711 ++++++++++++++++++ 1 file changed, 711 insertions(+) create mode 100644 jdk/test/jdk/internal/misc/Unsafe/CopySwap.java diff --git a/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java new file mode 100644 index 00000000000..ba61e23fcc9 --- /dev/null +++ b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; + +/* + * @test + * @summary Test Unsafe.copySwapMemory + * @modules java.base/jdk.internal.misc + */ +public class CopySwap { + private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG"); + + public static final long KB = 1024; + public static final long MB = KB * 1024; + public static final long GB = MB * 1024; + + private static final Unsafe UNSAFE; + private static final int SMALL_COPY_SIZE = 32; + private static final int BASE_ALIGNMENT = 16; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + private static long alignDown(long value, long alignment) { + return value & ~(alignment - 1); + } + + private static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + private static boolean isAligned(long value, long alignment) { + return value == alignDown(value, alignment); + } + + private CopySwap() { + } + + /** + * Generate verification data for a given offset + * + * The verification data is used to verify that the correct bytes + * have indeed been copied and byte swapped. + * + * The data is generated based on the offset (in bytes) into the + * source buffer. For a native buffer the offset is relative to + * the base pointer. For a heap array it is relative to the + * address of the first array element. + * + * This method will return the result of doing an elementSize byte + * read starting at offset (in bytes). + * + * @param offset offset into buffer + * @param elemSize size (in bytes) of the element + * + * @return the verification data, only the least significant + * elemSize*8 bits are set, zero extended + */ + private long getVerificationDataForOffset(long offset, long elemSize) { + byte[] bytes = new byte[(int)elemSize]; + + for (long i = 0; i < elemSize; i++) { + bytes[(int)i] = (byte)(offset + i); + } + + long o = UNSAFE.arrayBaseOffset(byte[].class); + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); + case 8: return UNSAFE.getLongUnaligned(bytes, o); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Verify byte swapped data + * + * @param ptr the data to verify + * @param srcOffset the srcOffset (in bytes) from which the copy started, + * used as key to regenerate the verification data + * @param dstOffset the offset (in bytes) in the array at which to start + * the verification, relative to the first element in the array + * @param size size (in bytes) of data to to verify + * @param elemSize size (in bytes) of the individual array elements + * + * @throws RuntimeException if an error is found + */ + private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { + for (long offset = 0; offset < size; offset += elemSize) { + long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); + long expected = byteSwap(expectedUnswapped, elemSize); + + long actual = getArrayElem(ptr, dstOffset + offset, elemSize); + + if (expected != actual) { + throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + + " dstOffset: 0x" + Long.toHexString(dstOffset) + + " size: 0x" + Long.toHexString(size) + + " offset: 0x" + Long.toHexString(offset) + + " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + /** + * Initialize an array with verification friendly data + * + * @param ptr pointer to the data to initialize + * @param size size (in bytes) of the data + * @param elemSize size (in bytes) of the individual elements + */ + private void initVerificationData(GenericPointer ptr, long size, long elemSize) { + for (long offset = 0; offset < size; offset++) { + byte data = (byte)getVerificationDataForOffset(offset, 1); + + if (ptr.isOnHeap()) { + UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); + } else { + UNSAFE.putByte(ptr.getOffset() + offset, data); + } + } + } + + /** + * Allocate a primitive array + * + * @param size size (in bytes) of all the array elements (elemSize * length) + * @param elemSize the size of the array elements + * + * @return a newly allocated primitive array + */ + Object allocArray(long size, long elemSize) { + int length = (int)(size / elemSize); + + switch ((int)elemSize) { + case 2: return new short[length]; + case 4: return new int[length]; + case 8: return new long[length]; + default: + throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the value of a primitive array entry + * + * @param ptr pointer to the data + * @param offset offset (in bytes) of the array element, relative to the first element in the array + * + * @return the array element, as an unsigned long + */ + private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { + if (ptr.isOnHeap()) { + Object o = ptr.getObject(); + int index = (int)(offset / elemSize); + + if (o instanceof short[]) { + short[] arr = (short[])o; + return Short.toUnsignedLong(arr[index]); + } else if (o instanceof int[]) { + int[] arr = (int[])o; + return Integer.toUnsignedLong(arr[index]); + } else if (o instanceof long[]) { + long[] arr = (long[])o; + return arr[index]; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } else { + long addr = ptr.getOffset() + offset; + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); + case 8: return UNSAFE.getLongUnaligned(null, addr); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + } + + private void putValue(long addr, long elemSize, long value) { + switch ((int)elemSize) { + case 1: UNSAFE.putByte(addr, (byte)value); break; + case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; + case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; + case 8: UNSAFE.putLongUnaligned(null, addr, value); break; + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the size of the elements for an array + * + * @param o a primitive heap array + * + * @return the size (in bytes) of the individual array elements + */ + private long getArrayElemSize(Object o) { + if (o instanceof short[]) { + return 2; + } else if (o instanceof int[]) { + return 4; + } else if (o instanceof long[]) { + return 8; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } + + /** + * Byte swap a value + * + * @param value the value to swap, only the bytes*8 least significant bits are used + * @param size size (in bytes) of the value + * + * @return the byte swapped value in the bytes*8 least significant bits + */ + private long byteSwap(long value, long size) { + switch ((int)size) { + case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); + case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); + case 8: return Long.reverseBytes(value); + default: throw new IllegalArgumentException("Invalid element size: " + size); + } + } + + /** + * Verify data in a heap array which has *not* been byte swapped + * + * @param ptr the data to verify + * @param startOffset the offset (in bytes) at which to start the verification + * @param size size (in bytes) of the data to verify + * + * @throws RuntimeException if an error is found + */ + private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) { + for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) { + byte expected = (byte)getVerificationDataForOffset(elemOffset, 1); + + byte actual; + if (ptr.isOnHeap()) { + actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset); + } else { + actual = UNSAFE.getByte(ptr.getOffset() + elemOffset); + } + + if (expected != actual) { + throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + + " size: 0x" + Long.toHexString(size) + + " elemOffset: 0x" + Long.toHexString(elemOffset) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + + /** + * Copy and byte swap data from the source to the destination + * + * This method will pre-populate the whole source and destination + * buffers with verification friendly data. It will then use + * copySwapMemory to fill part of the destination buffer with + * swapped data from the source. Some space (padding) will be + * left before and after the data in the destination buffer, which + * should not be touched/overwritten by the copy call. + * + * Note: Both source and destination buffers will be overwritten! + * + * @param src source buffer to copy from + * @param srcOffset the offset (in bytes) in the source buffer, relative to + * the first array element, at which to start reading data + * @param dst destination buffer to copy to + * @param dstOffset the offset (in bytes) in the destination + * buffer, relative to the first array element, at which to + * start writing data + * @param bufSize the size (in bytes) of the src and dst arrays + * @param copyBytes the size (in bytes) of the copy to perform, + * must be a multiple of elemSize + * @param elemSize the size (in bytes) of the elements to byte swap + * + * @throws RuntimeException if an error is found + */ + private void testCopySwap(GenericPointer src, long srcOffset, + GenericPointer dst, long dstOffset, + long bufSize, long copyBytes, long elemSize) { + if (!isAligned(copyBytes, elemSize)) { + throw new IllegalArgumentException( + "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (srcOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + if (dstOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + + // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) + initVerificationData(src, bufSize, elemSize); + if (!src.equals(dst)) { + initVerificationData(dst, bufSize, elemSize); + } + + if (DEBUG) { + System.out.println("===before==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Copy & swap data into the middle of the destination buffer + UNSAFE.copySwapMemory(src.getObject(), + src.getOffset() + srcOffset, + dst.getObject(), + dst.getOffset() + dstOffset, + copyBytes, + elemSize); + + if (DEBUG) { + System.out.println("===after==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Verify the the front padding is unchanged + verifyUnswappedData(dst, 0, dstOffset); + + // Verify swapped data + verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize); + + // Verify that the back back padding is unchanged + long frontAndDataBytes = dstOffset + copyBytes; + long trailingBytes = bufSize - frontAndDataBytes; + verifyUnswappedData(dst, frontAndDataBytes, trailingBytes); + } + + /** + * Test various configurations copy-swapping from one buffer to the other + * + * @param src the source buffer to copy from + * @param dst the destination buffer to copy to + * @param size size (in bytes) of the buffers + * @param elemSize size (in bytes) of the individual elements + * + * @throws RuntimeException if an error is found + */ + public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) { + // offset in source from which to start reading data + for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { + + // offset in destination at which to start writing data + for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { + + // number of bytes to copy + long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); + for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { + try { + testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize); + } catch (RuntimeException e) { + // Wrap the exception in another exception to catch the relevant configuration data + throw new RuntimeException("testBufferPair: " + + "src=" + src + + " dst=" + dst + + " elemSize=0x" + Long.toHexString(elemSize) + + " copyBytes=0x" + Long.toHexString(copyBytes) + + " srcOffset=0x" + Long.toHexString(srcOffset) + + " dstOffset=0x" + Long.toHexString(dstOffset), + e); + } + } + } + } + } + + /** + * Test copying between various permutations of buffers + * + * @param buffers buffers to permute (src x dst) + * @param size size (in bytes) of buffers + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) { + for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { + for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { + testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize); + } + } + } + + /** + * Test copying of a specific element size + * + * @param size size (in bytes) of buffers to allocate + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + private void testElemSize(long size, long elemSize) { + long buf1Raw = 0; + long buf2Raw = 0; + + try { + buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); + + buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); + + GenericPointer[] buffers = { + new GenericPointer(buf1), + new GenericPointer(buf2), + new GenericPointer(allocArray(size, elemSize)), + new GenericPointer(allocArray(size, elemSize)) + }; + + testPermuteBuffers(buffers, size, elemSize); + } finally { + if (buf1Raw != 0) { + UNSAFE.freeMemory(buf1Raw); + } + if (buf2Raw != 0) { + UNSAFE.freeMemory(buf2Raw); + } + } + } + + /** + * Verify that small copy swaps work + */ + private void testSmallCopy() { + int smallBufSize = SMALL_COPY_SIZE; + + // Test various element types and heap/native combinations + for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) { + testElemSize(smallBufSize, elemSize); + } + } + + + /** + * Verify that large copy swaps work + */ + private void testLargeCopy() { + long size = 2 * GB + 8; + long bufRaw = 0; + + // Check that a large native copy succeeds + try { + try { + bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + } catch (OutOfMemoryError e) { + // Accept failure, skip test + return; + } + + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + + UNSAFE.copySwapMemory(null, buf, null, buf, size, 8); + } catch (Exception e) { + throw new RuntimeException("copySwapMemory of large buffer failed"); + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run positive tests + * + * @throws RuntimeException if an error is found + */ + private void testPositive() { + testSmallCopy(); + testLargeCopy(); + } + + /** + * Run negative tests, testing corner cases and the various exceptions + * + * @throws RuntimeException if an error is found + */ + private void testNegative() { + long bufRaw = 0; + + try { + bufRaw = UNSAFE.allocateMemory(1024); + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + short[] arr = new short[16]; + + // Check various illegal element sizes + for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) { + long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 }; + for (long size : illegalSizes) { + try { + // Check that illegal elemSize throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize); + throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize); + } catch (IllegalArgumentException e) { + // good + } + } + } + + try { + // Check that negative srcOffset throws an IAE + UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that negative dstOffset throws an IAE + UNSAFE.copySwapMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + long illegalElemSizes[] = { 0, 1, 3, 5, 6, 7, 9, 10, -1 }; + for (long elemSize : illegalElemSizes) { + try { + // Check that elemSize 1 throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, 16, elemSize); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + } + + try { + // Check that a NULL source throws NPE + UNSAFE.copySwapMemory(null, 0, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a NULL destination throws NPE + UNSAFE.copySwapMemory(null, buf, null, 0, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a reference array destination throws IAE + UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + + // Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms) + if (UNSAFE.addressSize() == 4) { + long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, invalidPtr, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, buf, null, invalidPtr, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + } + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run all tests + * + * @throws RuntimeException if an error is found + */ + private void test() { + testPositive(); + testNegative(); + } + + public static void main(String[] args) { + CopySwap cs = new CopySwap(); + cs.test(); + } + + /** + * Helper class to represent a "pointer" - either a heap array or + * a pointer to a native buffer. + * + * In the case of a native pointer, the Object is null and the offset is + * the absolute address of the native buffer. + * + * In the case of a heap object, the Object is a primitive array, and + * the offset will be set to the base offset to the first element, meaning + * the object and the offset together form a double-register pointer. + */ + static class GenericPointer { + private final Object o; + private final long offset; + + private GenericPointer(Object o, long offset) { + this.o = o; + this.offset = offset; + } + + public String toString() { + return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; + } + + public boolean equals(Object other) { + if (!(other instanceof GenericPointer)) { + return false; + } + + GenericPointer otherp = (GenericPointer)other; + + return o == otherp.o && offset == otherp.offset; + } + + GenericPointer(Object o) { + this(o, UNSAFE.arrayBaseOffset(o.getClass())); + } + + GenericPointer(long offset) { + this(null, offset); + } + + public boolean isOnHeap() { + return o != null; + } + + public Object getObject() { + return o; + } + + public long getOffset() { + return offset; + } + } +} From 7c237a1bfa2c4e049a5d4f27046b0bfc842c32a1 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Mon, 15 Feb 2016 15:57:58 +0000 Subject: [PATCH 23/44] 8149411: PKCS12KeyStore cannot extract AES Secret Keys Reviewed-by: xuelei --- .../sun/security/pkcs12/PKCS12KeyStore.java | 8 +- .../sun/security/pkcs12/P12SecretKey.java | 87 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 jdk/test/sun/security/pkcs12/P12SecretKey.java diff --git a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index a0fa9c781ed..1c176f9fa24 100644 --- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -394,19 +394,19 @@ public final class PKCS12KeyStore extends KeyStoreSpi { // decode secret key } else { - SecretKeyFactory sKeyFactory = - SecretKeyFactory.getInstance(keyAlgo); byte[] keyBytes = in.getOctetString(); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, keyAlgo); // Special handling required for PBE: needs a PBEKeySpec if (keyAlgo.startsWith("PBE")) { + SecretKeyFactory sKeyFactory = + SecretKeyFactory.getInstance(keyAlgo); KeySpec pbeKeySpec = sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class); key = sKeyFactory.generateSecret(pbeKeySpec); } else { - key = sKeyFactory.generateSecret(secretKeySpec); + key = secretKeySpec; } if (debug != null) { diff --git a/jdk/test/sun/security/pkcs12/P12SecretKey.java b/jdk/test/sun/security/pkcs12/P12SecretKey.java new file mode 100644 index 00000000000..39f95d5e0b1 --- /dev/null +++ b/jdk/test/sun/security/pkcs12/P12SecretKey.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149411 + * @summary Get AES key from keystore (uses SecretKeySpec not SecretKeyFactory) + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.Arrays; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +public class P12SecretKey { + + private static final String ALIAS = "alias"; + + public static void main(String[] args) throws Exception { + P12SecretKey testp12 = new P12SecretKey(); + String keystoreType = "pkcs12"; + if (args != null && args.length > 0) { + keystoreType = args[0]; + } + testp12.run(keystoreType); + } + + private void run(String keystoreType) throws Exception { + char[] pw = "password".toCharArray(); + KeyStore ks = KeyStore.getInstance(keystoreType); + ks.load(null, pw); + + KeyGenerator kg = KeyGenerator.getInstance("AES"); + kg.init(128); + SecretKey key = kg.generateKey(); + + KeyStore.SecretKeyEntry ske = new KeyStore.SecretKeyEntry(key); + KeyStore.ProtectionParameter kspp = new KeyStore.PasswordProtection(pw); + ks.setEntry(ALIAS, ske, kspp); + + File ksFile = File.createTempFile("test", ".test"); + try (FileOutputStream fos = new FileOutputStream(ksFile)) { + ks.store(fos, pw); + fos.flush(); + } + + // now see if we can get it back + try (FileInputStream fis = new FileInputStream(ksFile)) { + KeyStore ks2 = KeyStore.getInstance(keystoreType); + ks2.load(fis, pw); + KeyStore.Entry entry = ks2.getEntry(ALIAS, kspp); + SecretKey keyIn = ((KeyStore.SecretKeyEntry)entry).getSecretKey(); + if (Arrays.equals(key.getEncoded(), keyIn.getEncoded())) { + System.err.println("OK: worked just fine with " + keystoreType + + " keystore"); + } else { + System.err.println("ERROR: keys are NOT equal after storing in " + + keystoreType + " keystore"); + } + } + } +} From 4458220d4a5b5c77ff2575c45ab18032d501a575 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 15 Feb 2016 20:27:12 +0300 Subject: [PATCH 24/44] 8148994: Replacing MH::invokeBasic with a direct call breaks LF customization Reviewed-by: jrose, redestad --- .../classes/java/lang/invoke/MethodHandleImpl.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index ebaf2a393ad..9b4029cc7b5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -778,8 +778,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return (asTypeCache = wrapper); } + // Customize target if counting happens for too long. + private int invocations = CUSTOMIZE_THRESHOLD; + private void maybeCustomizeTarget() { + int c = invocations; + if (c >= 0) { + if (c == 1) { + target.customize(); + } + invocations = c - 1; + } + } + boolean countDown() { int c = count; + maybeCustomizeTarget(); if (c <= 1) { // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. if (isCounting) { From 8fe03ae5d29d3a8d8777867bcb3f188d44766830 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 15 Feb 2016 10:27:13 -0800 Subject: [PATCH 25/44] 8148624: Test failure of ConstructInflaterOutput.java Reviewed-by: darcy --- jdk/test/java/util/zip/ConstructDeflaterInput.java | 4 ++-- jdk/test/java/util/zip/ConstructInflaterOutput.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/jdk/test/java/util/zip/ConstructDeflaterInput.java b/jdk/test/java/util/zip/ConstructDeflaterInput.java index 631163dcb36..94b308b5bb7 100644 --- a/jdk/test/java/util/zip/ConstructDeflaterInput.java +++ b/jdk/test/java/util/zip/ConstructDeflaterInput.java @@ -23,7 +23,7 @@ /** * @test - * @bug 4679743 + * @bug 4679743 8148624 * @summary Test parts of DeflaterInputStream code that don't really do I/O. */ @@ -41,10 +41,10 @@ public class ConstructDeflaterInput { } } + private static MyDeflater def = new MyDeflater(); public static void realMain(String[] args) throws Throwable { ByteArrayInputStream bais = new ByteArrayInputStream( "hello, world".getBytes()); - MyDeflater def = new MyDeflater(); DeflaterInputStream dis = null; byte[] b = new byte[512]; diff --git a/jdk/test/java/util/zip/ConstructInflaterOutput.java b/jdk/test/java/util/zip/ConstructInflaterOutput.java index d767235b0e0..c83826ce42e 100644 --- a/jdk/test/java/util/zip/ConstructInflaterOutput.java +++ b/jdk/test/java/util/zip/ConstructInflaterOutput.java @@ -23,7 +23,7 @@ /** * @test - * @bug 4679743 + * @bug 4679743 8148624 * @summary Test parts of InflaterOutputStream code that don't really do I/O. */ @@ -41,9 +41,10 @@ public class ConstructInflaterOutput { } } + private static MyInflater inf = new MyInflater(); + public static void realMain(String[] args) throws Throwable { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - MyInflater inf = new MyInflater(); InflaterOutputStream ios = null; byte[] b = new byte[512]; From 05ca3c971e2fcc77f6e4a9123a54887c6d7860c5 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 15 Feb 2016 18:41:23 -0800 Subject: [PATCH 26/44] 8135108: java/util/zip/TestLocalTime.java fails intermittently with Invalid value for NanoOfSecond Reviewed-by: darcy --- .../share/classes/java/util/zip/ZipEntry.java | 4 ++-- jdk/test/java/util/zip/TestLocalTime.java | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java index ee91cee3ed8..b67c5ec16f3 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java @@ -227,12 +227,12 @@ class ZipEntry implements ZipConstants, Cloneable { if (year < 0) { this.xdostime = DOSTIME_BEFORE_1980; } else { - this.xdostime = (year << 25 | + this.xdostime = ((year << 25 | time.getMonthValue() << 21 | time.getDayOfMonth() << 16 | time.getHour() << 11 | time.getMinute() << 5 | - time.getSecond() >> 1) + time.getSecond() >> 1) & 0xffffffffL) + ((long)(((time.getSecond() & 0x1) * 1000) + time.getNano() / 1000_000) << 32); } diff --git a/jdk/test/java/util/zip/TestLocalTime.java b/jdk/test/java/util/zip/TestLocalTime.java index d1909afba54..93770ef2f3b 100644 --- a/jdk/test/java/util/zip/TestLocalTime.java +++ b/jdk/test/java/util/zip/TestLocalTime.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8075526 + * @bug 8075526 8135108 * @key intermittent * @summary Test timestamp via ZipEntry.get/setTimeLocal() */ @@ -41,6 +41,7 @@ public class TestLocalTime { try { LocalDateTime ldt = LocalDateTime.now(); test(getBytes(ldt), ldt); // now + ldt = ldt.withYear(1968); test(getBytes(ldt), ldt); ldt = ldt.withYear(1970); test(getBytes(ldt), ldt); ldt = ldt.withYear(1982); test(getBytes(ldt), ldt); @@ -55,6 +56,13 @@ public class TestLocalTime { testWithTZ(tz, ldt.withYear(2037)); testWithTZ(tz, ldt.withYear(2100)); testWithTZ(tz, ldt.withYear(2106)); + + // for #8135108 + ldt = LocalDateTime.of(2100, 12, 06, 12, 34, 34, 973); + test(getBytes(ldt), ldt); + ldt = LocalDateTime.of(2106, 12, 06, 12, 34, 34, 973); + test(getBytes(ldt), ldt); + } finally { TimeZone.setDefault(tz0); } From 6eabb6bd195fb7741c576cb4b7ba1bf3411e20a8 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Tue, 16 Feb 2016 07:06:09 +0100 Subject: [PATCH 27/44] 8149700: Remove jdk_svc test group from tier * groups Reviewed-by: darcy --- jdk/test/TEST.groups | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index f621295f82d..7d56e8afd61 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -54,8 +54,7 @@ tier2 = \ -com/sun/crypto/provider/Cipher \ :jdk_text \ :core_tools \ - :jdk_other \ - :jdk_svc + :jdk_other tier3 = \ :jdk_rmi \ From e4e9015254e91be68b14a403683df3d02d8c184e Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 16 Feb 2016 11:36:20 -0500 Subject: [PATCH 28/44] 8148775: Spec for j.l.ProcessBuilder.Redirect.DISCARD need to be improved Reviewed-by: martin --- .../java.base/share/classes/java/lang/ProcessBuilder.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index 8610465c1ee..ebd47fcfe87 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -553,10 +553,9 @@ public final class ProcessBuilder * *

It will always be true that *

 {@code
-         * Redirect.DISCARD.file() the filename appropriate for the operating system
+         * Redirect.DISCARD.file() is the filename appropriate for the operating system
          * and may be null &&
-         * Redirect.DISCARD.type() == Redirect.Type.WRITE &&
-         * Redirect.DISCARD.append() == false
+         * Redirect.DISCARD.type() == Redirect.Type.WRITE
          * }
* @since 9 */ From a188f9045f2d4eafdd216f1379704e1706d321ed Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 16 Feb 2016 09:09:31 -0800 Subject: [PATCH 29/44] 8149896: Remove unnecessary values in FloatConsts and DoubleConsts Reviewed-by: shade, psandoz, lbourges, mduigou --- .../share/classes/java/lang/Double.java | 8 +-- .../share/classes/java/lang/Float.java | 12 ++--- .../share/classes/java/lang/Math.java | 35 +++++++------ .../share/classes/java/util/Formatter.java | 8 +-- .../jdk/internal/math/DoubleConsts.java | 49 ++++--------------- .../jdk/internal/math/FloatConsts.java | 45 ++++------------- .../jdk/internal/math/FloatingDecimal.java | 16 +++--- .../classes/sun/java2d/marlin/FloatMath.java | 13 +---- .../classes/sun/java2d/marlin/Renderer.java | 4 +- 9 files changed, 59 insertions(+), 131 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Double.java b/jdk/src/java.base/share/classes/java/lang/Double.java index f1389ebe0f8..473b86dd909 100644 --- a/jdk/src/java.base/share/classes/java/lang/Double.java +++ b/jdk/src/java.base/share/classes/java/lang/Double.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -301,7 +301,7 @@ public final class Double extends Number implements Comparable { if(d == 0.0) { answer.append("0.0p0"); } else { - boolean subnormal = (d < DoubleConsts.MIN_NORMAL); + boolean subnormal = (d < Double.MIN_NORMAL); // Isolate significand bits and OR in a high-order bit // so that the string representation has a known @@ -329,7 +329,7 @@ public final class Double extends Number implements Comparable { // exponent (the representation of a subnormal uses // E_min -1). answer.append(subnormal ? - DoubleConsts.MIN_EXPONENT: + Double.MIN_EXPONENT: Math.getExponent(d)); } return answer.toString(); @@ -574,7 +574,7 @@ public final class Double extends Number implements Comparable { * @since 1.8 */ public static boolean isFinite(double d) { - return Math.abs(d) <= DoubleConsts.MAX_VALUE; + return Math.abs(d) <= Double.MAX_VALUE; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/Float.java b/jdk/src/java.base/share/classes/java/lang/Float.java index 09eb63527ab..334d3d033da 100644 --- a/jdk/src/java.base/share/classes/java/lang/Float.java +++ b/jdk/src/java.base/share/classes/java/lang/Float.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ package java.lang; import jdk.internal.math.FloatingDecimal; -import jdk.internal.math.FloatConsts; -import jdk.internal.math.DoubleConsts; import jdk.internal.HotSpotIntrinsicCandidate; /** @@ -282,15 +280,15 @@ public final class Float extends Number implements Comparable { * @author Joseph D. Darcy */ public static String toHexString(float f) { - if (Math.abs(f) < FloatConsts.MIN_NORMAL + if (Math.abs(f) < Float.MIN_NORMAL && f != 0.0f ) {// float subnormal // Adjust exponent to create subnormal double, then // replace subnormal double exponent with subnormal float // exponent String s = Double.toHexString(Math.scalb((double)f, /* -1022+126 */ - DoubleConsts.MIN_EXPONENT- - FloatConsts.MIN_EXPONENT)); + Double.MIN_EXPONENT- + Float.MIN_EXPONENT)); return s.replaceFirst("p-1022$", "p-126"); } else // double string will be the same as float string @@ -489,7 +487,7 @@ public final class Float extends Number implements Comparable { * @since 1.8 */ public static boolean isFinite(float f) { - return Math.abs(f) <= FloatConsts.MAX_VALUE; + return Math.abs(f) <= Float.MAX_VALUE; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/Math.java b/jdk/src/java.base/share/classes/java/lang/Math.java index ddb953225a8..17c254a1171 100644 --- a/jdk/src/java.base/share/classes/java/lang/Math.java +++ b/jdk/src/java.base/share/classes/java/lang/Math.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1476,18 +1476,18 @@ public final class Math { int exp = getExponent(d); switch(exp) { - case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity + case Double.MAX_EXPONENT + 1: // NaN or infinity return Math.abs(d); - case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal + case Double.MIN_EXPONENT - 1: // zero or subnormal return Double.MIN_VALUE; default: - assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT; + assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT; // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1); - if (exp >= DoubleConsts.MIN_EXPONENT) { + if (exp >= Double.MIN_EXPONENT) { return powerOfTwoD(exp); } else { @@ -1495,7 +1495,7 @@ public final class Math { // representation of Double.MIN_VALUE appropriate // number of positions return Double.longBitsToDouble(1L << - (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) )); + (exp - (Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) )); } } } @@ -1527,26 +1527,25 @@ public final class Math { int exp = getExponent(f); switch(exp) { - case FloatConsts.MAX_EXPONENT+1: // NaN or infinity + case Float.MAX_EXPONENT+1: // NaN or infinity return Math.abs(f); - case FloatConsts.MIN_EXPONENT-1: // zero or subnormal - return FloatConsts.MIN_VALUE; + case Float.MIN_EXPONENT-1: // zero or subnormal + return Float.MIN_VALUE; default: - assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT; + assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT; // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1); - if (exp >= FloatConsts.MIN_EXPONENT) { + if (exp >= Float.MIN_EXPONENT) { return powerOfTwoF(exp); - } - else { + } else { // return a subnormal result; left shift integer // representation of FloatConsts.MIN_VALUE appropriate // number of positions return Float.intBitsToFloat(1 << - (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) )); + (exp - (Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) )); } } } @@ -2276,7 +2275,7 @@ public final class Math { // nonzero value by it would be guaranteed to over or // underflow; due to rounding, scaling down takes an // additional power of two which is reflected here - final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + + final int MAX_SCALE = Double.MAX_EXPONENT + -Double.MIN_EXPONENT + DoubleConsts.SIGNIFICAND_WIDTH + 1; int exp_adjust = 0; int scale_increment = 0; @@ -2345,7 +2344,7 @@ public final class Math { // nonzero value by it would be guaranteed to over or // underflow; due to rounding, scaling down takes an // additional power of two which is reflected here - final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + + final int MAX_SCALE = Float.MAX_EXPONENT + -Float.MIN_EXPONENT + FloatConsts.SIGNIFICAND_WIDTH + 1; // Make sure scaling factor is in a reasonable range @@ -2371,7 +2370,7 @@ public final class Math { * Returns a floating-point power of two in the normal range. */ static double powerOfTwoD(int n) { - assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT); + assert(n >= Double.MIN_EXPONENT && n <= Double.MAX_EXPONENT); return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK); @@ -2381,7 +2380,7 @@ public final class Math { * Returns a floating-point power of two in the normal range. */ static float powerOfTwoF(int n) { - assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT); + assert(n >= Float.MIN_EXPONENT && n <= Float.MAX_EXPONENT); return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) << (FloatConsts.SIGNIFICAND_WIDTH-1)) & FloatConsts.EXP_BIT_MASK); diff --git a/jdk/src/java.base/share/classes/java/util/Formatter.java b/jdk/src/java.base/share/classes/java/util/Formatter.java index c771ac1ba0c..7e85e967562 100644 --- a/jdk/src/java.base/share/classes/java/util/Formatter.java +++ b/jdk/src/java.base/share/classes/java/util/Formatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3440,7 +3440,7 @@ public final class Formatter implements Closeable, Flushable { int exponent = Math.getExponent(d); boolean subnormal - = (exponent == DoubleConsts.MIN_EXPONENT - 1); + = (exponent == Double.MIN_EXPONENT - 1); // If this is subnormal input so normalize (could be faster to // do as integer operation). @@ -3450,8 +3450,8 @@ public final class Formatter implements Closeable, Flushable { // Calculate the exponent. This is not just exponent + 54 // since the former is not the normalized exponent. exponent = Math.getExponent(d); - assert exponent >= DoubleConsts.MIN_EXPONENT && - exponent <= DoubleConsts.MAX_EXPONENT: exponent; + assert exponent >= Double.MIN_EXPONENT && + exponent <= Double.MAX_EXPONENT: exponent; } int precision = 1 + prec*4; diff --git a/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java b/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java index c0480e9d497..1c773b35743 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java +++ b/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ package jdk.internal.math; /** * This class contains additional constants documenting limits of the - * double type. + * {@code double} type. * * @author Joseph D. Darcy */ @@ -38,69 +38,38 @@ public class DoubleConsts { */ private DoubleConsts() {} - public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY; - public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY; - public static final double NaN = java.lang.Double.NaN; - public static final double MAX_VALUE = java.lang.Double.MAX_VALUE; - public static final double MIN_VALUE = java.lang.Double.MIN_VALUE; - - /** - * A constant holding the smallest positive normal value of type - * double, 2-1022. It is equal to the - * value returned by - * Double.longBitsToDouble(0x0010000000000000L). - * - * @since 1.5 - */ - public static final double MIN_NORMAL = 2.2250738585072014E-308; - - /** * The number of logical bits in the significand of a - * double number, including the implicit bit. + * {@code double} number, including the implicit bit. */ public static final int SIGNIFICAND_WIDTH = 53; /** - * Maximum exponent a finite double number may have. - * It is equal to the value returned by - * Math.ilogb(Double.MAX_VALUE). - */ - public static final int MAX_EXPONENT = 1023; - - /** - * Minimum exponent a normalized double number may - * have. It is equal to the value returned by - * Math.ilogb(Double.MIN_NORMAL). - */ - public static final int MIN_EXPONENT = -1022; - - /** - * The exponent the smallest positive double + * The exponent the smallest positive {@code double} * subnormal value would have if it could be normalized.. */ - public static final int MIN_SUB_EXPONENT = MIN_EXPONENT - + public static final int MIN_SUB_EXPONENT = Double.MIN_EXPONENT - (SIGNIFICAND_WIDTH - 1); /** - * Bias used in representing a double exponent. + * Bias used in representing a {@code double} exponent. */ public static final int EXP_BIAS = 1023; /** - * Bit mask to isolate the sign bit of a double. + * Bit mask to isolate the sign bit of a {@code double}. */ public static final long SIGN_BIT_MASK = 0x8000000000000000L; /** * Bit mask to isolate the exponent field of a - * double. + * {@code double}. */ public static final long EXP_BIT_MASK = 0x7FF0000000000000L; /** * Bit mask to isolate the significand field of a - * double. + * {@code double}. */ public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL; diff --git a/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java b/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java index 977a222278b..05e1ca9e7a6 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java +++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ package jdk.internal.math; /** * This class contains additional constants documenting limits of the - * float type. + * {@code float} type. * * @author Joseph D. Darcy */ @@ -38,65 +38,38 @@ public class FloatConsts { */ private FloatConsts() {} - public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY; - public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY; - public static final float NaN = java.lang.Float.NaN; - public static final float MAX_VALUE = java.lang.Float.MAX_VALUE; - public static final float MIN_VALUE = java.lang.Float.MIN_VALUE; - - /** - * A constant holding the smallest positive normal value of type - * float, 2-126. It is equal to the value - * returned by Float.intBitsToFloat(0x00800000). - */ - public static final float MIN_NORMAL = 1.17549435E-38f; - /** * The number of logical bits in the significand of a - * float number, including the implicit bit. + * {@code float} number, including the implicit bit. */ public static final int SIGNIFICAND_WIDTH = 24; /** - * Maximum exponent a finite float number may have. - * It is equal to the value returned by - * Math.ilogb(Float.MAX_VALUE). - */ - public static final int MAX_EXPONENT = 127; - - /** - * Minimum exponent a normalized float number may - * have. It is equal to the value returned by - * Math.ilogb(Float.MIN_NORMAL). - */ - public static final int MIN_EXPONENT = -126; - - /** - * The exponent the smallest positive float subnormal + * The exponent the smallest positive {@code float} subnormal * value would have if it could be normalized. */ - public static final int MIN_SUB_EXPONENT = MIN_EXPONENT - + public static final int MIN_SUB_EXPONENT = Float.MIN_EXPONENT - (SIGNIFICAND_WIDTH - 1); /** - * Bias used in representing a float exponent. + * Bias used in representing a {@code float} exponent. */ public static final int EXP_BIAS = 127; /** - * Bit mask to isolate the sign bit of a float. + * Bit mask to isolate the sign bit of a {@code float}. */ public static final int SIGN_BIT_MASK = 0x80000000; /** * Bit mask to isolate the exponent field of a - * float. + * {@code float}. */ public static final int EXP_BIT_MASK = 0x7F800000; /** * Bit mask to isolate the significand field of a - * float. + * {@code float}. */ public static final int SIGNIF_BIT_MASK = 0x007FFFFF; diff --git a/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java b/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java index 575255eb174..2f4ade027b9 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2377,8 +2377,8 @@ public class FloatingDecimal{ // Float calculations int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0; - if (exponent >= FloatConsts.MIN_EXPONENT) { - if (exponent > FloatConsts.MAX_EXPONENT) { + if (exponent >= Float.MIN_EXPONENT) { + if (exponent > Float.MAX_EXPONENT) { // Float.POSITIVE_INFINITY floatBits |= FloatConsts.EXP_BIT_MASK; } else { @@ -2409,12 +2409,12 @@ public class FloatingDecimal{ float fValue = Float.intBitsToFloat(floatBits); // Check for overflow and update exponent accordingly. - if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result + if (exponent > Double.MAX_EXPONENT) { // Infinite result // overflow to properly signed infinity return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY; } else { // Finite return value - if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result - exponent >= DoubleConsts.MIN_EXPONENT) { + if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result + exponent >= Double.MIN_EXPONENT) { // The result returned in this block cannot be a // zero or subnormal; however after the @@ -2434,7 +2434,7 @@ public class FloatingDecimal{ (DoubleConsts.SIGNIF_BIT_MASK & significand); } else { // Subnormal or zero - // (exponent < DoubleConsts.MIN_EXPONENT) + // (exponent < Double.MIN_EXPONENT) if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) { // No way to round back to nonzero value @@ -2474,7 +2474,7 @@ public class FloatingDecimal{ // Now, discard the bits significand = significand >> bitsDiscarded; - significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp. + significand = ((((long) (Double.MIN_EXPONENT - 1) + // subnorm exp. (long) DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH - 1)) & DoubleConsts.EXP_BIT_MASK) | diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java index df6af52438c..d10a1e03ec7 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package sun.java2d.marlin; -import jdk.internal.math.DoubleConsts; import jdk.internal.math.FloatConsts; /** @@ -210,14 +209,4 @@ public final class FloatMath implements MarlinConst { } return intpart - 1; } - - /** - * Returns a floating-point power of two in the normal range. - */ - static double powerOfTwoD(int n) { - assert (n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT); - return Double.longBitsToDouble((((long) n + (long) DoubleConsts.EXP_BIAS) - << (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - & DoubleConsts.EXP_BIT_MASK); - } } diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java index aacd8b2062d..043db8adeba 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { private static final int ALL_BUT_LSB = 0xfffffffe; private static final int ERR_STEP_MAX = 0x7fffffff; // = 2^31 - 1 - private static final double POWER_2_TO_32 = FloatMath.powerOfTwoD(32); + private static final double POWER_2_TO_32 = 0x1.0p32; // use float to make tosubpix methods faster (no int to float conversion) public static final float f_SUBPIXEL_POSITIONS_X From 1e1ba844616c376ad16cbacb07d8cb530aa87137 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 16 Feb 2016 09:49:14 -0800 Subject: [PATCH 30/44] 8139927: Improve documentation for CompletableFuture composition 8143089: CompletableFuture.whenComplete should use addSuppressed Reviewed-by: martin, psandoz, chegar, plevart --- .../util/concurrent/CompletableFuture.java | 17 +- .../java/util/concurrent/CompletionStage.java | 384 +++++++++++------- .../concurrent/tck/CompletableFutureTest.java | 9 +- 3 files changed, 249 insertions(+), 161 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index dd24b82f2cc..b3fb80dcd37 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -234,14 +234,13 @@ public class CompletableFuture implements Future, CompletionStage { * Without precautions, CompletableFutures would be prone to * garbage accumulation as chains of Completions build up, each * pointing back to its sources. So we null out fields as soon as - * possible (see especially method Completion.detach). The - * screening checks needed anyway harmlessly ignore null arguments - * that may have been obtained during races with threads nulling - * out fields. We also try to unlink fired Completions from - * stacks that might never be popped (see method postFire). - * Completion fields need not be declared as final or volatile - * because they are only visible to other threads upon safe - * publication. + * possible. The screening checks needed anyway harmlessly ignore + * null arguments that may have been obtained during races with + * threads nulling out fields. We also try to unlink fired + * Completions from stacks that might never be popped (see method + * postFire). Completion fields need not be declared as final or + * volatile because they are only visible to other threads upon + * safe publication. */ volatile Object result; // Either the result or boxed AltResult @@ -800,6 +799,8 @@ public class CompletableFuture implements Future, CompletionStage { } catch (Throwable ex) { if (x == null) x = ex; + else if (x != ex) + x.addSuppressed(ex); } completeThrowable(x, r); } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 1d9d6f3141a..d855945b829 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -46,16 +46,25 @@ import java.util.function.Function; * A stage completes upon termination of its computation, but this may * in turn trigger other dependent stages. The functionality defined * in this interface takes only a few basic forms, which expand out to - * a larger set of methods to capture a range of usage styles: