Mercurial > hg > icedtea8-forest > jdk
changeset 9617:3dd165facde7 jdk8u20-b10
Merge
author | asaha |
---|---|
date | Wed, 09 Apr 2014 12:26:00 -0700 |
parents | b37ecfdc78a2 (current diff) c106b618496a (diff) |
children | a0f5e73db4f9 57c1da89ae1a |
files | .hgtags src/macosx/classes/com/apple/laf/ImageCache.java src/share/classes/java/lang/invoke/BoundMethodHandle.java src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java src/windows/native/sun/windows/awt_Toolkit.cpp test/java/lang/Runtime/exec/CloseRace.java |
diffstat | 114 files changed, 4839 insertions(+), 1920 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Apr 02 10:01:16 2014 -0700 +++ b/.hgtags Wed Apr 09 12:26:00 2014 -0700 @@ -279,3 +279,4 @@ 1ecfc0fac3e7b931f09728b7594384ea5b5f9f0f jdk8u20-b06 db30cb9eb18dacea39c35daf15a3ee5fea41fd86 jdk8u20-b07 0e717bd55bc9e3f3fa3432e545944d81ed887ab0 jdk8u20-b08 +bfcdcc29c8823595a5d70b5b633bedcd5ee3ba8e jdk8u20-b09
--- a/src/macosx/classes/com/apple/laf/AquaIcon.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaIcon.java Wed Apr 09 12:26:00 2014 -0700 @@ -295,14 +295,8 @@ } Image createImage() { - int w = getIconWidth(); - int h = getIconHeight(); - return new AquaImageFactory.MultiResolutionIconImage( - AquaUtils.getCImageCreator().createSystemImageFromSelector( - selector, w, h), - AquaUtils.getCImageCreator().createSystemImageFromSelector( - selector, 2 * w, 2 * h) - ); + return AquaUtils.getCImageCreator().createSystemImageFromSelector( + selector, getIconWidth(), getIconHeight()); } } }
--- a/src/macosx/classes/com/apple/laf/AquaImageFactory.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaImageFactory.java Wed Apr 09 12:26:00 2014 -0700 @@ -125,16 +125,14 @@ private static final int kAlertIconSize = 64; static IconUIResource getAppIconCompositedOn(final Image background) { - final BufferedImage iconImage = getAppIconImageCompositedOn(background, 1); + if (background instanceof MultiResolutionBufferedImage) { + int width = background.getWidth(null); + Image mrIconImage = ((MultiResolutionBufferedImage) background).map( + rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width)); + return new IconUIResource(new ImageIcon(mrIconImage)); + } - if (background instanceof MultiResolutionIconImage) { - BufferedImage background2x - = ((MultiResolutionIconImage) background).resolutionVariant; - BufferedImage icon2xImage = getAppIconImageCompositedOn(background2x, 2); - - return new IconUIResource(new ImageIcon( - new MultiResolutionIconImage(iconImage, icon2xImage))); - } + BufferedImage iconImage = getAppIconImageCompositedOn(background, 1); return new IconUIResource(new ImageIcon(iconImage)); } @@ -312,10 +310,16 @@ return icon; } - Image icon2x = AquaUtils.getCImageCreator().createImageFromName( - imageName, 2 * icon.getWidth(null), 2 * icon.getHeight(null)); - return new MultiResolutionBufferedImage( - BufferedImage.TYPE_INT_ARGB_PRE, 0, icon, icon2x); + int w = icon.getWidth(null); + int h = icon.getHeight(null); + + Dimension[] sizes = new Dimension[]{ + new Dimension(w, h), new Dimension(2 * w, 2 * h) + }; + + return new MultiResolutionBufferedImage(icon, sizes, (width, height) -> + AquaUtils.getCImageCreator().createImageFromName( + imageName, width, height)); } public static class NineSliceMetrics { @@ -524,29 +528,4 @@ public static Color getSelectionInactiveForegroundColorUIResource() { return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.INACTIVE_SELECTION_FOREGROUND_COLOR)); } - - static class MultiResolutionIconImage extends BufferedImage - implements MultiResolutionImage { - - BufferedImage resolutionVariant; - - public MultiResolutionIconImage(BufferedImage image, BufferedImage resolutionVariant) { - super(image.getWidth(), image.getHeight(), image.getType()); - this.resolutionVariant = resolutionVariant; - Graphics g = getGraphics(); - g.drawImage(image, 0, 0, null); - g.dispose(); - } - - @Override - public Image getResolutionVariant(int width, int height) { - return ((width <= getWidth() && height <= getHeight())) - ? this : resolutionVariant; - } - - @Override - public List<Image> getResolutionVariants() { - return Arrays.asList(this, resolutionVariant); - } - } -} +} \ No newline at end of file
--- a/src/macosx/classes/com/apple/laf/AquaPainter.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaPainter.java Wed Apr 09 12:26:00 2014 -0700 @@ -38,6 +38,7 @@ import sun.print.*; import apple.laf.*; import apple.laf.JRSUIUtils.NineSliceMetricsProvider; +import sun.awt.image.ImageCache; abstract class AquaPainter <T extends JRSUIState> { static <T extends JRSUIState> AquaPainter<T> create(final T state) { @@ -155,10 +156,15 @@ final ImageCache cache = ImageCache.getInstance(); final int imgW = bounds.width * scale; final int imgH = bounds.height * scale; - BufferedImage img = (BufferedImage) cache.getImage(config, imgW, imgH, scale, controlState); + AquaPixelsKey key = new AquaPixelsKey(config, + imgW, imgH, scale, controlState); + BufferedImage img = (BufferedImage) cache.getImage(key); if (img == null) { img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB_PRE); - cache.setImage(img, config, imgW, imgH, scale, controlState); + if (!controlState.is(JRSUIConstants.Animating.YES)) { + cache.setImage(key, img); + } + final WritableRaster raster = img.getRaster(); final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); @@ -172,6 +178,59 @@ } } + private static class AquaPixelsKey implements ImageCache.PixelsKey { + + private final int pixelCount; + private final int hash; + + // key parts + private final GraphicsConfiguration config; + private final int w; + private final int h; + private final int scale; + private final JRSUIState state; + + AquaPixelsKey(final GraphicsConfiguration config, + final int w, final int h, final int scale, + final JRSUIState state) { + this.pixelCount = w * h; + this.config = config; + this.w = w; + this.h = h; + this.scale = scale; + this.state = state; + this.hash = hash(); + } + + public int getPixelCount() { + return pixelCount; + } + + private int hash() { + int hash = config != null ? config.hashCode() : 0; + hash = 31 * hash + w; + hash = 31 * hash + h; + hash = 31 * hash + scale; + hash = 31 * hash + state.hashCode(); + return hash; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AquaPixelsKey) { + AquaPixelsKey key = (AquaPixelsKey) obj; + return config == key.config && w == key.w && h == key.h + && scale == key.scale && state.equals(key.state); + } + return false; + } + } + private static class RecyclableJRSUISlicedImageControl extends RecyclableSlicedImageControl {
--- a/src/macosx/classes/com/apple/laf/AquaUtils.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/com/apple/laf/AquaUtils.java Wed Apr 09 12:26:00 2014 -0700 @@ -177,16 +177,7 @@ abstract static class RecyclableSingleton<T> { final T get() { - final AppContext appContext = AppContext.getAppContext(); - SoftReference<T> ref = (SoftReference<T>) appContext.get(this); - if (ref != null) { - final T object = ref.get(); - if (object != null) return object; - } - final T object = getInstance(); - ref = new SoftReference<T>(object); - appContext.put(this, ref); - return object; + return AppContext.getSoftReferenceValue(this, () -> getInstance()); } void reset() {
--- a/src/macosx/classes/com/apple/laf/ImageCache.java Wed Apr 02 10:01:16 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.apple.laf; - -import java.awt.*; -import java.lang.ref.*; -import java.util.*; -import java.util.concurrent.locks.*; - -import apple.laf.JRSUIConstants; -import apple.laf.JRSUIState; -import com.apple.laf.AquaUtils.RecyclableSingleton; - -/** - * ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary set of arguments. All images are held with - * SoftReferences so they will be dropped by the GC if heap memory gets tight. When our size hits max pixel count least - * recently requested images are removed first. - */ -final class ImageCache { - // Ordered Map keyed by args hash, ordered by most recent accessed entry. - private final LinkedHashMap<Integer, PixelCountSoftReference> map = new LinkedHashMap<>(16, 0.75f, true); - - // Maximum number of pixels to cache, this is used if maxCount - private final int maxPixelCount; - // The current number of pixels stored in the cache - private int currentPixelCount = 0; - - // Lock for concurrent access to map - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - // Reference queue for tracking lost softreferences to images in the cache - private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>(); - - // Singleton Instance - private static final RecyclableSingleton<ImageCache> instance = new RecyclableSingleton<ImageCache>() { - @Override - protected ImageCache getInstance() { - return new ImageCache(); - } - }; - static ImageCache getInstance() { - return instance.get(); - } - - ImageCache(final int maxPixelCount) { - this.maxPixelCount = maxPixelCount; - } - - ImageCache() { - this((8 * 1024 * 1024) / 4); // 8Mb of pixels - } - - public void flush() { - lock.writeLock().lock(); - try { - map.clear(); - } finally { - lock.writeLock().unlock(); - } - } - - public Image getImage(final GraphicsConfiguration config, final int w, - final int h, final int scale, - final JRSUIState state) { - final int hash = hash(config, w, h, scale, state); - final PixelCountSoftReference ref; - lock.readLock().lock(); - try { - ref = map.get(hash); - } finally { - lock.readLock().unlock(); - } - // check reference has not been lost and the key truly matches, - // in case of false positive hash match - if (ref != null && ref.equals(config, w, h, scale, state)) { - return ref.get(); - } - return null; - } - - /** - * Sets the cached image for the specified constraints. - * - * @param image The image to store in cache - * @param config The graphics configuration, needed if cached image is a Volatile Image. Used as part of cache key - * @param w The image width, used as part of cache key - * @param h The image height, used as part of cache key - * @param scale The image scale factor, used as part of cache key - * @return true if the image could be cached, false otherwise. - */ - public boolean setImage(final Image image, - final GraphicsConfiguration config, final int w, final int h, - final int scale, final JRSUIState state) { - if (state.is(JRSUIConstants.Animating.YES)) { - return false; - } - - final int hash = hash(config, w, h, scale, state); - - lock.writeLock().lock(); - try { - PixelCountSoftReference ref = map.get(hash); - // check if currently in map - if (ref != null && ref.get() == image) return true; - - // clear out old - if (ref != null) { - currentPixelCount -= ref.pixelCount; - map.remove(hash); - } - - // add new image to pixel count - final int newPixelCount = image.getWidth(null) * image.getHeight(null); - currentPixelCount += newPixelCount; - // clean out lost references if not enough space - if (currentPixelCount > maxPixelCount) { - while ((ref = (PixelCountSoftReference)referenceQueue.poll()) != null) { - //reference lost - map.remove(ref.hash); - currentPixelCount -= ref.pixelCount; - } - } - - // remove old items till there is enough free space - if (currentPixelCount > maxPixelCount) { - final Iterator<Map.Entry<Integer, PixelCountSoftReference>> mapIter = map.entrySet().iterator(); - while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) { - final Map.Entry<Integer, PixelCountSoftReference> entry = mapIter.next(); - mapIter.remove(); - final Image img = entry.getValue().get(); - if (img != null) img.flush(); - currentPixelCount -= entry.getValue().pixelCount; - } - } - // finally put new in map - map.put(hash, new PixelCountSoftReference(image, referenceQueue, newPixelCount, hash, config, w, h, scale, state)); - return true; - } finally { - lock.writeLock().unlock(); - } - } - - private static int hash(final GraphicsConfiguration config, final int w, - final int h, final int scale, - final JRSUIState state) { - int hash = config != null ? config.hashCode() : 0; - hash = 31 * hash + w; - hash = 31 * hash + h; - hash = 31 * hash + scale; - hash = 31 * hash + state.hashCode(); - return hash; - } - - /** - * Extended SoftReference that stores the pixel count even after the image - * is lost. - */ - private static class PixelCountSoftReference extends SoftReference<Image> { - - // default access, because access to these fields shouldn't be emulated - // by a synthetic accessor. - final int pixelCount; - final int hash; - - // key parts - private final GraphicsConfiguration config; - private final int w; - private final int h; - private final int scale; - private final JRSUIState state; - - PixelCountSoftReference(final Image referent, - final ReferenceQueue<? super Image> q, final int pixelCount, - final int hash, final GraphicsConfiguration config, final int w, - final int h, final int scale, final JRSUIState state) { - super(referent, q); - this.pixelCount = pixelCount; - this.hash = hash; - this.config = config; - this.w = w; - this.h = h; - this.scale = scale; - this.state = state; - } - - boolean equals(final GraphicsConfiguration config, final int w, - final int h, final int scale, final JRSUIState state) { - return config == this.config && w == this.w && h == this.h - && scale == this.scale && state.equals(this.state); - } - } - -// /** Gets the rendered image for this painter at the requested size, either from cache or create a new one */ -// private VolatileImage getImage(GraphicsConfiguration config, JComponent c, int w, int h, Object[] extendedCacheKeys) { -// VolatileImage buffer = (VolatileImage)getImage(config, w, h, this, extendedCacheKeys); -// -// int renderCounter = 0; // to avoid any potential, though unlikely, infinite loop -// do { -// //validate the buffer so we can check for surface loss -// int bufferStatus = VolatileImage.IMAGE_INCOMPATIBLE; -// if (buffer != null) { -// bufferStatus = buffer.validate(config); -// } -// -// //If the buffer status is incompatible or restored, then we need to re-render to the volatile image -// if (bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE || bufferStatus == VolatileImage.IMAGE_RESTORED) { -// // if the buffer isn't the right size, or has lost its contents, then recreate -// if (buffer != null) { -// if (buffer.getWidth() != w || buffer.getHeight() != h || bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE) { -// // clear any resources related to the old back buffer -// buffer.flush(); -// buffer = null; -// } -// } -// -// if (buffer == null) { -// // recreate the buffer -// buffer = config.createCompatibleVolatileImage(w, h, Transparency.TRANSLUCENT); -// // put in cache for future -// setImage(buffer, config, w, h, this, extendedCacheKeys); -// } -// -// //create the graphics context with which to paint to the buffer -// Graphics2D bg = buffer.createGraphics(); -// -// //clear the background before configuring the graphics -// bg.setComposite(AlphaComposite.Clear); -// bg.fillRect(0, 0, w, h); -// bg.setComposite(AlphaComposite.SrcOver); -// bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); -// -// // paint the painter into buffer -// paint0(bg, c, w, h, extendedCacheKeys); -// //close buffer graphics -// bg.dispose(); -// } -// } while (buffer.contentsLost() && renderCounter++ < 3); -// -// // check if we failed -// if (renderCounter >= 3) return null; -// -// return buffer; -// } -}
--- a/src/macosx/classes/sun/lwawt/macosx/CImage.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/CImage.java Wed Apr 09 12:26:00 2014 -0700 @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.List; import sun.awt.image.MultiResolutionImage; +import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.SunWritableRaster; @@ -42,10 +43,11 @@ private static native long nativeCreateNSImageOfFileFromLaunchServices(String file); private static native long nativeCreateNSImageFromImageName(String name); private static native long nativeCreateNSImageFromIconSelector(int selector); - private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int w, int h); + private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int sw, int sh, int dw, int dh); private static native Dimension2D nativeGetNSImageSize(long image); private static native void nativeSetNSImageSize(long image, double w, double h); private static native void nativeResizeNSImageRepresentations(long image, double w, double h); + private static native Dimension2D[] nativeGetNSImageRepresentationSizes(long image, double w, double h); static Creator creator = new Creator(); static Creator getCreator() { @@ -210,18 +212,30 @@ super(nsImagePtr, true); } - /** @return A BufferedImage created from nsImagePtr, or null. */ - public BufferedImage toImage() { + /** @return A MultiResolution image created from nsImagePtr, or null. */ + private BufferedImage toImage() { if (ptr == 0) return null; final Dimension2D size = nativeGetNSImageSize(ptr); final int w = (int)size.getWidth(); final int h = (int)size.getHeight(); - final BufferedImage bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); + Dimension2D[] sizes + = nativeGetNSImageRepresentationSizes(ptr, + size.getWidth(), size.getHeight()); + + BufferedImage baseImage = toImage(w, h, w, h); + + return sizes == null || sizes.length < 2 ? baseImage + : new MultiResolutionBufferedImage(baseImage, sizes, + (width, height) -> toImage(w, h, width, height)); + } + + private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) { + final BufferedImage bimg = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB_PRE); final DataBufferInt dbi = (DataBufferInt)bimg.getRaster().getDataBuffer(); final int[] buffer = SunWritableRaster.stealData(dbi, 0); - nativeCopyNSImageIntoArray(ptr, buffer, w, h); + nativeCopyNSImageIntoArray(ptr, buffer, srcWidth, srcHeight, dstWidth, dstHeight); SunWritableRaster.markDirty(dbi); return bimg; }
--- a/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Wed Apr 09 12:26:00 2014 -0700 @@ -41,7 +41,7 @@ import sun.java2d.*; import sun.print.*; -final class CPrinterJob extends RasterPrinterJob { +public final class CPrinterJob extends RasterPrinterJob { // NOTE: This uses RasterPrinterJob as a base, but it doesn't use // all of the RasterPrinterJob functions. RasterPrinterJob will // break down printing to pieces that aren't necessary under MacOSX
--- a/src/macosx/native/sun/awt/AWTWindow.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/AWTWindow.m Wed Apr 09 12:26:00 2014 -0700 @@ -762,6 +762,10 @@ return lastKeyWindow; } +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { + return !NSEqualSizes(self.nsWindow.frame.size, newFrame.size); +} + @end // AWTWindow
--- a/src/macosx/native/sun/awt/CImage.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/CImage.m Wed Apr 09 12:26:00 2014 -0700 @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +#import "jni_util.h" #import <Cocoa/Cocoa.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> @@ -52,18 +53,21 @@ } static void CImage_CopyNSImageIntoArray -(NSImage *srcImage, jint *dstPixels, int width, int height) +(NSImage *srcImage, jint *dstPixels, NSRect fromRect, NSRect toRect) { + int width = toRect.size.width; + int height = toRect.size.height; CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); - CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height, 8, width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height, + 8, width * 4, colorspace, + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); CGColorSpaceRelease(colorspace); NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgRef flipped:NO]; CGContextRelease(cgRef); NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain]; [NSGraphicsContext setCurrentContext:context]; - NSRect rect = NSMakeRect(0, 0, width, height); - [srcImage drawInRect:rect - fromRect:rect + [srcImage drawInRect:toRect + fromRect:fromRect operation:NSCompositeSourceOver fraction:1.0]; [NSGraphicsContext setCurrentContext:oldContext]; @@ -266,17 +270,20 @@ /* * Class: sun_lwawt_macosx_CImage * Method: nativeCopyNSImageIntoArray - * Signature: (J[III)V + * Signature: (J[IIIII)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray -(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint w, jint h) +(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint sw, jint sh, + jint dw, jint dh) { JNF_COCOA_ENTER(env); NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr); jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL); if (dst) { - CImage_CopyNSImageIntoArray(img, dst, w, h); + NSRect fromRect = NSMakeRect(0, 0, sw, sh); + NSRect toRect = NSMakeRect(0, 0, dw, dh); + CImage_CopyNSImageIntoArray(img, dst, fromRect, toRect); (*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT); } @@ -343,3 +350,87 @@ JNF_COCOA_EXIT(env); } + +NSComparisonResult getOrder(BOOL order){ + return (NSComparisonResult) (order ? NSOrderedAscending : NSOrderedDescending); +} + +/* + * Class: sun_lwawt_macosx_CImage + * Method: nativeGetNSImageRepresentationsCount + * Signature: (JDD)[Ljava/awt/geom/Dimension2D; + */ +JNIEXPORT jobjectArray JNICALL + Java_sun_lwawt_macosx_CImage_nativeGetNSImageRepresentationSizes +(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h) +{ + if (!image) return NULL; + jobjectArray jreturnArray = NULL; + NSImage *img = (NSImage *)jlong_to_ptr(image); + +JNF_COCOA_ENTER(env); + + NSArray *imageRepresentations = [img representations]; + if([imageRepresentations count] == 0){ + return NULL; + } + + NSArray *sortedImageRepresentations = [imageRepresentations + sortedArrayUsingComparator: ^(id obj1, id obj2) { + + NSImageRep *imageRep1 = (NSImageRep *) obj1; + NSImageRep *imageRep2 = (NSImageRep *) obj2; + NSSize size1 = [imageRep1 size]; + NSSize size2 = [imageRep2 size]; + + if (NSEqualSizes(size1, size2)) { + return getOrder([imageRep1 pixelsWide] <= [imageRep2 pixelsWide] && + [imageRep1 pixelsHigh] <= [imageRep2 pixelsHigh]); + } + + return getOrder(size1.width <= size2.width && size1.height <= size2.height); + }]; + + NSMutableArray *sortedPixelSizes = [[[NSMutableArray alloc] init] autorelease]; + NSSize lastSize = [[sortedImageRepresentations lastObject] size]; + + NSUInteger i = [sortedImageRepresentations indexOfObjectPassingTest: + ^BOOL(id obj, NSUInteger idx, BOOL *stop) { + NSSize imageRepSize = [obj size]; + return (w <= imageRepSize.width && h <= imageRepSize.height) + || NSEqualSizes(imageRepSize, lastSize); + }]; + + NSUInteger count = [sortedImageRepresentations count]; + i = (i == NSNotFound) ? count - 1 : i; + NSSize bestFitSize = [[sortedImageRepresentations objectAtIndex: i] size]; + + for(; i < count; i++){ + NSImageRep *imageRep = [sortedImageRepresentations objectAtIndex: i]; + + if (!NSEqualSizes([imageRep size], bestFitSize)) { + break; + } + + NSSize pixelSize = NSMakeSize( + [imageRep pixelsWide], [imageRep pixelsHigh]); + [sortedPixelSizes addObject: [NSValue valueWithSize: pixelSize]]; + } + + count = [sortedPixelSizes count]; + static JNF_CLASS_CACHE(jc_Dimension, "java/awt/Dimension"); + jreturnArray = JNFNewObjectArray(env, &jc_Dimension, count); + CHECK_NULL_RETURN(jreturnArray, NULL); + + for(i = 0; i < count; i++){ + NSSize pixelSize = [[sortedPixelSizes objectAtIndex: i] sizeValue]; + + (*env)->SetObjectArrayElement(env, jreturnArray, i, + NSToJavaSize(env, pixelSize)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); + } + +JNF_COCOA_EXIT(env); + + return jreturnArray; +} \ No newline at end of file
--- a/src/macosx/native/sun/awt/CTextPipe.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/CTextPipe.m Wed Apr 09 12:26:00 2014 -0700 @@ -147,7 +147,7 @@ CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx); - NSUInteger i; + NSInteger i; for (i = 0; i < length; i++) { CGGlyph glyph = glyphs[i]; @@ -355,19 +355,31 @@ static JNF_CLASS_CACHE(jc_StandardGlyphVector_GlyphTransformInfo, "sun/font/StandardGlyphVector$GlyphTransformInfo"); static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_transforms, jc_StandardGlyphVector_GlyphTransformInfo, "transforms", "[D"); jdoubleArray g_gtiTransformsArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_transforms); //(*env)->GetObjectField(env, gti, g_gtiTransforms); + if (g_gtiTransformsArray == NULL) { + return; + } jdouble *g_gvTransformsAsDoubles = (*env)->GetPrimitiveArrayCritical(env, g_gtiTransformsArray, NULL); + if (g_gvTransformsAsDoubles == NULL) { + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + return; + } static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_indices, jc_StandardGlyphVector_GlyphTransformInfo, "indices", "[I"); jintArray g_gtiTXIndicesArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_indices); jint *g_gvTXIndicesAsInts = (*env)->GetPrimitiveArrayCritical(env, g_gtiTXIndicesArray, NULL); - + if (g_gvTXIndicesAsInts == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT); + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray); + return; + } // slowest case, we have per-glyph transforms, and possibly glyph substitution as well JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length); (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT); - (*env)->DeleteLocalRef(env, g_gtiTransformsArray); + (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT); - (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT); + (*env)->DeleteLocalRef(env, g_gtiTransformsArray); (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray); } @@ -403,6 +415,9 @@ { // fill the glyph buffer jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL); + if (glyphsAsInts == NULL) { + return; + } // if a glyph code from Java is negative, that means it is really a unicode value // which we can use in CoreText to strike the character in another font @@ -429,11 +444,15 @@ // fill the advance buffer static JNF_MEMBER_CACHE(jm_StandardGlyphVector_positions, jc_StandardGlyphVector, "positions", "[F"); jfloatArray posArray = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_positions); - if (posArray != NULL) - { + jfloat *positions = NULL; + if (posArray != NULL) { // in this case, the positions have already been pre-calculated for us on the Java side - - jfloat *positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL); + positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL); + if (positions == NULL) { + (*env)->DeleteLocalRef(env, posArray); + } + } + if (positions != NULL) { CGPoint prev; prev.x = positions[0]; prev.y = positions[1];
--- a/src/macosx/native/sun/awt/ImageSurfaceData.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/ImageSurfaceData.m Wed Apr 09 12:26:00 2014 -0700 @@ -849,7 +849,7 @@ indexOfBest = 0; distanceOfBest = DBL_MAX; - for (i=0; i<lutDataSize; i++) + for (i=0; (unsigned)i<lutDataSize; i++) { p2 = lutdata[i]; @@ -899,7 +899,7 @@ { if (data != NULL) { - free(data); + free((void*)data); } } @@ -1577,7 +1577,9 @@ { static char *bimgName = "java/awt/image/BufferedImage"; jclass bimg = (*env)->FindClass(env, bimgName); + CHECK_NULL_RETURN(bimg, NULL); sDataID = (*env)->GetFieldID(env, bimg, "sData", "Lsun/java2d/SurfaceData;"); + CHECK_NULL_RETURN(sDataID, NULL); } return (*env)->GetObjectField(env, bufImg, sDataID); @@ -1591,7 +1593,9 @@ { static char *bimgName = "java/awt/image/BufferedImage"; jclass bimg = (*env)->FindClass(env, bimgName); + CHECK_NULL(bimg); sDataID = (*env)->GetFieldID(env, bimg, "sData", "Lsun/java2d/SurfaceData;"); + CHECK_NULL(sDataID); } (*env)->SetObjectField(env, bufImg, sDataID, sData); @@ -1610,18 +1614,11 @@ return; } - icm = (*env)->FindClass(env, icmName); - if (icm == NULL) { - return; - } - - rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I"); - allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z"); - mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I"); - CMpDataID = (*env)->GetFieldID(env, icm, "pData", "J"); - if (allGrayID == 0 || rgbID == 0 || mapSizeID == 0 || CMpDataID == 0) { - JNU_ThrowInternalError(env, "Could not get field IDs"); - } + CHECK_NULL(icm = (*env)->FindClass(env, icmName)); + CHECK_NULL(rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I")); + CHECK_NULL(allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z")); + CHECK_NULL(mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I")); + CHECK_NULL(CMpDataID = (*env)->GetFieldID(env, icm, "pData", "J")); } gColorspaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); @@ -1795,6 +1792,7 @@ //bisdo->sdOps.Dispose = BufImg_Dispose; bisdo->array = (*env)->NewWeakGlobalRef(env, array); + if (array != NULL) CHECK_NULL(bisdo->array); bisdo->offset = offset; //bisdo->scanStr = scanStr; bisdo->scanStr = scanStride; @@ -1807,8 +1805,10 @@ } else { jobject lutarray = (*env)->GetObjectField(env, icm, rgbID); bisdo->lutarray = (*env)->NewWeakGlobalRef(env, lutarray); + if (lutarray != NULL) CHECK_NULL(bisdo->lutarray); bisdo->lutsize = (*env)->GetIntField(env, icm, mapSizeID); bisdo->icm = (*env)->NewWeakGlobalRef(env, icm); + if (icm != NULL) CHECK_NULL(bisdo->icm); } bisdo->rasbounds.x1 = 0; bisdo->rasbounds.y1 = 0; @@ -1887,7 +1887,7 @@ Pixel32bit* src = lutdata; Pixel32bit* dst = isdo->lutData; jint i; - for (i=0; i<isdo->lutDataSize; i++) + for (i=0; (unsigned)i<isdo->lutDataSize; i++) { if (i != transparent_index) { @@ -1919,7 +1919,7 @@ Pixel32bit* src = lutdata; Pixel32bit* dst = isdo->lutData; jint i; - for (i=0; i<isdo->lutDataSize; i++) + for (i=0; (unsigned)i<isdo->lutDataSize; i++) { *dst = *src | mask; dst++; src++;
--- a/src/macosx/native/sun/awt/QuartzRenderer.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/QuartzRenderer.m Wed Apr 09 12:26:00 2014 -0700 @@ -438,6 +438,9 @@ { SDRenderType renderType = SD_Nothing; + if (xpointsarray == NULL || ypointsarray == NULL) { + return SD_Nothing; + } if (npoints > 1) { if (fill == YES) @@ -452,7 +455,14 @@ jint i; jint* xpoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, xpointsarray, NULL); + if (xpoints == NULL) { + return SD_Nothing; + } jint* ypoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, ypointsarray, NULL); + if (ypoints == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, xpointsarray, xpoints, 0); + return SD_Nothing; + } CGContextMoveToPoint(cgRef, xpoints[0]+offsetX, ypoints[0]+offsetY);
--- a/src/macosx/native/sun/awt/QuartzSurfaceData.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/awt/QuartzSurfaceData.m Wed Apr 09 12:26:00 2014 -0700 @@ -778,6 +778,10 @@ qsdo->graphicsStateInfo.simpleStroke = NO; jint length = (*env)->GetArrayLength(env, dasharray); jfloat* jdashes = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, dasharray, NULL); + if (jdashes == NULL) { + CGContextSetLineDash(cgRef, 0, NULL, 0); + return; + } CGFloat* dashes = (CGFloat*)malloc(sizeof(CGFloat)*length); if (dashes != NULL) {
--- a/src/macosx/native/sun/font/AWTStrike.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/font/AWTStrike.m Wed Apr 09 12:26:00 2014 -0700 @@ -127,6 +127,9 @@ } jdouble *txPtr = (*env)->GetPrimitiveArrayCritical(env, txArray, NULL); + if (txPtr == NULL) { + return CGAffineTransformIdentity; + } CGAffineTransform tx = CGAffineTransformMake(txPtr[0], txPtr[1], txPtr[2], @@ -311,18 +314,22 @@ jlong *glyphInfos = (*env)->GetPrimitiveArrayCritical(env, glyphInfoLongArray, NULL); + if (glyphInfos != NULL) { jint *rawGlyphCodes = (*env)->GetPrimitiveArrayCritical(env, glyphCodes, NULL); + if (rawGlyphCodes != NULL) { CGGlyphImages_GetGlyphImagePtrs(glyphInfos, awtStrike, rawGlyphCodes, len); (*env)->ReleasePrimitiveArrayCritical(env, glyphCodes, rawGlyphCodes, JNI_ABORT); + } // Do not use JNI_COMMIT, as that will not free the buffer copy // when +ProtectJavaHeap is on. (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray, glyphInfos, 0); + } JNF_COCOA_EXIT(env); }
--- a/src/macosx/native/sun/font/CCharToGlyphMapper.m Wed Apr 02 10:01:16 2014 -0700 +++ b/src/macosx/native/sun/font/CCharToGlyphMapper.m Wed Apr 09 12:26:00 2014 -0700 @@ -101,10 +101,13 @@ jchar *unicodesAsChars = (*env)->GetPrimitiveArrayCritical(env, unicodes, NULL); - AllocateGlyphBuffer(env, awtFont, count, (UniChar *)unicodesAsChars, glyphs); + if (unicodesAsChars != NULL) { + AllocateGlyphBuffer(env, awtFont, count, + (UniChar *)unicodesAsChars, glyphs); (*env)->ReleasePrimitiveArrayCritical(env, unicodes, unicodesAsChars, JNI_ABORT); + } JNF_COCOA_EXIT(env); }
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Wed Apr 09 12:26:00 2014 -0700 @@ -787,6 +787,14 @@ if (!reconnected) { try { NotificationResult nr = fetchNotifs(-1, 0, 0); + + if (state != STOPPED) { // JDK-8038940 + // reconnection must happen during + // fetchNotifs(-1, 0, 0), and a new + // thread takes over the fetching job + return; + } + clientSequenceNumber = nr.getNextSequenceNumber(); } catch (ClassNotFoundException e) { // can't happen
--- a/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 09 12:26:00 2014 -0700 @@ -862,4 +862,18 @@ * All subclasses must provide such a value describing their type signature. */ static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY; + + private static final SpeciesData[] SPECIES_DATA_CACHE = new SpeciesData[5]; + private static SpeciesData checkCache(int size, String types) { + int idx = size - 1; + SpeciesData data = SPECIES_DATA_CACHE[idx]; + if (data != null) return data; + SPECIES_DATA_CACHE[idx] = data = getSpeciesData(types); + return data; + } + static SpeciesData speciesData_L() { return checkCache(1, "L"); } + static SpeciesData speciesData_LL() { return checkCache(2, "LL"); } + static SpeciesData speciesData_LLL() { return checkCache(3, "LLL"); } + static SpeciesData speciesData_LLLL() { return checkCache(4, "LLLL"); } + static SpeciesData speciesData_LLLLL() { return checkCache(5, "LLLLL"); } }
--- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Apr 09 12:26:00 2014 -0700 @@ -27,7 +27,6 @@ import sun.invoke.util.VerifyAccess; import java.lang.invoke.LambdaForm.Name; -import java.lang.invoke.MethodHandles.Lookup; import sun.invoke.util.Wrapper; @@ -39,8 +38,6 @@ import java.lang.reflect.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; -import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; /** @@ -51,7 +48,7 @@ class InvokerBytecodeGenerator { /** Define class names for convenience. */ private static final String MH = "java/lang/invoke/MethodHandle"; - private static final String BMH = "java/lang/invoke/BoundMethodHandle"; + private static final String MHI = "java/lang/invoke/MethodHandleImpl"; private static final String LF = "java/lang/invoke/LambdaForm"; private static final String LFN = "java/lang/invoke/LambdaForm$Name"; private static final String CLS = "java/lang/Class"; @@ -61,6 +58,7 @@ private static final String LF_SIG = "L" + LF + ";"; private static final String LFN_SIG = "L" + LFN + ";"; private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; + private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ private static final String superName = LF; @@ -438,7 +436,7 @@ mv.visitLdcInsn(constantPlaceholder(pclass)); mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG); if (pclass.isArray()) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); } @@ -512,17 +510,22 @@ Name name = lambdaForm.names[i]; MemberName member = name.function.member(); - if (isSelectAlternative(member)) { - // selectAlternative idiom - // FIXME: make sure this idiom is really present! + if (isSelectAlternative(i)) { emitSelectAlternative(name, lambdaForm.names[i + 1]); i++; // skip MH.invokeBasic of the selectAlternative result + } else if (isGuardWithCatch(i)) { + emitGuardWithCatch(i); + i = i+2; // Jump to the end of GWC idiom } else if (isStaticallyInvocable(member)) { emitStaticInvoke(member, name); } else { emitInvoke(name); } + // Update cached form name's info in case an intrinsic spanning multiple names was encountered. + name = lambdaForm.names[i]; + member = name.function.member(); + // store the result from evaluating to the target name in a local if required // (if this is the last value, i.e., the one that is going to be returned, // avoid store/load/return and just return) @@ -675,12 +678,66 @@ } /** - * Check if MemberName is a call to MethodHandleImpl.selectAlternative. + * Check if MemberName is a call to a method named {@code name} in class {@code declaredClass}. + */ + private boolean memberRefersTo(MemberName member, Class<?> declaringClass, String name) { + return member != null && + member.getDeclaringClass() == declaringClass && + member.getName().equals(name); + } + private boolean nameRefersTo(Name name, Class<?> declaringClass, String methodName) { + return name.function != null && + memberRefersTo(name.function.member(), declaringClass, methodName); + } + + /** + * Check if MemberName is a call to MethodHandle.invokeBasic. + */ + private boolean isInvokeBasic(Name name) { + if (name.function == null) + return false; + if (name.arguments.length < 1) + return false; // must have MH argument + MemberName member = name.function.member(); + return memberRefersTo(member, MethodHandle.class, "invokeBasic") && + !member.isPublic() && !member.isStatic(); + } + + /** + * Check if i-th name is a call to MethodHandleImpl.selectAlternative. */ - private boolean isSelectAlternative(MemberName member) { - return member != null && - member.getDeclaringClass() == MethodHandleImpl.class && - member.getName().equals("selectAlternative"); + private boolean isSelectAlternative(int pos) { + // selectAlternative idiom: + // t_{n}:L=MethodHandleImpl.selectAlternative(...) + // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...) + if (pos+1 >= lambdaForm.names.length) return false; + Name name0 = lambdaForm.names[pos]; + Name name1 = lambdaForm.names[pos+1]; + return nameRefersTo(name0, MethodHandleImpl.class, "selectAlternative") && + isInvokeBasic(name1) && + name1.lastUseIndex(name0) == 0 && // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...) + lambdaForm.lastUseIndex(name0) == pos+1; // t_{n} is local: used only in t_{n+1} + } + + /** + * Check if i-th name is a start of GuardWithCatch idiom. + */ + private boolean isGuardWithCatch(int pos) { + // GuardWithCatch idiom: + // t_{n}:L=MethodHandle.invokeBasic(...) + // t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n}); + // t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1}) + if (pos+2 >= lambdaForm.names.length) return false; + Name name0 = lambdaForm.names[pos]; + Name name1 = lambdaForm.names[pos+1]; + Name name2 = lambdaForm.names[pos+2]; + return nameRefersTo(name1, MethodHandleImpl.class, "guardWithCatch") && + isInvokeBasic(name0) && + isInvokeBasic(name2) && + name1.lastUseIndex(name0) == 3 && // t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n}); + lambdaForm.lastUseIndex(name0) == pos+1 && // t_{n} is local: used only in t_{n+1} + name2.lastUseIndex(name1) == 1 && // t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1}) + lambdaForm.lastUseIndex(name1) == pos+2; // t_{n+1} is local: used only in t_{n+2} } /** @@ -695,8 +752,6 @@ * }</pre></blockquote> */ private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { - MethodType type = selectAlternativeName.function.methodType(); - Name receiver = (Name) invokeBasicName.arguments[0]; Label L_fallback = new Label(); @@ -710,7 +765,6 @@ mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback); // invoke selectAlternativeName.arguments[1] - MethodHandle target = (MethodHandle) selectAlternativeName.arguments[1]; emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitInvoke(invokeBasicName); @@ -722,7 +776,6 @@ mv.visitLabel(L_fallback); // invoke selectAlternativeName.arguments[2] - MethodHandle fallback = (MethodHandle) selectAlternativeName.arguments[2]; emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitInvoke(invokeBasicName); @@ -731,6 +784,85 @@ mv.visitLabel(L_done); } + /** + * Emit bytecode for the guardWithCatch idiom. + * + * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithCatch): + * <blockquote><pre>{@code + * guardWithCatch=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{ + * t8:L=MethodHandle.invokeBasic(a4:L,a6:L,a7:L); + * t9:L=MethodHandleImpl.guardWithCatch(a1:L,a2:L,a3:L,t8:L); + * t10:I=MethodHandle.invokeBasic(a5:L,t9:L);t10:I} + * }</pre></blockquote> + * + * It is compiled into bytecode equivalent of the following code: + * <blockquote><pre>{@code + * try { + * return a1.invokeBasic(a6, a7); + * } catch (Throwable e) { + * if (!a2.isInstance(e)) throw e; + * return a3.invokeBasic(ex, a6, a7); + * }} + */ + private void emitGuardWithCatch(int pos) { + Name args = lambdaForm.names[pos]; + Name invoker = lambdaForm.names[pos+1]; + Name result = lambdaForm.names[pos+2]; + + Label L_startBlock = new Label(); + Label L_endBlock = new Label(); + Label L_handler = new Label(); + Label L_done = new Label(); + + Class<?> returnType = result.function.resolvedHandle.type().returnType(); + MethodType type = args.function.resolvedHandle.type() + .dropParameterTypes(0,1) + .changeReturnType(returnType); + + mv.visitTryCatchBlock(L_startBlock, L_endBlock, L_handler, "java/lang/Throwable"); + + // Normal case + mv.visitLabel(L_startBlock); + // load target + emitPushArgument(invoker, 0); + emitPushArguments(args, 1); // skip 1st argument: method handle + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false); + mv.visitLabel(L_endBlock); + mv.visitJumpInsn(Opcodes.GOTO, L_done); + + // Exceptional case + mv.visitLabel(L_handler); + + // Check exception's type + mv.visitInsn(Opcodes.DUP); + // load exception class + emitPushArgument(invoker, 1); + mv.visitInsn(Opcodes.SWAP); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "isInstance", "(Ljava/lang/Object;)Z", false); + Label L_rethrow = new Label(); + mv.visitJumpInsn(Opcodes.IFEQ, L_rethrow); + + // Invoke catcher + // load catcher + emitPushArgument(invoker, 2); + mv.visitInsn(Opcodes.SWAP); + emitPushArguments(args, 1); // skip 1st argument: method handle + MethodType catcherType = type.insertParameterTypes(0, Throwable.class); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", catcherType.basicType().toMethodDescriptorString(), false); + mv.visitJumpInsn(Opcodes.GOTO, L_done); + + mv.visitLabel(L_rethrow); + mv.visitInsn(Opcodes.ATHROW); + + mv.visitLabel(L_done); + } + + private void emitPushArguments(Name args, int start) { + for (int i = start; i < args.arguments.length; i++) { + emitPushArgument(args, i); + } + } + private void emitPushArgument(Name name, int paramIndex) { Object arg = name.arguments[paramIndex]; char ptype = name.function.parameterType(paramIndex);
--- a/src/share/classes/java/lang/invoke/LambdaForm.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/lang/invoke/LambdaForm.java Wed Apr 09 12:26:00 2014 -0700 @@ -1465,6 +1465,33 @@ return false; } + /** Return the index of the last occurrence of n in the argument array. + * Return -1 if the name is not used. + */ + int lastUseIndex(Name n) { + if (arguments == null) return -1; + for (int i = arguments.length; --i >= 0; ) { + if (arguments[i] == n) return i; + } + return -1; + } + + /** Return the number of occurrences of n in the argument array. + * Return 0 if the name is not used. + */ + int useCount(Name n) { + if (arguments == null) return 0; + int count = 0; + for (int i = arguments.length; --i >= 0; ) { + if (arguments[i] == n) ++count; + } + return count; + } + + boolean contains(Name n) { + return this == n || lastUseIndex(n) >= 0; + } + public boolean equals(Name that) { if (this == that) return true; if (isParam()) @@ -1488,6 +1515,35 @@ } } + /** Return the index of the last name which contains n as an argument. + * Return -1 if the name is not used. Return names.length if it is the return value. + */ + int lastUseIndex(Name n) { + int ni = n.index, nmax = names.length; + assert(names[ni] == n); + if (result == ni) return nmax; // live all the way beyond the end + for (int i = nmax; --i > ni; ) { + if (names[i].lastUseIndex(n) >= 0) + return i; + } + return -1; + } + + /** Return the number of times n is used as an argument or return value. */ + int useCount(Name n) { + int ni = n.index, nmax = names.length; + int end = lastUseIndex(n); + if (end < 0) return 0; + int count = 0; + if (end == nmax) { count++; end--; } + int beg = n.index() + 1; + if (beg < arity) beg = arity; + for (int i = beg; i <= end; i++) { + count += names[i].useCount(n); + } + return count; + } + static Name argument(int which, char type) { int tn = ALL_TYPES.indexOf(type); if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Apr 09 12:26:00 2014 -0700 @@ -27,7 +27,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import sun.invoke.empty.Empty; @@ -254,7 +253,7 @@ // Note: Do not check for a class hierarchy relation // between src and dst. In all cases a 'null' argument // will pass the cast conversion. - fn = ValueConversions.cast(dst); + fn = ValueConversions.cast(dst, Lazy.MH_castReference); } } Name conv = new Name(fn, names[INARG_BASE + i]); @@ -294,6 +293,25 @@ return SimpleMethodHandle.make(srcType, form); } + /** + * Identity function, with reference cast. + * @param t an arbitrary reference type + * @param x an arbitrary reference value + * @return the same value x + */ + @ForceInline + @SuppressWarnings("unchecked") + static <T,U> T castReference(Class<? extends T> t, U x) { + // inlined Class.cast because we can't ForceInline it + if (x != null && !t.isInstance(x)) + throw newClassCastException(t, x); + return (T) x; + } + + private static ClassCastException newClassCastException(Class<?> t, Object obj) { + return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); + } + static MethodHandle makeReferenceIdentity(Class<?> refType) { MethodType lambdaType = MethodType.genericMethodType(1).invokerType(); Name[] names = arguments(1, lambdaType); @@ -482,12 +500,31 @@ * Factored in an inner class to delay initialization until first usage. */ private static class Lazy { + private static final Class<?> MHI = MethodHandleImpl.class; + static final NamedFunction NF_checkSpreadArgument; + static final NamedFunction NF_guardWithCatch; + static final NamedFunction NF_selectAlternative; + static final NamedFunction NF_throwException; + + static final MethodHandle MH_castReference; + static { try { - NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class - .getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); + NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); + NF_guardWithCatch = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class, + MethodHandle.class, Object[].class)); + NF_selectAlternative = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class, + MethodHandle.class)); + NF_throwException = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class)); + NF_checkSpreadArgument.resolve(); + NF_guardWithCatch.resolve(); + NF_selectAlternative.resolve(); + NF_throwException.resolve(); + + MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class); + MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } @@ -548,24 +585,12 @@ return SimpleMethodHandle.make(srcType, form); } + @LambdaForm.Hidden static MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) { return testResult ? target : fallback; } - static MethodHandle SELECT_ALTERNATIVE; - static MethodHandle selectAlternative() { - if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE; - try { - SELECT_ALTERNATIVE - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative", - MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - return SELECT_ALTERNATIVE; - } - static MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle target, @@ -585,7 +610,7 @@ // call selectAlternative Object[] selectArgs = { names[arity + 1], target, fallback }; - names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs); + names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs); targetArgs[0] = names[arity + 2]; // call target or fallback @@ -595,167 +620,138 @@ return SimpleMethodHandle.make(target.type(), form); } - private static class GuardWithCatch { - private final MethodHandle target; - private final Class<? extends Throwable> exType; - private final MethodHandle catcher; - // FIXME: Build the control flow out of foldArguments. - GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { - this.target = target; - this.exType = exType; - this.catcher = catcher; - } - @LambdaForm.Hidden - private Object invoke_V(Object... av) throws Throwable { - try { - return target.invokeExact(av); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, av); - } - } - @LambdaForm.Hidden - private Object invoke_L0() throws Throwable { - try { - return target.invokeExact(); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t); - } - } - @LambdaForm.Hidden - private Object invoke_L1(Object a0) throws Throwable { - try { - return target.invokeExact(a0); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0); - } - } - @LambdaForm.Hidden - private Object invoke_L2(Object a0, Object a1) throws Throwable { - try { - return target.invokeExact(a0, a1); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1); - } - } - @LambdaForm.Hidden - private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { - try { - return target.invokeExact(a0, a1, a2); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2); - } - } - @LambdaForm.Hidden - private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3); - } + /** + * The LambaForm shape for catchException combinator is the following: + * <blockquote><pre>{@code + * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{ + * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L); + * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L); + * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L); + * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L); + * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L); + * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L); + * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L); + * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I} + * }</pre></blockquote> + * + * argL0 and argL2 are target and catcher method handles. argL1 is exception class. + * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[] + * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()). + * + * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms + * among catchException combinators with the same basic type. + */ + private static LambdaForm makeGuardWithCatchForm(MethodType basicType) { + MethodType lambdaType = basicType.invokerType(); + + LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC); + if (lform != null) { + return lform; } - @LambdaForm.Hidden - private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4); - } - } - @LambdaForm.Hidden - private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5); - } - } - @LambdaForm.Hidden - private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6); - } - } - @LambdaForm.Hidden - private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { - try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); - } catch (Throwable t) { - if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); - } - } - static MethodHandle[] makeInvokes() { - ArrayList<MethodHandle> invokes = new ArrayList<>(); - MethodHandles.Lookup lookup = IMPL_LOOKUP; - for (;;) { - int nargs = invokes.size(); - String name = "invoke_L"+nargs; - MethodHandle invoke = null; - try { - invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); - } catch (ReflectiveOperationException ex) { - } - if (invoke == null) break; - invokes.add(invoke); - } - assert(invokes.size() == 9); // current number of methods - return invokes.toArray(new MethodHandle[0]); - }; - static final MethodHandle[] INVOKES = makeInvokes(); - // For testing use this: - //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); - static final MethodHandle VARARGS_INVOKE; - static { - try { - VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); - } catch (ReflectiveOperationException ex) { - throw uncaughtException(ex); - } - } + final int THIS_MH = 0; // the BMH_LLLLL + final int ARG_BASE = 1; // start of incoming arguments + final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); + + int nameCursor = ARG_LIMIT; + final int GET_TARGET = nameCursor++; + final int GET_CLASS = nameCursor++; + final int GET_CATCHER = nameCursor++; + final int GET_COLLECT_ARGS = nameCursor++; + final int GET_UNBOX_RESULT = nameCursor++; + final int BOXED_ARGS = nameCursor++; + final int TRY_CATCH = nameCursor++; + final int UNBOX_RESULT = nameCursor++; + + Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); + names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]); + names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]); + names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]); + names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]); + names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]); + + // FIXME: rework argument boxing/result unboxing logic for LF interpretation + + // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...); + MethodType collectArgsType = basicType.changeReturnType(Object.class); + MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType); + Object[] args = new Object[invokeBasic.type().parameterCount()]; + args[0] = names[GET_COLLECT_ARGS]; + System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE); + names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args); + + // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L); + Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]}; + names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs); + + // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); + MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); + Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]}; + names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs); + + lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names); + + basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform); + return lform; } - static MethodHandle makeGuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { MethodType type = target.type(); - MethodType ctype = catcher.type(); - int nargs = type.parameterCount(); - if (nargs < GuardWithCatch.INVOKES.length) { - MethodType gtype = type.generic(); - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); - // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0) - MethodHandle gtarget = makePairwiseConvert(target, gtype, 2); - MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2); - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null) throw new InternalError(); - MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard); - return makePairwiseConvert(ginvoker, type, 2); + LambdaForm form = makeGuardWithCatchForm(type.basicType()); + + // Prepare auxiliary method handles used during LambdaForm interpreation. + // Box arguments and wrap them into Object[]: ValueConversions.array(). + MethodType varargsType = type.changeReturnType(Object[].class); + MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount()) + .asType(varargsType); + // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). + MethodHandle unboxResult; + if (type.returnType().isPrimitive()) { + unboxResult = ValueConversions.unbox(type.returnType()); } else { - target = target.asType(type.changeReturnType(Object.class)); - MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs); - MethodType catcherType = ctype.changeParameterType(0, Throwable.class) - .changeReturnType(Object.class); - catcher = catcher.asType(catcherType); - MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs); - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null) throw new InternalError(); - MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard); - MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false); - return makePairwiseConvert(gcollect, type, 2); + unboxResult = ValueConversions.identity(); + } + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); + BoundMethodHandle mh; + try { + mh = (BoundMethodHandle) + data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher, + (Object) collectArgs, (Object) unboxResult); + } catch (Throwable ex) { + throw uncaughtException(ex); } + assert(mh.type() == type); + return mh; + } + + /** + * Intrinsified during LambdaForm compilation + * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}). + */ + @LambdaForm.Hidden + static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher, + Object... av) throws Throwable { + // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case. + try { + return target.asFixedArity().invokeWithArguments(av); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.asFixedArity().invokeWithArguments(prepend(t, av)); + } + } + + /** Prepend an element {@code elem} to an {@code array}. */ + @LambdaForm.Hidden + private static Object[] prepend(Object elem, Object[] array) { + Object[] newArray = new Object[array.length+1]; + newArray[0] = elem; + System.arraycopy(array, 0, newArray, 1, array.length); + return newArray; } static @@ -765,23 +761,9 @@ if (arity > 1) { return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1); } - return makePairwiseConvert(throwException(), type, 2); + return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2); } - static MethodHandle THROW_EXCEPTION; - static MethodHandle throwException() { - MethodHandle mh = THROW_EXCEPTION; - if (mh != null) return mh; - try { - mh - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", - MethodType.methodType(Empty.class, Throwable.class)); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - THROW_EXCEPTION = mh; - return mh; - } static <T extends Throwable> Empty throwException(T t) throws T { throw t; } static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
--- a/src/share/classes/java/lang/invoke/MethodTypeForm.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodTypeForm.java Wed Apr 09 12:26:00 2014 -0700 @@ -76,7 +76,8 @@ LF_GEN_INVOKER = 12, LF_CS_LINKER = 13, // linkToCallSite_CS LF_MH_LINKER = 14, // linkToCallSite_MH - LF_LIMIT = 15; + LF_GWC = 15, + LF_LIMIT = 16; public MethodType erasedType() { return erasedType;
--- a/src/share/classes/java/util/Arrays.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/util/Arrays.java Wed Apr 09 12:26:00 2014 -0700 @@ -28,6 +28,7 @@ import java.lang.reflect.Array; import java.util.concurrent.ForkJoinPool; import java.util.function.BinaryOperator; +import java.util.function.Consumer; import java.util.function.DoubleBinaryOperator; import java.util.function.IntBinaryOperator; import java.util.function.IntFunction; @@ -35,6 +36,7 @@ import java.util.function.IntToLongFunction; import java.util.function.IntUnaryOperator; import java.util.function.LongBinaryOperator; +import java.util.function.UnaryOperator; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; @@ -3848,12 +3850,13 @@ @Override public int indexOf(Object o) { - if (o==null) { - for (int i=0; i<a.length; i++) - if (a[i]==null) + E[] a = this.a; + if (o == null) { + for (int i = 0; i < a.length; i++) + if (a[i] == null) return i; } else { - for (int i=0; i<a.length; i++) + for (int i = 0; i < a.length; i++) if (o.equals(a[i])) return i; } @@ -3869,6 +3872,28 @@ public Spliterator<E> spliterator() { return Spliterators.spliterator(a, Spliterator.ORDERED); } + + @Override + public void forEach(Consumer<? super E> action) { + Objects.requireNonNull(action); + for (E e : a) { + action.accept(e); + } + } + + @Override + public void replaceAll(UnaryOperator<E> operator) { + Objects.requireNonNull(operator); + E[] a = this.a; + for (int i = 0; i < a.length; i++) { + a[i] = operator.apply(a[i]); + } + } + + @Override + public void sort(Comparator<? super E> c) { + Arrays.sort(a, c); + } } /**
--- a/src/share/classes/java/util/Spliterators.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/java/util/Spliterators.java Wed Apr 09 12:26:00 2014 -0700 @@ -384,7 +384,7 @@ */ private static void checkFromToBounds(int arrayLength, int origin, int fence) { if (origin > fence) { - throw new IllegalArgumentException( + throw new ArrayIndexOutOfBoundsException( "origin(" + origin + ") > fence(" + fence + ")"); } if (origin < 0) {
--- a/src/share/classes/javax/swing/JComboBox.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/javax/swing/JComboBox.java Wed Apr 09 12:26:00 2014 -0700 @@ -1416,6 +1416,28 @@ } /** + * {@inheritDoc} + */ + @Override + protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + if (super.processKeyBinding(ks, e, condition, pressed)) { + return true; + } + + if (!isEditable() || condition != WHEN_FOCUSED || getEditor() == null + || !Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor"))) { + return false; + } + + Component editorComponent = getEditor().getEditorComponent(); + if (editorComponent instanceof JComponent) { + JComponent component = (JComponent) editorComponent; + return component.processKeyBinding(ks, e, WHEN_FOCUSED, pressed); + } + return false; + } + + /** * Sets the object that translates a keyboard character into a list * selection. Typically, the first selection with a matching first * character becomes the selected item.
--- a/src/share/classes/javax/swing/text/html/EditableView.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/javax/swing/text/html/EditableView.java Wed Apr 09 12:26:00 2014 -0700 @@ -73,7 +73,7 @@ Component c = getComponent(); Container host = getContainer(); - if (host != null && + if (host instanceof JTextComponent && isVisible != ((JTextComponent)host).isEditable()) { isVisible = ((JTextComponent)host).isEditable(); preferenceChanged(null, true, true);
--- a/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java Wed Apr 09 12:26:00 2014 -0700 @@ -259,41 +259,68 @@ if (c >= '\001' && c <= '\177') { data[len++] = (byte) c; } else { - int byteLength = i; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - byteLength++; - } else if (c > '\u07FF') { - byteLength += 3; - } else { - byteLength += 2; - } - } - if (byteLength > 65535) { - throw new IllegalArgumentException(); - } - data[length] = (byte) (byteLength >>> 8); - data[length + 1] = (byte) byteLength; - if (length + 2 + byteLength > data.length) { - length = len; - enlarge(2 + byteLength); - data = this.data; - } - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else if (c > '\u07FF') { - data[len++] = (byte) (0xE0 | c >> 12 & 0xF); - data[len++] = (byte) (0x80 | c >> 6 & 0x3F); - data[len++] = (byte) (0x80 | c & 0x3F); - } else { - data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); - data[len++] = (byte) (0x80 | c & 0x3F); - } - } - break; + length = len; + return encodeUTF8(s, i, 65535); + } + } + length = len; + return this; + } + + /** + * Puts an UTF8 string into this byte vector. The byte vector is + * automatically enlarged if necessary. The string length is encoded in two + * bytes before the encoded characters, if there is space for that (i.e. if + * this.length - i - 2 >= 0). + * + * @param s + * the String to encode. + * @param i + * the index of the first character to encode. The previous + * characters are supposed to have already been encoded, using + * only one byte per character. + * @param maxByteLength + * the maximum byte length of the encoded string, including the + * already encoded characters. + * @return this byte vector. + */ + ByteVector encodeUTF8(final String s, int i, int maxByteLength) { + int charLength = s.length(); + int byteLength = i; + char c; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + byteLength++; + } else if (c > '\u07FF') { + byteLength += 3; + } else { + byteLength += 2; + } + } + if (byteLength > maxByteLength) { + throw new IllegalArgumentException(); + } + int start = length - i - 2; + if (start >= 0) { + data[start] = (byte) (byteLength >>> 8); + data[start + 1] = (byte) byteLength; + } + if (length + byteLength - i > data.length) { + enlarge(byteLength - i); + } + int len = length; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else if (c > '\u07FF') { + data[len++] = (byte) (0xE0 | c >> 12 & 0xF); + data[len++] = (byte) (0x80 | c >> 6 & 0x3F); + data[len++] = (byte) (0x80 | c & 0x3F); + } else { + data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); + data[len++] = (byte) (0x80 | c & 0x3F); } } length = len;
--- a/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Wed Apr 09 12:26:00 2014 -0700 @@ -716,7 +716,8 @@ sourceFile = newUTF8(file); } if (debug != null) { - sourceDebug = new ByteVector().putUTF8(debug); + sourceDebug = new ByteVector().encodeUTF8(debug, 0, + Integer.MAX_VALUE); } } @@ -857,7 +858,7 @@ } if (sourceDebug != null) { ++attributeCount; - size += sourceDebug.length + 4; + size += sourceDebug.length + 6; newUTF8("SourceDebugExtension"); } if (enclosingMethodOwner != 0) { @@ -946,9 +947,9 @@ out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); } if (sourceDebug != null) { - int len = sourceDebug.length - 2; + int len = sourceDebug.length; out.putShort(newUTF8("SourceDebugExtension")).putInt(len); - out.putByteArray(sourceDebug.data, 2, len); + out.putByteArray(sourceDebug.data, 0, len); } if (enclosingMethodOwner != 0) { out.putShort(newUTF8("EnclosingMethod")).putInt(4);
--- a/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java Wed Apr 09 12:26:00 2014 -0700 @@ -99,8 +99,8 @@ * stack types. VALUE depends on KIND. For LOCAL types, it is an index in * the input local variable types. For STACK types, it is a position * relatively to the top of input frame stack. For BASE types, it is either - * one of the constants defined in FrameVisitor, or for OBJECT and - * UNINITIALIZED types, a tag and an index in the type table. + * one of the constants defined below, or for OBJECT and UNINITIALIZED + * types, a tag and an index in the type table. * * Output frames can contain types of any kind and with a positive or * negative dimension (and even unassigned types, represented by 0 - which @@ -537,7 +537,7 @@ /** * The types that are initialized in the basic block. A constructor * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace - * <i>every occurrence</i> of this type in the local variables and in the + * <i>every occurence</i> of this type in the local variables and in the * operand stack. This cannot be done during the first phase of the * algorithm since, during this phase, the local variables and the operand * stack are not completely computed. It is therefore necessary to store the @@ -1446,6 +1446,7 @@ // if t is the NULL type, merge(u,t)=u, so there is no change return false; } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { + // if t and u have the same dimension and same base kind if ((u & BASE_KIND) == OBJECT) { // if t is also a reference type, and if u and t have the // same dimension merge(u,t) = dim(t) | common parent of the @@ -1458,9 +1459,13 @@ v = OBJECT | cw.addType("java/lang/Object"); } } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { - // if t is any other reference or array type, - // merge(u,t)=java/lang/Object - v = OBJECT | cw.addType("java/lang/Object"); + // if t is any other reference or array type, the merged type + // is Object, or min(dim(u), dim(t)) | java/lang/Object is u + // and t have different array dimensions + int tdim = t & DIM; + int udim = u & DIM; + v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT + | cw.addType("java/lang/Object"); } else { // if t is any other type, merge(u,t)=TOP v = TOP;
--- a/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java Wed Apr 09 12:26:00 2014 -0700 @@ -240,6 +240,7 @@ locals.add(types[i].getInternalName()); } } + maxLocals = locals.size(); } @Override @@ -519,12 +520,12 @@ // ------------------------------------------------------------------------ private Object get(final int local) { - maxLocals = Math.max(maxLocals, local); + maxLocals = Math.max(maxLocals, local + 1); return local < locals.size() ? locals.get(local) : Opcodes.TOP; } private void set(final int local, final Object type) { - maxLocals = Math.max(maxLocals, local); + maxLocals = Math.max(maxLocals, local + 1); while (local >= locals.size()) { locals.add(Opcodes.TOP); }
--- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java Wed Apr 09 12:26:00 2014 -0700 @@ -556,6 +556,8 @@ AbstractInsnNode prev; + AbstractInsnNode remove; + InsnListIterator(int index) { if (index == size()) { next = null; @@ -577,12 +579,22 @@ AbstractInsnNode result = next; prev = result; next = result.next; + remove = result; return result; } public void remove() { - InsnList.this.remove(prev); - prev = prev.prev; + if (remove != null) { + if (remove == next) { + next = next.next; + } else { + prev = prev.prev; + } + InsnList.this.remove(remove); + remove = null; + } else { + throw new IllegalStateException(); + } } public boolean hasPrevious() { @@ -593,6 +605,7 @@ AbstractInsnNode result = prev; next = result; prev = result.prev; + remove = result; return result; } @@ -619,6 +632,7 @@ public void add(Object o) { InsnList.this.insertBefore(next, (AbstractInsnNode) o); prev = (AbstractInsnNode) o; + remove = null; } public void set(Object o) {
--- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java Wed Apr 09 12:26:00 2014 -0700 @@ -404,7 +404,7 @@ * instruction of the method. The size of the returned array is * equal to the number of instructions (and labels) of the method. A * given frame is <tt>null</tt> if the corresponding instruction - * cannot be reached, or if an error occurred during the analysis of + * cannot be reached, or if an error occured during the analysis of * the method. */ public Frame<V>[] getFrames() {
--- a/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java Wed Apr 09 12:26:00 2014 -0700 @@ -111,7 +111,7 @@ * the bytecode instruction to be interpreted. * @return the result of the interpretation of the given instruction. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException; @@ -130,7 +130,7 @@ * @return the result of the interpretation of the given instruction. The * returned value must be <tt>equal</tt> to the given value. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException; @@ -151,7 +151,7 @@ * the argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException; @@ -175,7 +175,7 @@ * the second argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) throws AnalyzerException; @@ -196,7 +196,7 @@ * the third argument of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3) throws AnalyzerException; @@ -214,7 +214,7 @@ * the arguments of the instruction to be interpreted. * @return the result of the interpretation of the given instruction. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract V naryOperation(AbstractInsnNode insn, List<? extends V> values) throws AnalyzerException; @@ -232,7 +232,7 @@ * @param expected * the expected return type of the analyzed method. * @throws AnalyzerException - * if an error occurred during the interpretation. + * if an error occured during the interpretation. */ public abstract void returnOperation(AbstractInsnNode insn, V value, V expected) throws AnalyzerException;
--- a/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java Wed Apr 09 12:26:00 2014 -0700 @@ -99,7 +99,7 @@ } if (value instanceof Type) { int sort = ((Type) value).getSort(); - if (sort != Type.OBJECT && sort != Type.ARRAY) { + if (sort == Type.METHOD) { throw new IllegalArgumentException("Invalid annotation value"); } }
--- a/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java Wed Apr 09 12:26:00 2014 -0700 @@ -166,6 +166,11 @@ */ protected Map<Label, String> labelNames; + /** + * Class access flags + */ + private int access; + private int valueNumber = 0; /** @@ -245,6 +250,7 @@ public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { + this.access = access; int major = version & 0xFFFF; int minor = version >>> 16; buf.setLength(0); @@ -447,6 +453,11 @@ if ((access & Opcodes.ACC_BRIDGE) != 0) { buf.append("bridge "); } + if ((this.access & Opcodes.ACC_INTERFACE) != 0 + && (access & Opcodes.ACC_ABSTRACT) == 0 + && (access & Opcodes.ACC_STATIC) == 0) { + buf.append("default "); + } buf.append(name); appendDescriptor(METHOD_DESCRIPTOR, desc); @@ -856,7 +867,6 @@ appendDescriptor(INTERNAL_NAME, owner); buf.append('.').append(name).append(' '); appendDescriptor(METHOD_DESCRIPTOR, desc); - buf.append(' ').append(itf ? "itf" : ""); buf.append('\n'); text.add(buf.toString()); } @@ -869,26 +879,35 @@ buf.append(name); appendDescriptor(METHOD_DESCRIPTOR, desc); buf.append(" ["); + buf.append('\n'); + buf.append(tab3); appendHandle(bsm); + buf.append('\n'); buf.append(tab3).append("// arguments:"); if (bsmArgs.length == 0) { buf.append(" none"); } else { - buf.append('\n').append(tab3); + buf.append('\n'); for (int i = 0; i < bsmArgs.length; i++) { + buf.append(tab3); Object cst = bsmArgs[i]; if (cst instanceof String) { Printer.appendString(buf, (String) cst); } else if (cst instanceof Type) { - buf.append(((Type) cst).getDescriptor()).append(".class"); + Type type = (Type) cst; + if(type.getSort() == Type.METHOD){ + appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor()); + } else { + buf.append(type.getDescriptor()).append(".class"); + } } else if (cst instanceof Handle) { appendHandle((Handle) cst); } else { buf.append(cst); } - buf.append(", "); + buf.append(", \n"); } - buf.setLength(buf.length() - 2); + buf.setLength(buf.length() - 3); } buf.append('\n'); buf.append(tab2).append("]\n"); @@ -1234,10 +1253,10 @@ * a handle, non null. */ protected void appendHandle(final Handle h) { - buf.append('\n').append(tab3); int tag = h.getTag(); buf.append("// handle kind 0x").append(Integer.toHexString(tag)) .append(" : "); + boolean isMethodHandle = false; switch (tag) { case Opcodes.H_GETFIELD: buf.append("GETFIELD"); @@ -1253,18 +1272,23 @@ break; case Opcodes.H_INVOKEINTERFACE: buf.append("INVOKEINTERFACE"); + isMethodHandle = true; break; case Opcodes.H_INVOKESPECIAL: buf.append("INVOKESPECIAL"); + isMethodHandle = true; break; case Opcodes.H_INVOKESTATIC: buf.append("INVOKESTATIC"); + isMethodHandle = true; break; case Opcodes.H_INVOKEVIRTUAL: buf.append("INVOKEVIRTUAL"); + isMethodHandle = true; break; case Opcodes.H_NEWINVOKESPECIAL: buf.append("NEWINVOKESPECIAL"); + isMethodHandle = true; break; } buf.append('\n'); @@ -1272,9 +1296,13 @@ appendDescriptor(INTERNAL_NAME, h.getOwner()); buf.append('.'); buf.append(h.getName()); - buf.append('('); + if(!isMethodHandle){ + buf.append('('); + } appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc()); - buf.append(')').append('\n'); + if(!isMethodHandle){ + buf.append(')'); + } } /**
--- a/src/share/classes/jdk/internal/org/objectweb/asm/version.txt Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/jdk/internal/org/objectweb/asm/version.txt Wed Apr 09 12:26:00 2014 -0700 @@ -1,12 +1,12 @@ Path: . -Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/ASM_5_0_BETA -URL: svn://svn.forge.objectweb.org/svnroot/asm/trunk/asm -Repository Root: svn://svn.forge.objectweb.org/svnroot/asm +Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/asm-svn-2014-03-12 +URL: file:///svnroot/asm/trunk/asm +Repository Root: file:///svnroot/asm Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 -Revision: 1700 +Revision: 1721 Node Kind: directory Schedule: normal Last Changed Author: ebruneton -Last Changed Rev: 1700 -Last Changed Date: 2013-10-29 20:22:52 +0100 (Tue, 29 Oct 2013) +Last Changed Rev: 1721 +Last Changed Date: 2014-03-02 17:25:35 +0100 (Sun, 02 Mar 2014)
--- a/src/share/classes/sun/awt/AppContext.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/awt/AppContext.java Wed Apr 09 12:26:00 2014 -0700 @@ -42,11 +42,13 @@ import java.util.HashSet; import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeListener; +import java.lang.ref.SoftReference; import sun.util.logging.PlatformLogger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; /** * The AppContext is a table referenced by ThreadGroup which stores @@ -883,6 +885,23 @@ }); } + + public static <T> T getSoftReferenceValue(Object key, + Supplier<T> supplier) { + + final AppContext appContext = AppContext.getAppContext(); + SoftReference<T> ref = (SoftReference<T>) appContext.get(key); + if (ref != null) { + final T object = ref.get(); + if (object != null) { + return object; + } + } + final T object = supplier.get(); + ref = new SoftReference<>(object); + appContext.put(key, ref); + return object; + } } final class MostRecentKeyValue {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/awt/image/ImageCache.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt.image; + +import java.awt.*; +import java.lang.ref.*; +import java.util.*; +import java.util.concurrent.locks.*; +import sun.awt.AppContext; + +/** + * ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary + * set of arguments. All images are held with SoftReferences so they will be + * dropped by the GC if heap memory gets tight. When our size hits max pixel + * count least recently requested images are removed first. + * + * The ImageCache must be used from the thread with an AppContext only. + * + */ +final public class ImageCache { + + // Ordered Map keyed by args hash, ordered by most recent accessed entry. + private final LinkedHashMap<PixelsKey, ImageSoftReference> map + = new LinkedHashMap<>(16, 0.75f, true); + + // Maximum number of pixels to cache, this is used if maxCount + private final int maxPixelCount; + // The current number of pixels stored in the cache + private int currentPixelCount = 0; + + // Lock for concurrent access to map + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + // Reference queue for tracking lost softreferences to images in the cache + private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>(); + + public static ImageCache getInstance() { + return AppContext.getSoftReferenceValue(ImageCache.class, + () -> new ImageCache()); + } + + ImageCache(final int maxPixelCount) { + this.maxPixelCount = maxPixelCount; + } + + ImageCache() { + this((8 * 1024 * 1024) / 4); // 8Mb of pixels + } + + public void flush() { + lock.writeLock().lock(); + try { + map.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + public Image getImage(final PixelsKey key){ + final ImageSoftReference ref; + lock.readLock().lock(); + try { + ref = map.get(key); + } finally { + lock.readLock().unlock(); + } + return ref == null ? null : ref.get(); + } + + /** + * Sets the cached image for the specified constraints. + * + * @param key The key with which the specified image is to be associated + * @param image The image to store in cache + */ + public void setImage(final PixelsKey key, final Image image) { + + lock.writeLock().lock(); + try { + ImageSoftReference ref = map.get(key); + + // check if currently in map + if (ref != null) { + if (ref.get() != null) { + return; + } + // soft image has been removed + currentPixelCount -= key.getPixelCount(); + map.remove(key); + }; + + + // add new image to pixel count + final int newPixelCount = key.getPixelCount(); + currentPixelCount += newPixelCount; + // clean out lost references if not enough space + if (currentPixelCount > maxPixelCount) { + while ((ref = (ImageSoftReference)referenceQueue.poll()) != null) { + //reference lost + map.remove(ref.key); + currentPixelCount -= ref.key.getPixelCount(); + } + } + + // remove old items till there is enough free space + if (currentPixelCount > maxPixelCount) { + final Iterator<Map.Entry<PixelsKey, ImageSoftReference>> + mapIter = map.entrySet().iterator(); + while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) { + final Map.Entry<PixelsKey, ImageSoftReference> entry = + mapIter.next(); + mapIter.remove(); + final Image img = entry.getValue().get(); + if (img != null) img.flush(); + currentPixelCount -= entry.getValue().key.getPixelCount(); + } + } + + // finally put new in map + map.put(key, new ImageSoftReference(key, image, referenceQueue)); + } finally { + lock.writeLock().unlock(); + } + } + + public interface PixelsKey { + + int getPixelCount(); + } + + private static class ImageSoftReference extends SoftReference<Image> { + + final PixelsKey key; + + ImageSoftReference(final PixelsKey key, final Image referent, + final ReferenceQueue<? super Image> q) { + super(referent, q); + this.key = key; + } + } +}
--- a/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java Wed Apr 09 12:26:00 2014 -0700 @@ -26,46 +26,152 @@ import java.awt.Image; import java.awt.Graphics; +import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; import java.util.Arrays; import java.util.List; import java.util.function.Function; +import java.util.function.BiFunction; +import java.util.stream.Collectors; public class MultiResolutionBufferedImage extends BufferedImage implements MultiResolutionImage { - Image[] resolutionVariants; - int baseIndex; + private final BiFunction<Integer, Integer, Image> mapper; + private final Dimension2D[] sizes; + private int availableInfo; - public MultiResolutionBufferedImage(int imageType, int baseIndex, Image... images) { - super(images[baseIndex].getWidth(null), images[baseIndex].getHeight(null), - imageType); - this.baseIndex = baseIndex; - this.resolutionVariants = images; + public MultiResolutionBufferedImage(Image baseImage, + Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) { + super(baseImage.getWidth(null), baseImage.getHeight(null), + BufferedImage.TYPE_INT_ARGB_PRE); + this.sizes = sizes; + this.mapper = mapper; + this.availableInfo = getInfo(baseImage); Graphics g = getGraphics(); - g.drawImage(images[baseIndex], 0, 0, null); + g.drawImage(baseImage, 0, 0, null); g.dispose(); - images[baseIndex] = this; } @Override public Image getResolutionVariant(int width, int height) { - for (Image image : resolutionVariants) { - if (width <= image.getWidth(null) && height <= image.getHeight(null)) { - return image; - } + int baseWidth = getWidth(); + int baseHeight = getHeight(); + + if (baseWidth == width && baseHeight == height) { + return this; } - return this; + + ImageCache cache = ImageCache.getInstance(); + ImageCacheKey key = new ImageCacheKey(this, width, height); + Image resolutionVariant = cache.getImage(key); + if (resolutionVariant == null) { + resolutionVariant = mapper.apply(width, height); + cache.setImage(key, resolutionVariant); + preload(resolutionVariant, availableInfo); + } + + return resolutionVariant; } @Override public List<Image> getResolutionVariants() { - return Arrays.asList(resolutionVariants); + return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size + -> getResolutionVariant((int) size.getWidth(), + (int) size.getHeight())).collect(Collectors.toList()); } public MultiResolutionBufferedImage map(Function<Image, Image> mapper) { - return new MultiResolutionBufferedImage(getType(), baseIndex, - Arrays.stream(resolutionVariants).map(mapper) - .toArray(length -> new Image[length])); + return new MultiResolutionBufferedImage(mapper.apply(this), sizes, + (width, height) -> + mapper.apply(getResolutionVariant(width, height))); + } + + @Override + public int getWidth(ImageObserver observer) { + availableInfo |= ImageObserver.WIDTH; + return super.getWidth(observer); + } + + @Override + public int getHeight(ImageObserver observer) { + availableInfo |= ImageObserver.HEIGHT; + return super.getHeight(observer); + } + + @Override + public Object getProperty(String name, ImageObserver observer) { + availableInfo |= ImageObserver.PROPERTIES; + return super.getProperty(name, observer); + } + + private static int getInfo(Image image) { + if (image instanceof ToolkitImage) { + return ((ToolkitImage) image).getImageRep().check( + (img, infoflags, x, y, w, h) -> false); + } + return 0; + } + + private static void preload(Image image, int availableInfo) { + if (image instanceof ToolkitImage) { + ((ToolkitImage) image).preload(new ImageObserver() { + int flags = availableInfo; + + @Override + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + flags &= ~infoflags; + return (flags != 0) && ((infoflags + & (ImageObserver.ERROR | ImageObserver.ABORT)) == 0); + } + }); + } } -} + + private static class ImageCacheKey implements ImageCache.PixelsKey { + + private final int pixelCount; + private final int hash; + + private final int w; + private final int h; + private final Image baseImage; + + ImageCacheKey(final Image baseImage, + final int w, final int h) { + this.baseImage = baseImage; + this.w = w; + this.h = h; + this.pixelCount = w * h; + hash = hash(); + } + + @Override + public int getPixelCount() { + return pixelCount; + } + + private int hash() { + int hash = baseImage.hashCode(); + hash = 31 * hash + w; + hash = 31 * hash + h; + return hash; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ImageCacheKey) { + ImageCacheKey key = (ImageCacheKey) obj; + return baseImage == key.baseImage && w == key.w && h == key.h; + } + return false; + } + } +} \ No newline at end of file
--- a/src/share/classes/sun/invoke/util/ValueConversions.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/invoke/util/ValueConversions.java Wed Apr 09 12:26:00 2014 -0700 @@ -443,20 +443,6 @@ return x; } - /** - * Identity function, with reference cast. - * @param t an arbitrary reference type - * @param x an arbitrary reference value - * @return the same value x - */ - @SuppressWarnings("unchecked") - static <T,U> T castReference(Class<? extends T> t, U x) { - // inlined Class.cast because we can't ForceInline it - if (x != null && !t.isInstance(x)) - throw newClassCastException(t, x); - return (T) x; - } - private static ClassCastException newClassCastException(Class<?> t, Object obj) { return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); } @@ -466,12 +452,10 @@ static { try { MethodType idType = MethodType.genericMethodType(1); - MethodType castType = idType.insertParameterTypes(0, Class.class); MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); - //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); - CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType); + CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); @@ -509,6 +493,9 @@ * and returns it as the given type. */ public static MethodHandle cast(Class<?> type) { + return cast(type, CAST_REFERENCE); + } + public static MethodHandle cast(Class<?> type, MethodHandle castReference) { if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); MethodHandle mh; Wrapper wrap = null; @@ -519,7 +506,7 @@ mh = cache.get(wrap); if (mh != null) return mh; } - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); + mh = MethodHandles.insertArguments(castReference, 0, type); if (cache != null) cache.put(wrap, mh); return mh;
--- a/src/share/classes/sun/java2d/SunGraphics2D.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/java2d/SunGraphics2D.java Wed Apr 09 12:26:00 2014 -0700 @@ -2430,6 +2430,8 @@ surfaceData = NullSurfaceData.theInstance; } + invalidatePipe(); + // this will recalculate the composite clip setDevClip(surfaceData.getBounds());
--- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.Base64; import java.util.HashMap; import sun.net.www.HeaderParser; +import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; @@ -44,6 +45,7 @@ class NegotiateAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; + private static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); final private HttpCallerInfo hci; @@ -79,6 +81,31 @@ } /** + * Find out if the HttpCallerInfo supports Negotiate protocol. + * @return true if supported + */ + public static boolean isSupported(HttpCallerInfo hci) { + ClassLoader loader = null; + try { + loader = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException se) { + if (logger.isLoggable(PlatformLogger.Level.FINER)) { + logger.finer("NegotiateAuthentication: " + + "Attempt to get the context class loader failed - " + se); + } + } + + if (loader != null) { + // Lock on the class loader instance to avoid the deadlock engaging + // the lock in "ClassLoader.loadClass(String, boolean)" method. + synchronized (loader) { + return isSupportedImpl(hci); + } + } + return isSupportedImpl(hci); + } + + /** * Find out if the HttpCallerInfo supports Negotiate protocol. In order to * find out yes or no, an initialization of a Negotiator object against it * is tried. The generated object will be cached under the name of ths @@ -89,7 +116,7 @@ * * @return true if supported */ - synchronized public static boolean isSupported(HttpCallerInfo hci) { + private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) { if (supported == null) { supported = new HashMap <String, Boolean>(); cache = new HashMap <String, Negotiator>();
--- a/src/share/classes/sun/security/krb5/Config.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/security/krb5/Config.java Wed Apr 09 12:26:00 2014 -0700 @@ -549,12 +549,11 @@ previous = line.substring(1).trim(); } } else { - if (previous == null) { - throw new KrbException( - "Config file must starts with a section"); + // Lines before the first section are ignored + if (previous != null) { + v.add(previous); + previous = line; } - v.add(previous); - previous = line; } } if (previous != null) {
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Wed Apr 09 12:26:00 2014 -0700 @@ -94,9 +94,6 @@ X509Certificate firstCert = certList.get(0); // check trusted certificate's subject selector.setSubject(firstCert.getIssuerX500Principal()); - // check the validity period - selector.setValidityPeriod(firstCert.getNotBefore(), - firstCert.getNotAfter()); /* * Facilitate certification path construction with authority * key identifier and subject key identifier.
--- a/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,29 +34,9 @@ /** * The reasonCode is a non-critical CRL entry extension that identifies - * the reason for the certificate revocation. CAs are strongly - * encouraged to include reason codes in CRL entries; however, the - * reason code CRL entry extension should be absent instead of using the - * unspecified (0) reasonCode value. - * <p>The ASN.1 syntax for this is: - * <pre> - * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } - * - * -- reasonCode ::= { CRLReason } - * - * CRLReason ::= ENUMERATED { - * unspecified (0), - * keyCompromise (1), - * cACompromise (2), - * affiliationChanged (3), - * superseded (4), - * cessationOfOperation (5), - * certificateHold (6), - * removeFromCRL (8), - * privilegeWithdrawn (9), - * aACompromise (10) } - * </pre> + * the reason for the certificate revocation. * @author Hemma Prafullchandra + * @see java.security.cert.CRLReason * @see Extension * @see CertAttrSet */ @@ -64,23 +44,11 @@ implements CertAttrSet<String> { /** - * Attribute name and Reason codes + * Attribute name */ public static final String NAME = "CRLReasonCode"; public static final String REASON = "reason"; - public static final int UNSPECIFIED = 0; - public static final int KEY_COMPROMISE = 1; - public static final int CA_COMPROMISE = 2; - public static final int AFFLIATION_CHANGED = 3; - public static final int SUPERSEDED = 4; - public static final int CESSATION_OF_OPERATION = 5; - public static final int CERTIFICATE_HOLD = 6; - // note 7 missing in syntax - public static final int REMOVE_FROM_CRL = 8; - public static final int PRIVILEGE_WITHDRAWN = 9; - public static final int AA_COMPROMISE = 10; - private static CRLReason[] values = CRLReason.values(); private int reasonCode = 0; @@ -181,7 +149,7 @@ * Returns a printable representation of the Reason code. */ public String toString() { - return super.toString() + " Reason Code: " + values[reasonCode]; + return super.toString() + " Reason Code: " + getReasonCode(); } /**
--- a/src/share/classes/sun/text/resources/es/FormatData_es_CL.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/text/resources/es/FormatData_es_CL.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,10 +57,10 @@ }, { "TimePatterns", new String[] { - "hh:mm:ss a z", // full time pattern - "hh:mm:ss a z", // long time pattern - "hh:mm:ss a", // medium time pattern - "hh:mm a", // short time pattern + "HH:mm:ss zzzz", // full time pattern + "H:mm:ss z", // long time pattern + "H:mm:ss", // medium time pattern + "H:mm", // short time pattern } }, { "DatePatterns",
--- a/src/share/classes/sun/text/resources/es/FormatData_es_EC.java Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/classes/sun/text/resources/es/FormatData_es_EC.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,10 +72,10 @@ }, { "TimePatterns", new String[] { - "hh:mm:ss a z", // full time pattern - "hh:mm:ss a z", // long time pattern - "hh:mm:ss a", // medium time pattern - "hh:mm a", // short time pattern + "HH:mm:ss zzzz", // full time pattern + "H:mm:ss z", // long time pattern + "H:mm:ss", // medium time pattern + "H:mm", // short time pattern } }, { "DatePatterns",
--- a/src/share/native/sun/font/FontInstanceAdapter.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/native/sun/font/FontInstanceAdapter.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -222,10 +222,16 @@ jobject pt = env->NewObject(sunFontIDs.pt2DFloatClass, sunFontIDs.pt2DFloatCtr, adjustment.fX, adjustment.fY); + if (pt == NULL) { + env->ExceptionClear(); + adjustment.fX = 0.0f; + adjustment.fY = 0.0f; + } else { env->CallObjectMethod(fontStrike, sunFontIDs.adjustPointMID, pt); adjustment.fX = env->GetFloatField(pt, sunFontIDs.xFID); adjustment.fY = env->GetFloatField(pt, sunFontIDs.yFID); } +} void FontInstanceAdapter::getWideGlyphAdvance(le_uint32 glyph, LEPoint &advance) const {
--- a/src/share/native/sun/font/layout/SunLayoutEngine.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/native/sun/font/layout/SunLayoutEngine.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -56,50 +56,13 @@ JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_initGVIDs (JNIEnv *env, jclass cls) { - gvdClass = env->FindClass(gvdClassName); - if (!gvdClass) { - JNU_ThrowClassNotFoundException(env, gvdClassName); - return; - } - gvdClass = (jclass)env->NewGlobalRef(gvdClass); - if (!gvdClass) { - JNU_ThrowInternalError(env, "could not create global ref"); - return; - } - gvdCountFID = env->GetFieldID(gvdClass, "_count", "I"); - if (!gvdCountFID) { - gvdClass = 0; - JNU_ThrowNoSuchFieldException(env, "_count"); - return; - } - - gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I"); - if (!gvdFlagsFID) { - gvdClass = 0; - JNU_ThrowNoSuchFieldException(env, "_flags"); - return; - } - - gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I"); - if (!gvdGlyphsFID) { - gvdClass = 0; - JNU_ThrowNoSuchFieldException(env, "_glyphs"); - return; - } - - gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F"); - if (!gvdPositionsFID) { - gvdClass = 0; - JNU_ThrowNoSuchFieldException(env, "_positions"); - return; - } - + CHECK_NULL(gvdClass = env->FindClass(gvdClassName)); + CHECK_NULL(gvdClass = (jclass)env->NewGlobalRef(gvdClass)); + CHECK_NULL(gvdCountFID = env->GetFieldID(gvdClass, "_count", "I")); + CHECK_NULL(gvdFlagsFID = env->GetFieldID(gvdClass, "_flags", "I")); + CHECK_NULL(gvdGlyphsFID = env->GetFieldID(gvdClass, "_glyphs", "[I")); + CHECK_NULL(gvdPositionsFID = env->GetFieldID(gvdClass, "_positions", "[F")); gvdIndicesFID = env->GetFieldID(gvdClass, "_indices", "[I"); - if (!gvdIndicesFID) { - gvdClass = 0; - JNU_ThrowNoSuchFieldException(env, "_indices"); - return; - } } int putGV(JNIEnv* env, jint gmask, jint baseIndex, jobject gvdata, const LayoutEngine* engine, int glyphCount) { @@ -195,7 +158,7 @@ jchar* chars = buffer; if (len > 256) { size_t size = len * sizeof(jchar); - if (size / sizeof(jchar) != len) { + if (size / sizeof(jchar) != (size_t)len) { return; } chars = (jchar*)malloc(size); @@ -220,10 +183,12 @@ env->SetIntField(gvdata, gvdCountFID, -1); // flag failure } else { if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) { + if (!(env->ExceptionCheck())) { // !!! hmmm, could use current value in positions array of GVData... putFloat(env, pt, x, y); } } + } if (chars != buffer) { free(chars);
--- a/src/share/native/sun/font/sunFont.c Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/native/sun/font/sunFont.c Wed Apr 09 12:26:00 2014 -0700 @@ -27,6 +27,7 @@ #include "string.h" #include "gdefs.h" #include "jlong.h" +#include "jni_util.h" #include "sunfontids.h" #include "fontscalerdefs.h" #include "sun_font_SunFontManager.h" @@ -81,100 +82,106 @@ if (initialisedFontIDs) { return; } - tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont"); - sunFontIDs.ttReadBlockMID = + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont")); + CHECK_NULL(sunFontIDs.ttReadBlockMID = (*env)->GetMethodID(env, tmpClass, "readBlock", - "(Ljava/nio/ByteBuffer;II)I"); - sunFontIDs.ttReadBytesMID = - (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B"); + "(Ljava/nio/ByteBuffer;II)I")); + CHECK_NULL(sunFontIDs.ttReadBytesMID = + (*env)->GetMethodID(env, tmpClass, "readBytes", "(II)[B")); - tmpClass = (*env)->FindClass(env, "sun/font/Type1Font"); - sunFontIDs.readFileMID = + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Type1Font")); + CHECK_NULL(sunFontIDs.readFileMID = (*env)->GetMethodID(env, tmpClass, - "readFile", "(Ljava/nio/ByteBuffer;)V"); + "readFile", "(Ljava/nio/ByteBuffer;)V")); - tmpClass = (*env)->FindClass(env, "java/awt/geom/Point2D$Float"); + CHECK_NULL(tmpClass = + (*env)->FindClass(env, "java/awt/geom/Point2D$Float")); sunFontIDs.pt2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); - sunFontIDs.pt2DFloatCtr = - (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V"); + CHECK_NULL(sunFontIDs.pt2DFloatCtr = + (*env)->GetMethodID(env, sunFontIDs.pt2DFloatClass, "<init>","(FF)V")); - sunFontIDs.xFID = - (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F"); - sunFontIDs.yFID = - (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F"); + CHECK_NULL(sunFontIDs.xFID = + (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "x", "F")); + CHECK_NULL(sunFontIDs.yFID = + (*env)->GetFieldID(env, sunFontIDs.pt2DFloatClass, "y", "F")); - tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics"); - sunFontIDs.strikeMetricsClass=(jclass)(*env)->NewGlobalRef(env, tmpClass); + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/StrikeMetrics")); + CHECK_NULL(sunFontIDs.strikeMetricsClass = + (jclass)(*env)->NewGlobalRef(env, tmpClass)); - sunFontIDs.strikeMetricsCtr = + CHECK_NULL(sunFontIDs.strikeMetricsCtr = (*env)->GetMethodID(env, sunFontIDs.strikeMetricsClass, - "<init>", "(FFFFFFFFFF)V"); + "<init>", "(FFFFFFFFFF)V")); - tmpClass = (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float"); + CHECK_NULL(tmpClass = + (*env)->FindClass(env, "java/awt/geom/Rectangle2D$Float")); sunFontIDs.rect2DFloatClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); - sunFontIDs.rect2DFloatCtr = - (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V"); - sunFontIDs.rect2DFloatCtr4 = + CHECK_NULL(sunFontIDs.rect2DFloatCtr = + (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, "<init>", "()V")); + CHECK_NULL(sunFontIDs.rect2DFloatCtr4 = (*env)->GetMethodID(env, sunFontIDs.rect2DFloatClass, - "<init>", "(FFFF)V"); - sunFontIDs.rectF2DX = - (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F"); - sunFontIDs.rectF2DY = - (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F"); - sunFontIDs.rectF2DWidth = - (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F"); - sunFontIDs.rectF2DHeight = - (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F"); + "<init>", "(FFFF)V")); + CHECK_NULL(sunFontIDs.rectF2DX = + (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "x", "F")); + CHECK_NULL(sunFontIDs.rectF2DY = + (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "y", "F")); + CHECK_NULL(sunFontIDs.rectF2DWidth = + (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "width", "F")); + CHECK_NULL(sunFontIDs.rectF2DHeight = + (*env)->GetFieldID(env, sunFontIDs.rect2DFloatClass, "height", "F")); - tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath"); + CHECK_NULL(tmpClass = (*env)->FindClass(env, "java/awt/geom/GeneralPath")); sunFontIDs.gpClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); - sunFontIDs.gpCtr = - (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V"); - sunFontIDs.gpCtrEmpty = - (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V"); + CHECK_NULL(sunFontIDs.gpCtr = + (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "(I[BI[FI)V")); + CHECK_NULL(sunFontIDs.gpCtrEmpty = + (*env)->GetMethodID(env, sunFontIDs.gpClass, "<init>", "()V")); - tmpClass = (*env)->FindClass(env, "sun/font/Font2D"); - sunFontIDs.f2dCharToGlyphMID = - (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"); - sunFontIDs.getMapperMID = + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/Font2D")); + CHECK_NULL(sunFontIDs.f2dCharToGlyphMID = + (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); + CHECK_NULL(sunFontIDs.getMapperMID = (*env)->GetMethodID(env, tmpClass, "getMapper", - "()Lsun/font/CharToGlyphMapper;"); - sunFontIDs.getTableBytesMID = - (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B"); - sunFontIDs.canDisplayMID = - (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z"); + "()Lsun/font/CharToGlyphMapper;")); + CHECK_NULL(sunFontIDs.getTableBytesMID = + (*env)->GetMethodID(env, tmpClass, "getTableBytes", "(I)[B")); + CHECK_NULL(sunFontIDs.canDisplayMID = + (*env)->GetMethodID(env, tmpClass, "canDisplay", "(C)Z")); - tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper"); - sunFontIDs.charToGlyphMID = - (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I"); + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/CharToGlyphMapper")); + CHECK_NULL(sunFontIDs.charToGlyphMID = + (*env)->GetMethodID(env, tmpClass, "charToGlyph", "(I)I")); - tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike"); - sunFontIDs.getGlyphMetricsMID = + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/PhysicalStrike")); + CHECK_NULL(sunFontIDs.getGlyphMetricsMID = (*env)->GetMethodID(env, tmpClass, "getGlyphMetrics", - "(I)Ljava/awt/geom/Point2D$Float;"); - sunFontIDs.getGlyphPointMID = + "(I)Ljava/awt/geom/Point2D$Float;")); + CHECK_NULL(sunFontIDs.getGlyphPointMID = (*env)->GetMethodID(env, tmpClass, "getGlyphPoint", - "(II)Ljava/awt/geom/Point2D$Float;"); - sunFontIDs.adjustPointMID = + "(II)Ljava/awt/geom/Point2D$Float;")); + CHECK_NULL(sunFontIDs.adjustPointMID = (*env)->GetMethodID(env, tmpClass, "adjustPoint", - "(Ljava/awt/geom/Point2D$Float;)V"); - sunFontIDs.pScalerContextFID = - (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J"); + "(Ljava/awt/geom/Point2D$Float;)V")); + CHECK_NULL(sunFontIDs.pScalerContextFID = + (*env)->GetFieldID(env, tmpClass, "pScalerContext", "J")); - tmpClass = (*env)->FindClass(env, "sun/font/GlyphList"); - sunFontIDs.glyphListX = (*env)->GetFieldID(env, tmpClass, "x", "F"); - sunFontIDs.glyphListY = (*env)->GetFieldID(env, tmpClass, "y", "F"); - sunFontIDs.glyphListLen = (*env)->GetFieldID(env, tmpClass, "len", "I"); - sunFontIDs.glyphImages = - (*env)->GetFieldID(env, tmpClass, "images", "[J"); - sunFontIDs.glyphListUsePos = - (*env)->GetFieldID(env, tmpClass, "usePositions", "Z"); - sunFontIDs.glyphListPos = - (*env)->GetFieldID(env, tmpClass, "positions", "[F"); - sunFontIDs.lcdRGBOrder = - (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z"); - sunFontIDs.lcdSubPixPos = - (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z"); + CHECK_NULL(tmpClass = (*env)->FindClass(env, "sun/font/GlyphList")); + CHECK_NULL(sunFontIDs.glyphListX = + (*env)->GetFieldID(env, tmpClass, "x", "F")); + CHECK_NULL(sunFontIDs.glyphListY = + (*env)->GetFieldID(env, tmpClass, "y", "F")); + CHECK_NULL(sunFontIDs.glyphListLen = + (*env)->GetFieldID(env, tmpClass, "len", "I")); + CHECK_NULL(sunFontIDs.glyphImages = + (*env)->GetFieldID(env, tmpClass, "images", "[J")); + CHECK_NULL(sunFontIDs.glyphListUsePos = + (*env)->GetFieldID(env, tmpClass, "usePositions", "Z")); + CHECK_NULL(sunFontIDs.glyphListPos = + (*env)->GetFieldID(env, tmpClass, "positions", "[F")); + CHECK_NULL(sunFontIDs.lcdRGBOrder = + (*env)->GetFieldID(env, tmpClass, "lcdRGBOrder", "Z")); + CHECK_NULL(sunFontIDs.lcdSubPixPos = + (*env)->GetFieldID(env, tmpClass, "lcdSubPixPos", "Z")); initLCDGammaTables();
--- a/src/share/native/sun/security/pkcs11/j2secmod.c Wed Apr 02 10:01:16 2014 -0700 +++ b/src/share/native/sun/security/pkcs11/j2secmod.c Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,20 +30,27 @@ // #define SECMOD_DEBUG #include "j2secmod.h" +#include "jni_util.h" JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssVersionCheck (JNIEnv *env, jclass thisClass, jlong jHandle, jstring jVersion) { - const char *requiredVersion = (*env)->GetStringUTFChars(env, jVersion, NULL); - int res; - FPTR_VersionCheck versionCheck = - (FPTR_VersionCheck)findFunction(env, jHandle, "NSS_VersionCheck"); + int res = 0; + FPTR_VersionCheck versionCheck; + const char *requiredVersion; + versionCheck = (FPTR_VersionCheck)findFunction(env, jHandle, + "NSS_VersionCheck"); if (versionCheck == NULL) { return JNI_FALSE; } + requiredVersion = (*env)->GetStringUTFChars(env, jVersion, NULL); + if (requiredVersion == NULL) { + return JNI_FALSE; + } + res = versionCheck(requiredVersion); dprintf2("-version >=%s: %d\n", requiredVersion, res); (*env)->ReleaseStringUTFChars(env, jVersion, requiredVersion); @@ -59,55 +66,73 @@ JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssInitialize (JNIEnv *env, jclass thisClass, jstring jFunctionName, jlong jHandle, jstring jConfigDir, jboolean jNssOptimizeSpace) { - const char *functionName = - (*env)->GetStringUTFChars(env, jFunctionName, NULL); - const char *configDir = (jConfigDir == NULL) - ? NULL : (*env)->GetStringUTFChars(env, jConfigDir, NULL); + int res = 0; FPTR_Initialize initialize = (FPTR_Initialize)findFunction(env, jHandle, "NSS_Initialize"); - int res = 0; unsigned int flags = 0x00; + const char *configDir = NULL; + const char *functionName = NULL; + + /* If we cannot initialize, exit now */ + if (initialize == NULL) { + res = 1; + goto cleanup; + } + + functionName = (*env)->GetStringUTFChars(env, jFunctionName, NULL); + if (functionName == NULL) { + res = 1; + goto cleanup; + } + + if (jConfigDir != NULL) { + configDir = (*env)->GetStringUTFChars(env, jConfigDir, NULL); + if (!configDir) { + res = 1; + goto cleanup; + } + } if (jNssOptimizeSpace == JNI_TRUE) { flags = 0x20; // NSS_INIT_OPTIMIZESPACE flag } - if (initialize != NULL) { - /* - * If the NSS_Init function is requested then call NSS_Initialize to - * open the Cert, Key and Security Module databases, read only. - */ - if (strcmp("NSS_Init", functionName) == 0) { - flags = flags | 0x01; // NSS_INIT_READONLY flag - res = initialize(configDir, "", "", "secmod.db", flags); + /* + * If the NSS_Init function is requested then call NSS_Initialize to + * open the Cert, Key and Security Module databases, read only. + */ + if (strcmp("NSS_Init", functionName) == 0) { + flags = flags | 0x01; // NSS_INIT_READONLY flag + res = initialize(configDir, "", "", "secmod.db", flags); - /* - * If the NSS_InitReadWrite function is requested then call - * NSS_Initialize to open the Cert, Key and Security Module databases, - * read/write. - */ - } else if (strcmp("NSS_InitReadWrite", functionName) == 0) { - res = initialize(configDir, "", "", "secmod.db", flags); + /* + * If the NSS_InitReadWrite function is requested then call + * NSS_Initialize to open the Cert, Key and Security Module databases, + * read/write. + */ + } else if (strcmp("NSS_InitReadWrite", functionName) == 0) { + res = initialize(configDir, "", "", "secmod.db", flags); - /* - * If the NSS_NoDB_Init function is requested then call - * NSS_Initialize without creating Cert, Key or Security Module - * databases. - */ - } else if (strcmp("NSS_NoDB_Init", functionName) == 0) { - flags = flags | 0x02 // NSS_INIT_NOCERTDB flag - | 0x04 // NSS_INIT_NOMODDB flag - | 0x08 // NSS_INIT_FORCEOPEN flag - | 0x10; // NSS_INIT_NOROOTINIT flag - res = initialize("", "", "", "", flags); + /* + * If the NSS_NoDB_Init function is requested then call + * NSS_Initialize without creating Cert, Key or Security Module + * databases. + */ + } else if (strcmp("NSS_NoDB_Init", functionName) == 0) { + flags = flags | 0x02 // NSS_INIT_NOCERTDB flag + | 0x04 // NSS_INIT_NOMODDB flag + | 0x08 // NSS_INIT_FORCEOPEN flag + | 0x10; // NSS_INIT_NOROOTINIT flag + res = initialize("", "", "", "", flags); - } else { - res = 2; - } } else { - res = 1; + res = 2; } - (*env)->ReleaseStringUTFChars(env, jFunctionName, functionName); + +cleanup: + if (functionName != NULL) { + (*env)->ReleaseStringUTFChars(env, jFunctionName, functionName); + } if (configDir != NULL) { (*env)->ReleaseStringUTFChars(env, jConfigDir, configDir); } @@ -142,13 +167,30 @@ } jListClass = (*env)->FindClass(env, "java/util/ArrayList"); + if (jListClass == NULL) { + return NULL; + } jListConstructor = (*env)->GetMethodID(env, jListClass, "<init>", "()V"); + if (jListConstructor == NULL) { + return NULL; + } jAdd = (*env)->GetMethodID(env, jListClass, "add", "(Ljava/lang/Object;)Z"); + if (jAdd == NULL) { + return NULL; + } jList = (*env)->NewObject(env, jListClass, jListConstructor); - + if (jList == NULL) { + return NULL; + } jModuleClass = (*env)->FindClass(env, "sun/security/pkcs11/Secmod$Module"); + if (jModuleClass == NULL) { + return NULL; + } jModuleConstructor = (*env)->GetMethodID(env, jModuleClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V"); + if (jModuleConstructor == NULL) { + return NULL; + } while (list != NULL) { module = list->module; @@ -160,16 +202,28 @@ dprintf1("-internal: %d\n", module->internal); dprintf1("-fips: %d\n", module->isFIPS); jCommonName = (*env)->NewStringUTF(env, module->commonName); + if (jCommonName == NULL) { + return NULL; + } if (module->dllName == NULL) { jDllName = NULL; } else { jDllName = (*env)->NewStringUTF(env, module->dllName); + if (jDllName == NULL) { + return NULL; + } } jFIPS = module->isFIPS; for (i = 0; i < module->slotCount; i++ ) { jModule = (*env)->NewObject(env, jModuleClass, jModuleConstructor, jLibDir, jDllName, jCommonName, jFIPS, i); + if (jModule == NULL) { + return NULL; + } (*env)->CallVoidMethod(env, jList, jAdd, jModule); + if ((*env)->ExceptionCheck(env)) { + return NULL; + } } list = list->next; }
--- a/src/solaris/classes/java/lang/UNIXProcess.java.bsd Wed Apr 02 10:01:16 2014 -0700 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.bsd Wed Apr 09 12:26:00 2014 -0700 @@ -342,47 +342,39 @@ ProcessPipeInputStream(int fd) { super(new FileInputStream(newFileDescriptor(fd))); } - - private InputStream drainInputStream(InputStream in) + private static byte[] drainInputStream(InputStream in) throws IOException { int n = 0; int j; byte[] a = null; - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - j = in.available(); - } - while (j > 0) { + while ((j = in.available()) > 0) { a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - n += in.read(a, n, j); - j = in.available(); - } + n += in.read(a, n, j); } - return (a == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n)); + return (a == null || n == a.length) ? a : Arrays.copyOf(a, n); } /** Called by the process reaper thread when the process exits. */ synchronized void processExited() { - try { - InputStream in = this.in; - if (in != null) { - InputStream stragglers = drainInputStream(in); - in.close(); - this.in = stragglers; - } - } catch (IOException ignored) { } + synchronized (closeLock) { + try { + InputStream in = this.in; + // this stream is closed if and only if: in == null + if (in != null) { + byte[] stragglers = drainInputStream(in); + in.close(); + this.in = (stragglers == null) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ByteArrayInputStream(stragglers); + } + } catch (IOException ignored) {} + } } @Override public void close() throws IOException { // BufferedInputStream#close() is not synchronized unlike most other methods. - // Synchronizing helps avoid racing with drainInputStream(). + // Synchronizing helps avoid race with processExited(). synchronized (closeLock) { super.close(); }
--- a/src/solaris/classes/java/lang/UNIXProcess.java.linux Wed Apr 02 10:01:16 2014 -0700 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.linux Wed Apr 09 12:26:00 2014 -0700 @@ -344,47 +344,39 @@ ProcessPipeInputStream(int fd) { super(new FileInputStream(newFileDescriptor(fd))); } - - private InputStream drainInputStream(InputStream in) + private static byte[] drainInputStream(InputStream in) throws IOException { int n = 0; int j; byte[] a = null; - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - j = in.available(); - } - while (j > 0) { + while ((j = in.available()) > 0) { a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j); - synchronized (closeLock) { - if (buf == null) // asynchronous close()? - return null; // discard - n += in.read(a, n, j); - j = in.available(); - } + n += in.read(a, n, j); } - return (a == null) ? - ProcessBuilder.NullInputStream.INSTANCE : - new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n)); + return (a == null || n == a.length) ? a : Arrays.copyOf(a, n); } /** Called by the process reaper thread when the process exits. */ synchronized void processExited() { - try { - InputStream in = this.in; - if (in != null) { - InputStream stragglers = drainInputStream(in); - in.close(); - this.in = stragglers; - } - } catch (IOException ignored) { } + synchronized (closeLock) { + try { + InputStream in = this.in; + // this stream is closed if and only if: in == null + if (in != null) { + byte[] stragglers = drainInputStream(in); + in.close(); + this.in = (stragglers == null) ? + ProcessBuilder.NullInputStream.INSTANCE : + new ByteArrayInputStream(stragglers); + } + } catch (IOException ignored) {} + } } @Override public void close() throws IOException { // BufferedInputStream#close() is not synchronized unlike most other methods. - // Synchronizing helps avoid racing with drainInputStream(). + // Synchronizing helps avoid race with processExited(). synchronized (closeLock) { super.close(); }
--- a/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c Wed Apr 02 10:01:16 2014 -0700 +++ b/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c Wed Apr 09 12:26:00 2014 -0700 @@ -38,8 +38,7 @@ #include "sun_nio_ch_sctp_ResultContainer.h" #include "sun_nio_ch_sctp_PeerAddrChange.h" -/* sizeof(union sctp_notification */ -#define NOTIFICATION_BUFFER_SIZE 280 +static int SCTP_NOTIFICATION_SIZE = sizeof(union sctp_notification); #define MESSAGE_IMPL_CLASS "sun/nio/ch/sctp/MessageInfoImpl" #define RESULT_CONTAINER_CLASS "sun/nio/ch/sctp/ResultContainer" @@ -460,20 +459,47 @@ if (msg->msg_flags & MSG_NOTIFICATION) { char *bufp = (char*)addr; union sctp_notification *snp; + jboolean allocated = JNI_FALSE; - if (!(msg->msg_flags & MSG_EOR) && length < NOTIFICATION_BUFFER_SIZE) { - char buf[NOTIFICATION_BUFFER_SIZE]; + if (rv > SCTP_NOTIFICATION_SIZE) { + JNU_ThrowInternalError(env, "should not reach here"); + return -1; + } + + if (!(msg->msg_flags & MSG_EOR) && length < SCTP_NOTIFICATION_SIZE) { + char* newBuf; int rvSAVE = rv; - memcpy(buf, addr, rv); - iov->iov_base = buf + rv; - iov->iov_len = NOTIFICATION_BUFFER_SIZE - rv; + + if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) { + JNU_ThrowOutOfMemoryError(env, "Out of native heap space."); + return -1; + } + allocated = JNI_TRUE; + + memcpy(newBuf, addr, rv); + iov->iov_base = newBuf + rv; + iov->iov_len = SCTP_NOTIFICATION_SIZE - rv; if ((rv = recvmsg(fd, msg, flags)) < 0) { handleSocketError(env, errno); return 0; } - bufp = buf; + bufp = newBuf; rv += rvSAVE; } +#ifdef __sparc + else if ((intptr_t)addr & 0x3) { + /* the given buffer is not 4 byte aligned */ + char* newBuf; + if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) { + JNU_ThrowOutOfMemoryError(env, "Out of native heap space."); + return -1; + } + allocated = JNI_TRUE; + + memcpy(newBuf, addr, rv); + bufp = newBuf; + } +#endif snp = (union sctp_notification *) bufp; if (handleNotification(env, fd, resultContainerObj, snp, rv, (msg->msg_flags & MSG_EOR), @@ -481,9 +507,16 @@ /* We have received a notification that is of interest to to the Java API. The appropriate notification will be set in the result container. */ + if (allocated == JNI_TRUE) { + free(bufp); + } return 0; } + if (allocated == JNI_TRUE) { + free(bufp); + } + // set iov back to addr, and reset msg_controllen iov->iov_base = addr; iov->iov_len = length;
--- a/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Wed Apr 02 10:01:16 2014 -0700 +++ b/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,10 @@ (JNIEnv *env, jclass thisClass, jstring jLibName) { const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL); + if (libName == NULL) { + return 0L; + } + // look up existing handle only, do not load #if defined(AIX) void *hModule = dlopen(libName, RTLD_LAZY); @@ -65,6 +69,9 @@ { void *hModule; const char *libName = (*env)->GetStringUTFChars(env, jLibName, NULL); + if (libName == NULL) { + return 0L; + } dprintf1("-lib %s\n", libName); hModule = dlopen(libName, RTLD_LAZY);
--- a/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Wed Apr 02 10:01:16 2014 -0700 +++ b/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -88,6 +88,9 @@ const char *getFunctionListStr; const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0); + if (libraryNameStr == NULL) { + return; + } TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr); @@ -123,6 +126,9 @@ // with the old JAR file jGetFunctionList is null, temporarily check for that if (jGetFunctionList != NULL) { getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0); + if (getFunctionListStr == NULL) { + return; + } C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr); (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr); }
--- a/src/windows/native/sun/windows/MouseInfo.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/MouseInfo.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,9 @@ env->DeleteLocalRef(pointClassLocal); } xID = env->GetFieldID(pointClass, "x", "I"); + CHECK_NULL_RETURN(xID, (jint)0); yID = env->GetFieldID(pointClass, "y", "I"); + CHECK_NULL_RETURN(yID, (jint)0); env->SetIntField(point, xID, pt.x); env->SetIntField(point, yID, pt.y);
--- a/src/windows/native/sun/windows/awt.h Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt.h Wed Apr 09 12:26:00 2014 -0700 @@ -49,6 +49,7 @@ #define JNI_CHECK_NULL_GOTO(obj, msg, where) { \ if (obj == NULL) { \ + env->ExceptionClear(); \ JNU_ThrowNullPointerException(env, msg); \ goto where; \ } \ @@ -65,6 +66,7 @@ #define JNI_CHECK_NULL_RETURN(obj, msg) { \ if (obj == NULL) { \ + env->ExceptionClear(); \ JNU_ThrowNullPointerException(env, msg); \ return; \ } \ @@ -91,6 +93,7 @@ #define JNI_CHECK_NULL_RETURN_NULL(obj, msg) { \ if (obj == NULL) { \ + env->ExceptionClear(); \ JNU_ThrowNullPointerException(env, msg); \ return 0; \ } \ @@ -98,6 +101,7 @@ #define JNI_CHECK_NULL_RETURN_VAL(obj, msg, val) { \ if (obj == NULL) { \ + env->ExceptionClear(); \ JNU_ThrowNullPointerException(env, msg); \ return val; \ } \ @@ -124,6 +128,7 @@ #define THROW_NULL_PDATA_IF_NOT_DESTROYED(peer) { \ jboolean destroyed = JNI_GET_DESTROYED(peer); \ if (destroyed != JNI_TRUE) { \ + env->ExceptionClear(); \ JNU_ThrowNullPointerException(env, "null pData"); \ } \ }
--- a/src/windows/native/sun/windows/awt_AWTEvent.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_AWTEvent.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -71,12 +71,16 @@ TRY; AwtAWTEvent::bdataID = env->GetFieldID(cls, "bdata", "[B"); - AwtAWTEvent::idID = env->GetFieldID(cls, "id", "I"); - AwtAWTEvent::consumedID = env->GetFieldID(cls, "consumed", "Z"); + DASSERT(AwtAWTEvent::bdataID != NULL); + CHECK_NULL(AwtAWTEvent::bdataID); - DASSERT(AwtAWTEvent::bdataID != NULL); + AwtAWTEvent::idID = env->GetFieldID(cls, "id", "I"); DASSERT(AwtAWTEvent::idID != NULL); + CHECK_NULL(AwtAWTEvent::idID); + + AwtAWTEvent::consumedID = env->GetFieldID(cls, "consumed", "Z"); DASSERT(AwtAWTEvent::consumedID != NULL); + CHECK_NULL(AwtAWTEvent::consumedID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_Component.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Component.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -467,6 +467,7 @@ jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig"); DASSERT(win32GCCls != NULL); DASSERT(env->IsInstanceOf(compGC, win32GCCls)); + CHECK_NULL(win32GCCls); env->SetObjectField(peer, AwtComponent::peerGCID, compGC); } } @@ -530,10 +531,15 @@ if (dw == ERROR_OUTOFMEMORY) { jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles"); - createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", + if (errorMsg == NULL || env->ExceptionCheck()) { + env->ExceptionClear(); + createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V"); + } else { + createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "(Ljava/lang/String;)V", errorMsg); - env->DeleteLocalRef(errorMsg); + env->DeleteLocalRef(errorMsg); + } } else { @@ -542,14 +548,18 @@ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL); jstring s = JNU_NewStringPlatform(env, buf); - createError = JNU_NewObjectByName(env, "java/lang/InternalError", - "(Ljava/lang/String;)V", s); + if (s == NULL || env->ExceptionCheck()) { + env->ExceptionClear(); + createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V"); + } else { + createError = JNU_NewObjectByName(env, "java/lang/InternalError", + "(Ljava/lang/String;)V", s); + env->DeleteLocalRef(s); + } LocalFree(buf); - env->DeleteLocalRef(s); } - env->SetObjectField(peer, AwtObject::createErrorID, createError); - if (createError != NULL) - { + if (createError != NULL) { + env->SetObjectField(peer, AwtObject::createErrorID, createError); env->DeleteLocalRef(createError); } env->DeleteLocalRef(target); @@ -1719,9 +1729,11 @@ case WM_IME_SETCONTEXT: // lParam is passed as pointer and it can be modified. mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam); + CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); break; case WM_IME_NOTIFY: mr = WmImeNotify(wParam, lParam); + CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); break; case WM_IME_STARTCOMPOSITION: mr = WmImeStartComposition(); @@ -3309,10 +3321,7 @@ if( extKeyCodesCls == NULL) { jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes"); DASSERT(extKeyCodesClsLocal); - if (extKeyCodesClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(extKeyCodesClsLocal); extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal); env->DeleteLocalRef(extKeyCodesClsLocal); } @@ -3321,6 +3330,7 @@ getExtendedKeyCodeForChar = env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I"); DASSERT(getExtendedKeyCodeForChar); + CHECK_NULL(getExtendedKeyCodeForChar); } jint extJKC; //extended Java key code @@ -3940,11 +3950,19 @@ if (cClause && rgClauseBoundary && rgClauseReading) { // convert clause boundary offset array to java array clauseBoundary = env->NewIntArray(cClause+1); + DASSERT(clauseBoundary); + CHECK_NULL(clauseBoundary); env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary); DASSERT(!safe_ExceptionOccurred(env)); // convert clause reading string array to java array - clauseReading = env->NewObjectArray(cClause, JNU_ClassString(env), NULL); + jclass stringCls = JNU_ClassString(env); + DASSERT(stringCls); + CHECK_NULL(stringCls); + clauseReading = env->NewObjectArray(cClause, stringCls, NULL); + env->DeleteLocalRef(stringCls); + DASSERT(clauseReading); + CHECK_NULL(clauseReading); for (int i=0; i<cClause; i++) env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]); DASSERT(!safe_ExceptionOccurred(env)); } @@ -3963,11 +3981,15 @@ if (cAttrBlock && rgAttrBoundary && rgAttrValue) { // convert attribute boundary offset array to java array attrBoundary = env->NewIntArray(cAttrBlock+1); + DASSERT(attrBoundary); + CHECK_NULL(attrBoundary); env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary); DASSERT(!safe_ExceptionOccurred(env)); // convert attribute value byte array to java array attrValue = env->NewByteArray(cAttrBlock); + DASSERT(attrValue); + CHECK_NULL(attrValue); env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue); DASSERT(!safe_ExceptionOccurred(env)); } @@ -3978,10 +4000,7 @@ if (wInputMethodCls == NULL) { jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod"); DASSERT(wInputMethodClsLocal); - if (wInputMethodClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(wInputMethodClsLocal); wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal); env->DeleteLocalRef(wInputMethodClsLocal); } @@ -3992,6 +4011,7 @@ sendIMEventMid = env->GetMethodID(wInputMethodCls, "sendInputMethodEvent", "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V"); DASSERT(sendIMEventMid); + CHECK_NULL(sendIMEventMid); } // call m_InputMethod.sendInputMethod() @@ -4017,10 +4037,7 @@ if (wInputMethodCls == NULL) { jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod"); DASSERT(wInputMethodClsLocal); - if (wInputMethodClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(wInputMethodClsLocal); wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal); env->DeleteLocalRef(wInputMethodClsLocal); } @@ -4028,10 +4045,10 @@ // get method ID of sendInputMethodEvent() (run only once) static jmethodID inqCandPosMid = 0; if (inqCandPosMid == 0) { - inqCandPosMid = env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", - "()V"); + inqCandPosMid = env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V"); DASSERT(!safe_ExceptionOccurred(env)); DASSERT(inqCandPosMid); + CHECK_NULL(inqCandPosMid); } // call m_InputMethod.sendInputMethod() @@ -4070,7 +4087,7 @@ { if (mr != mrConsume) { HWND proxy = GetProxyFocusOwner(); - if (proxy != NULL) { + if (proxy != NULL && ::IsWindowEnabled(proxy)) { retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam); mr = mrConsume; } @@ -4313,6 +4330,11 @@ if ((int) (drawInfo.itemID) >= 0) { jobject font = GET_FONT(target, peer); jstring text = GetItemString(env, target, drawInfo.itemID); + if (env->ExceptionCheck()) { + env->DeleteLocalRef(font); + env->DeleteLocalRef(target); + return; + } SIZE size = AwtFont::getMFStringSize(hDC, font, text); AwtFont::drawMFString(hDC, font, text, (GetRTL()) ? rect.right - size.cx - 1 @@ -4772,6 +4794,7 @@ keyEventConst = env->GetMethodID(keyEventCls, "<init>", "(Ljava/awt/Component;IJIICI)V"); DASSERT(keyEventConst); + CHECK_NULL(keyEventConst); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -4783,6 +4806,10 @@ if (safe_ExceptionOccurred(env)) env->ExceptionDescribe(); DASSERT(!safe_ExceptionOccurred(env)); DASSERT(keyEvent != NULL); + if (keyEvent == NULL) { + env->DeleteLocalRef(target); + return; + } env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode); if( nativeCode && nativeCode < 256 ) { env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode)); @@ -4866,10 +4893,7 @@ if (mouseEventCls == NULL) { jclass mouseEventClsLocal = env->FindClass("java/awt/event/MouseEvent"); - if (!mouseEventClsLocal) { - /* exception already thrown */ - return; - } + CHECK_NULL(mouseEventClsLocal); mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal); env->DeleteLocalRef(mouseEventClsLocal); } @@ -4882,6 +4906,7 @@ env->GetMethodID(mouseEventCls, "<init>", "(Ljava/awt/Component;IJIIIIIIZI)V"); DASSERT(mouseEventConst); + CHECK_NULL(mouseEventConst); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -4894,7 +4919,7 @@ target, id, when, modifiers, x+insets.left, y+insets.top, - xAbs, yAbs, + xAbs, yAbs, clickCount, popupTrigger, button); if (safe_ExceptionOccurred(env)) { @@ -4903,6 +4928,7 @@ } DASSERT(mouseEvent != NULL); + CHECK_NULL(mouseEvent); if (pMsg != 0) { AwtAWTEvent::saveMSG(env, pMsg, mouseEvent); } @@ -4931,10 +4957,7 @@ if (mouseWheelEventCls == NULL) { jclass mouseWheelEventClsLocal = env->FindClass("java/awt/event/MouseWheelEvent"); - if (!mouseWheelEventClsLocal) { - /* exception already thrown */ - return; - } + CHECK_NULL(mouseWheelEventClsLocal); mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal); env->DeleteLocalRef(mouseWheelEventClsLocal); } @@ -4947,6 +4970,7 @@ env->GetMethodID(mouseWheelEventCls, "<init>", "(Ljava/awt/Component;IJIIIIIIZIIID)V"); DASSERT(mouseWheelEventConst); + CHECK_NULL(mouseWheelEventConst); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -4963,11 +4987,14 @@ clickCount, popupTrigger, scrollType, scrollAmount, roundedWheelRotation, preciseWheelRotation); - if (safe_ExceptionOccurred(env)) { + + DASSERT(mouseWheelEvent != NULL); + if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) { env->ExceptionDescribe(); env->ExceptionClear(); - } - DASSERT(mouseWheelEvent != NULL); + env->DeleteLocalRef(target); + return; + } if (pMsg != NULL) { AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent); } @@ -4992,10 +5019,7 @@ jclass focusEventClsLocal = env->FindClass("java/awt/event/FocusEvent"); DASSERT(focusEventClsLocal); - if (focusEventClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(focusEventClsLocal); focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal); env->DeleteLocalRef(focusEventClsLocal); } @@ -5006,6 +5030,7 @@ env->GetMethodID(focusEventCls, "<init>", "(Ljava/awt/Component;IZLjava/awt/Component;)V"); DASSERT(focusEventConst); + CHECK_NULL(focusEventConst); } static jclass sequencedEventCls; @@ -5013,10 +5038,7 @@ jclass sequencedEventClsLocal = env->FindClass("java/awt/SequencedEvent"); DASSERT(sequencedEventClsLocal); - if (sequencedEventClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(sequencedEventClsLocal); sequencedEventCls = (jclass)env->NewGlobalRef(sequencedEventClsLocal); env->DeleteLocalRef(sequencedEventClsLocal); @@ -5027,6 +5049,8 @@ sequencedEventConst = env->GetMethodID(sequencedEventCls, "<init>", "(Ljava/awt/AWTEvent;)V"); + DASSERT(sequencedEventConst); + CHECK_NULL(sequencedEventConst); } if (env->EnsureLocalCapacity(3) < 0) { @@ -5049,6 +5073,7 @@ env->DeleteLocalRef(jOpposite); jOpposite = NULL; } env->DeleteLocalRef(target); target = NULL; + CHECK_NULL(focusEvent); jobject sequencedEvent = env->NewObject(sequencedEventCls, sequencedEventConst, @@ -5056,7 +5081,7 @@ DASSERT(!safe_ExceptionOccurred(env)); DASSERT(sequencedEvent != NULL); env->DeleteLocalRef(focusEvent); focusEvent = NULL; - + CHECK_NULL(sequencedEvent); SendEvent(sequencedEvent); env->DeleteLocalRef(sequencedEvent); @@ -5227,7 +5252,7 @@ "getWheelRotation", "()I").i; DASSERT(!safe_ExceptionOccurred(env)); - //DASSERT(wheelAmt); + JNU_CHECK_EXCEPTION(env); DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt); // convert Java wheel amount value to Win32 @@ -6306,10 +6331,12 @@ { TRY; jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent"); + CHECK_NULL(inputEventClazz); jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I"); + CHECK_NULL(getButtonDownMasksID); jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID); jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE); - + CHECK_NULL(tmp); jsize len = env->GetArrayLength(obj); AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len); for (int i = 0; i < len; i++) { @@ -6322,68 +6349,112 @@ jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer"); DASSERT(peerCls); + CHECK_NULL(peerCls); /* field ids */ AwtComponent::peerID = env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;"); + DASSERT(AwtComponent::peerID); + CHECK_NULL(AwtComponent::peerID); + AwtComponent::xID = env->GetFieldID(cls, "x", "I"); + DASSERT(AwtComponent::xID); + CHECK_NULL(AwtComponent::xID); + AwtComponent::yID = env->GetFieldID(cls, "y", "I"); + DASSERT(AwtComponent::yID); + CHECK_NULL(AwtComponent::yID); + AwtComponent::heightID = env->GetFieldID(cls, "height", "I"); + DASSERT(AwtComponent::heightID); + CHECK_NULL(AwtComponent::heightID); + AwtComponent::widthID = env->GetFieldID(cls, "width", "I"); + DASSERT(AwtComponent::widthID); + CHECK_NULL(AwtComponent::widthID); + AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z"); + DASSERT(AwtComponent::visibleID); + CHECK_NULL(AwtComponent::visibleID); + AwtComponent::backgroundID = env->GetFieldID(cls, "background", "Ljava/awt/Color;"); + DASSERT(AwtComponent::backgroundID); + CHECK_NULL(AwtComponent::backgroundID); + AwtComponent::foregroundID = env->GetFieldID(cls, "foreground", "Ljava/awt/Color;"); + DASSERT(AwtComponent::foregroundID); + CHECK_NULL(AwtComponent::foregroundID); + AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z"); + DASSERT(AwtComponent::enabledID); + CHECK_NULL(AwtComponent::enabledID); + AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;"); + DASSERT(AwtComponent::parentID); + CHECK_NULL(AwtComponent::parentID); + AwtComponent::graphicsConfigID = env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;"); + DASSERT(AwtComponent::graphicsConfigID); + CHECK_NULL(AwtComponent::graphicsConfigID); + AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z"); + DASSERT(AwtComponent::focusableID); + CHECK_NULL(AwtComponent::focusableID); AwtComponent::appContextID = env->GetFieldID(cls, "appContext", "Lsun/awt/AppContext;"); + DASSERT(AwtComponent::appContextID); + CHECK_NULL(AwtComponent::appContextID); AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig", "Lsun/awt/Win32GraphicsConfig;"); + DASSERT(AwtComponent::peerGCID); + CHECK_NULL(AwtComponent::peerGCID); AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J"); + DASSERT(AwtComponent::hwndID); + CHECK_NULL(AwtComponent::hwndID); AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;"); + DASSERT(AwtComponent::cursorID); + CHECK_NULL(AwtComponent::cursorID); /* method ids */ AwtComponent::getFontMID = env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;"); + DASSERT(AwtComponent::getFontMID); + CHECK_NULL(AwtComponent::getFontMID); + AwtComponent::getToolkitMID = env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;"); + DASSERT(AwtComponent::getToolkitMID); + CHECK_NULL(AwtComponent::getToolkitMID); + AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z"); + DASSERT(AwtComponent::isEnabledMID); + CHECK_NULL(AwtComponent::isEnabledMID); + AwtComponent::getLocationOnScreenMID = env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;"); + DASSERT(AwtComponent::getLocationOnScreenMID); + CHECK_NULL(AwtComponent::getLocationOnScreenMID); + AwtComponent::replaceSurfaceDataMID = env->GetMethodID(peerCls, "replaceSurfaceData", "()V"); + DASSERT(AwtComponent::replaceSurfaceDataMID); + CHECK_NULL(AwtComponent::replaceSurfaceDataMID); + AwtComponent::replaceSurfaceDataLaterMID = env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V"); + DASSERT(AwtComponent::replaceSurfaceDataLaterMID); + CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID); + AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V"); - - DASSERT(AwtComponent::xID); - DASSERT(AwtComponent::yID); - DASSERT(AwtComponent::heightID); - DASSERT(AwtComponent::widthID); - DASSERT(AwtComponent::visibleID); - DASSERT(AwtComponent::backgroundID); - DASSERT(AwtComponent::foregroundID); - DASSERT(AwtComponent::enabledID); - DASSERT(AwtComponent::parentID); - DASSERT(AwtComponent::hwndID); - - DASSERT(AwtComponent::getFontMID); - DASSERT(AwtComponent::getToolkitMID); - DASSERT(AwtComponent::isEnabledMID); - DASSERT(AwtComponent::getLocationOnScreenMID); - DASSERT(AwtComponent::replaceSurfaceDataMID); - DASSERT(AwtComponent::replaceSurfaceDataLaterMID); DASSERT(AwtComponent::disposeLaterMID); - + CHECK_NULL(AwtComponent::disposeLaterMID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_DataTransferer.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_DataTransferer.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -274,6 +274,9 @@ jclass str_clazz = env->FindClass("java/lang/String"); DASSERT(str_clazz != NULL); + if (str_clazz == NULL) { + throw std::bad_alloc(); + } jobjectArray filenames = env->NewObjectArray(nFilenames, str_clazz, NULL); if (filenames == NULL) { @@ -827,6 +830,7 @@ TRY; LPCTSTR cStr = JNU_GetStringPlatformChars(env, str, NULL); + CHECK_NULL_RETURN(cStr, 0); jlong value = ::RegisterClipboardFormat(cStr); JNU_ReleaseStringPlatformChars(env, str, cStr);
--- a/src/windows/native/sun/windows/awt_DesktopProperties.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_DesktopProperties.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,13 +83,19 @@ HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); if (dc != NULL) { - SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font")); - SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font")); - SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font")); - SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font")); - SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font")); - SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font")); - SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font")); + try { + SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font")); + SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font")); + SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font")); + SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font")); + SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font")); + SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font")); + SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font")); + } + catch (std::bad_alloc&) { + DeleteDC(dc); + throw; + } DeleteDC(dc); } } @@ -206,24 +212,35 @@ LPTSTR value; value = getXPStylePropFromReg(TEXT("ThemeActive")); - SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1'))); - if (value != NULL) { - free(value); - } - value = getXPStylePropFromReg(TEXT("DllName")); - if (value != NULL) { - SetStringProperty(TEXT("win.xpstyle.dllName"), value); - free(value); + try { + SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1'))); + if (value != NULL) { + free(value); + value = NULL; + } + value = getXPStylePropFromReg(TEXT("DllName")); + if (value != NULL) { + SetStringProperty(TEXT("win.xpstyle.dllName"), value); + free(value); + value = NULL; + } + value = getXPStylePropFromReg(TEXT("SizeName")); + if (value != NULL) { + SetStringProperty(TEXT("win.xpstyle.sizeName"), value); + free(value); + value = NULL; + } + value = getXPStylePropFromReg(TEXT("ColorName")); + if (value != NULL) { + SetStringProperty(TEXT("win.xpstyle.colorName"), value); + free(value); + } } - value = getXPStylePropFromReg(TEXT("SizeName")); - if (value != NULL) { - SetStringProperty(TEXT("win.xpstyle.sizeName"), value); - free(value); - } - value = getXPStylePropFromReg(TEXT("ColorName")); - if (value != NULL) { - SetStringProperty(TEXT("win.xpstyle.colorName"), value); - free(value); + catch (std::bad_alloc&) { + if (value != NULL) { + free(value); + } + throw; } } @@ -564,27 +581,37 @@ // Shell Icon BPP - only honored on platforms before XP value = getWindowsPropFromReg(TEXT("Control Panel\\Desktop\\WindowMetrics"), TEXT("Shell Icon BPP"), &valueType); - if (value != NULL) { - if (valueType == REG_SZ) { - SetStringProperty(TEXT("win.icon.shellIconBPP"), value); + + try { + if (value != NULL) { + if (valueType == REG_SZ) { + SetStringProperty(TEXT("win.icon.shellIconBPP"), value); + } + free(value); + value = NULL; } - free(value); - } - // The following registry settings control the file chooser places bar - // under the Windows L&F. These settings are not present by default, but - // can be enabled using the TweakUI tool from Microsoft. For more info, - // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/ + // The following registry settings control the file chooser places bar + // under the Windows L&F. These settings are not present by default, but + // can be enabled using the TweakUI tool from Microsoft. For more info, + // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/ - // NoPlacesBar is a REG_DWORD, with values 0 or 1 - value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"), - TEXT("NoPlacesBar"), &valueType); - if (value != NULL) { - if (valueType == REG_DWORD) { - SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0)); + // NoPlacesBar is a REG_DWORD, with values 0 or 1 + value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"), + TEXT("NoPlacesBar"), &valueType); + if (value != NULL) { + if (valueType == REG_DWORD) { + SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0)); + } + free(value); } - free(value); + } + catch (std::bad_alloc&) { + if (value != NULL) { + free(value); + } + throw; } LPTSTR valueName = TEXT("PlaceN"); @@ -592,7 +619,15 @@ lstrcpy(valueNameBuf, valueName); LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN"); - LPTSTR propKeyBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(propKey) + 1), sizeof(TCHAR)); + + LPTSTR propKeyBuf; + try { + propKeyBuf = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, (lstrlen(propKey) + 1), sizeof(TCHAR)); + } + catch (std::bad_alloc&) { + free(valueNameBuf); + throw; + } lstrcpy(propKeyBuf, propKey); int i = 0; @@ -601,20 +636,31 @@ propKeyBuf[25] = valueNameBuf[5]; LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar"); - if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) { - if (valueType == REG_DWORD) { - // Value is a CSIDL - SetIntegerProperty(propKeyBuf, (int)*value); - } else { - // Value is a path - SetStringProperty(propKeyBuf, value); + try { + value = NULL; + if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) { + if (valueType == REG_DWORD) { + // Value is a CSIDL + SetIntegerProperty(propKeyBuf, (int)*value); + } else { + // Value is a path + SetStringProperty(propKeyBuf, value); + } + free(value); } - free(value); + } + catch (std::bad_alloc&) { + if (value != NULL) { + free(value); + } + free(propKeyBuf); + free(valueNameBuf); + throw; } } while (value != NULL); + free(propKeyBuf); free(valueNameBuf); - free(propKeyBuf); } void AwtDesktopProperties::GetSoundEvents() { @@ -656,14 +702,26 @@ void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) { jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + throw std::bad_alloc(); + } + jstring jValue = JNU_NewStringPlatform(GetEnv(), value); + if (jValue == NULL) { + GetEnv()->DeleteLocalRef(key); + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setStringPropertyID, - key, JNU_NewStringPlatform(GetEnv(), value)); + key, jValue); + GetEnv()->DeleteLocalRef(jValue); GetEnv()->DeleteLocalRef(key); } void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) { jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setIntegerPropertyID, key, (jint)value); @@ -672,6 +730,9 @@ void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) { jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setBooleanPropertyID, key, value ? JNI_TRUE : JNI_FALSE); @@ -680,6 +741,9 @@ void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) { jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setColorPropertyID, key, GetRValue(value), GetGValue(value), @@ -720,6 +784,11 @@ else { fontName = JNU_NewStringPlatform(GetEnv(), face); } + if (fontName == NULL) { + delete[] face; + throw std::bad_alloc(); + } + jint pointSize = metrics.tmHeight - metrics.tmInternalLeading; jint style = java_awt_Font_PLAIN; @@ -732,11 +801,16 @@ } jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + GetEnv()->DeleteLocalRef(fontName); + delete[] face; + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); + GetEnv()->DeleteLocalRef(key); GetEnv()->DeleteLocalRef(fontName); - GetEnv()->DeleteLocalRef(key); } } delete[] face; @@ -750,7 +824,9 @@ jint style; fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName); - + if (fontName == NULL) { + throw std::bad_alloc(); + } #if 0 HDC hdc; int pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY); @@ -773,22 +849,31 @@ } jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + GetEnv()->DeleteLocalRef(fontName); + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); - + GetEnv()->DeleteLocalRef(key); GetEnv()->DeleteLocalRef(fontName); - GetEnv()->DeleteLocalRef(key); } void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) { jstring key = JNU_NewStringPlatform(GetEnv(), propName); + if (key == NULL) { + throw std::bad_alloc(); + } jstring event = JNU_NewStringPlatform(GetEnv(), winEventName); + if (event == NULL) { + GetEnv()->DeleteLocalRef(key); + throw std::bad_alloc(); + } GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setSoundPropertyID, key, event); - + GetEnv()->DeleteLocalRef(event); GetEnv()->DeleteLocalRef(key); - GetEnv()->DeleteLocalRef(event); } void AwtDesktopProperties::PlayWindowsSound(LPCTSTR event) { @@ -814,24 +899,37 @@ AwtDesktopProperties::pDataID = env->GetFieldID(cls, "pData", "J"); DASSERT(AwtDesktopProperties::pDataID != 0); + CHECK_NULL(AwtDesktopProperties::pDataID); - AwtDesktopProperties::setBooleanPropertyID = env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V"); + AwtDesktopProperties::setBooleanPropertyID = + env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V"); DASSERT(AwtDesktopProperties::setBooleanPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setBooleanPropertyID); - AwtDesktopProperties::setIntegerPropertyID = env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V"); + AwtDesktopProperties::setIntegerPropertyID = + env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V"); DASSERT(AwtDesktopProperties::setIntegerPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setIntegerPropertyID); - AwtDesktopProperties::setStringPropertyID = env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); + AwtDesktopProperties::setStringPropertyID = + env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); DASSERT(AwtDesktopProperties::setStringPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setStringPropertyID); - AwtDesktopProperties::setColorPropertyID = env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V"); + AwtDesktopProperties::setColorPropertyID = + env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V"); DASSERT(AwtDesktopProperties::setColorPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setColorPropertyID); - AwtDesktopProperties::setFontPropertyID = env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V"); + AwtDesktopProperties::setFontPropertyID = + env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V"); DASSERT(AwtDesktopProperties::setFontPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setFontPropertyID); - AwtDesktopProperties::setSoundPropertyID = env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); + AwtDesktopProperties::setSoundPropertyID = + env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V"); DASSERT(AwtDesktopProperties::setSoundPropertyID != 0); + CHECK_NULL(AwtDesktopProperties::setSoundPropertyID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_DnDDS.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_DnDDS.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -643,6 +643,7 @@ m_lastmods == modifiers) {//cannot move before cursor change call_dSCmouseMoved(env, m_peer, m_actions, modifiers, dragPoint.x, dragPoint.y); + JNU_CHECK_EXCEPTION_RETURN(env, E_UNEXPECTED); m_dragPoint = dragPoint; } @@ -977,6 +978,10 @@ if ((matchedFormatEtc.tymed & TYMED_ISTREAM) != 0) { jboolean isCopy; jbyte *bBytes = env->GetByteArrayElements(bytes, &isCopy); + if (bBytes == NULL) { + env->PopLocalFrame(NULL); + return E_UNEXPECTED; + } ULONG act; HRESULT res = pmedium->pstm->Write((const void *)bBytes, (ULONG)nBytes,
--- a/src/windows/native/sun/windows/awt_DnDDT.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_DnDDT.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -603,6 +603,10 @@ jobject local = JNU_NewStringPlatform( env, pmedium->lpszFileName); + if (env->ExceptionCheck()) { + hr = E_OUTOFMEMORY; + break; + } jstring fileName = (jstring)env->NewGlobalRef(local); env->DeleteLocalRef(local); @@ -1220,8 +1224,6 @@ /*****************************************************************************/ -jclass WDTCPIStreamWrapper::javaIOExceptionClazz = (jclass)NULL; - /** * construct a wrapper */ @@ -1233,16 +1235,6 @@ m_istream = stgmedium->pstm; m_istream->AddRef(); m_mutex = ::CreateMutex(NULL, FALSE, NULL); - - if (javaIOExceptionClazz == (jclass)NULL) { - javaIOExceptionClazz = env->FindClass("java/io/IOException"); - - if (JNU_IsNull(env, javaIOExceptionClazz)) { - env->ThrowNew(env->FindClass("java/lang/ClassNotFoundException"), - "Cant find java/io/IOException" - ); - } - } } /** @@ -1291,12 +1283,12 @@ JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (m_istream->Stat(&m_statstg, STATFLAG_NONAME) != S_OK) { - env->ThrowNew(javaIOExceptionClazz, "IStream::Stat() failed"); + JNU_ThrowIOException(env, "IStream::Stat() failed"); return 0; } if (m_statstg.cbSize.QuadPart > 0x7ffffffL) { - env->ThrowNew(javaIOExceptionClazz, "IStream::Stat() cbSize > 0x7ffffff"); + JNU_ThrowIOException(env, "IStream::Stat() cbSize > 0x7ffffff"); return 0; } @@ -1349,7 +1341,7 @@ return (jint)(actual == 0 ? -1 : b); default: - env->ThrowNew(javaIOExceptionClazz, "IStream::Read failed"); + JNU_ThrowIOException(env, "IStream::Read failed"); } return (jint)-1; } @@ -1394,6 +1386,7 @@ ULONG actual = 0; jbyte* local = env->GetByteArrayElements(buf, &isCopy); HRESULT res; + CHECK_NULL_RETURN(local, (jint)-1); switch (res = m_istream->Read((void *)(local + off), (ULONG)len, &actual)) { case S_FALSE: @@ -1406,7 +1399,7 @@ default: env->ReleaseByteArrayElements(buf, local, JNI_ABORT); - env->ThrowNew(javaIOExceptionClazz, "IStream::Read failed"); + JNU_ThrowIOException(env, "IStream::Read failed"); } return (jint)-1;
--- a/src/windows/native/sun/windows/awt_Event.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Event.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,12 +45,16 @@ TRY; AwtEvent::targetID = env->GetFieldID(cls, "target", "Ljava/lang/Object;"); - AwtEvent::xID = env->GetFieldID(cls, "x", "I"); - AwtEvent::yID = env->GetFieldID(cls, "y", "I"); + DASSERT(AwtEvent::targetID != NULL); + CHECK_NULL(AwtEvent::targetID); - DASSERT(AwtEvent::targetID != NULL); + AwtEvent::xID = env->GetFieldID(cls, "x", "I"); DASSERT(AwtEvent::xID != NULL); + CHECK_NULL(AwtEvent::xID); + + AwtEvent::yID = env->GetFieldID(cls, "y", "I"); DASSERT(AwtEvent::yID != NULL); + CHECK_NULL(AwtEvent::yID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_Frame.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Frame.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -342,6 +342,8 @@ case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: + case WM_IME_SETCONTEXT: + case WM_IME_NOTIFY: case WM_IME_CONTROL: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT:
--- a/src/windows/native/sun/windows/awt_InputTextInfor.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_InputTextInfor.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,6 +132,7 @@ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (m_cStrW > 0) { m_jtext = MakeJavaString(env, m_lpStrW, m_cStrW); + JNU_CHECK_EXCEPTION_RETURN(env, -1); } // Merge the string if necessary @@ -251,6 +252,13 @@ } else { readingClauseW[cls] = MakeJavaString(env, lpHWStrW, cHWStrW); } + if (env->ExceptionCheck()) { + lpBndClauseW = NULL; + lpReadingClauseW = NULL; + delete [] bndClauseW; + delete [] readingClauseW; + return 0; + } } else { readingClauseW[cls] = NULL;
--- a/src/windows/native/sun/windows/awt_Insets.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Insets.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -46,14 +46,20 @@ TRY; AwtInsets::leftID = env->GetFieldID(cls, "left", "I"); + DASSERT(AwtInsets::leftID != NULL); + CHECK_NULL(AwtInsets::leftID); + AwtInsets::rightID = env->GetFieldID(cls, "right", "I"); - AwtInsets::topID = env->GetFieldID(cls, "top", "I"); - AwtInsets::bottomID = env->GetFieldID(cls, "bottom", "I"); + DASSERT(AwtInsets::rightID != NULL); + CHECK_NULL(AwtInsets::rightID); - DASSERT(AwtInsets::leftID != NULL); - DASSERT(AwtInsets::rightID != NULL); + AwtInsets::topID = env->GetFieldID(cls, "top", "I"); DASSERT(AwtInsets::topID != NULL); + CHECK_NULL(AwtInsets::topID); + + AwtInsets::bottomID = env->GetFieldID(cls, "bottom", "I"); DASSERT(AwtInsets::bottomID != NULL); + CHECK_NULL(AwtInsets::bottomID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_MouseEvent.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_MouseEvent.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,12 +45,16 @@ TRY; AwtMouseEvent::xID = env->GetFieldID(cls, "x", "I"); - AwtMouseEvent::yID = env->GetFieldID(cls, "y", "I"); - AwtMouseEvent::buttonID = env->GetFieldID(cls, "button", "I"); + DASSERT(AwtMouseEvent::xID != NULL); + CHECK_NULL(AwtMouseEvent::xID); - DASSERT(AwtMouseEvent::xID != NULL); + AwtMouseEvent::yID = env->GetFieldID(cls, "y", "I"); DASSERT(AwtMouseEvent::yID != NULL); + CHECK_NULL(AwtMouseEvent::yID); + + AwtMouseEvent::buttonID = env->GetFieldID(cls, "button", "I"); DASSERT(AwtMouseEvent::buttonID != NULL); + CHECK_NULL(AwtMouseEvent::buttonID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_PrintJob.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_PrintJob.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -281,21 +281,15 @@ static long convertFromPoints(double value, int units); static double convertToPoints(long value, int units); void setCapabilities(JNIEnv *env, jobject self, HDC printDC); -static inline WORD getPrintPaperSize(JNIEnv *env, jobject self); -static inline void setPrintPaperSize(JNIEnv *env, jobject self, WORD sz); -static jint getIntField(JNIEnv *env, jobject self, const char *fieldName); -static jlong getLongField(JNIEnv *env, jobject self, const char *fieldName); -static void setIntField(JNIEnv *env, jobject self, - const char *fieldName, jint value); -static void setLongField(JNIEnv *env, jobject self, - const char *fieldName, jlong value); -static jfieldID getIdOfIntField(JNIEnv *env, jobject self, +static inline WORD getPrintPaperSize(JNIEnv *env, jboolean* err, jobject self); +static inline jboolean setPrintPaperSize(JNIEnv *env, jobject self, WORD sz); +static jint getIntField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName); +static jboolean setIntField(JNIEnv *env, jobject self, + const char *fieldName, jint value); +static jboolean getBooleanField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName); -static jfieldID getIdOfLongField(JNIEnv *env, jobject self, - const char *fieldName); -static void setBooleanField(JNIEnv *env, jobject self, +static jboolean setBooleanField(JNIEnv *env, jobject self, const char *fieldName, jboolean value); - static jbyte *findNonWhite(jbyte *image, long sy, long width, long height, long scanLineStride, long *numLinesP); static jbyte *findWhite(jbyte *image, long sy, long width, long height, @@ -577,7 +571,8 @@ * If both are null, then there is no default printer. */ if ((setup.hDevMode == NULL) && (setup.hDevNames == NULL)) { - return JNI_FALSE; + doIt = JNI_FALSE; + goto done; } } else { int measure = PSD_INTHOUSANDTHSOFINCHES; @@ -602,8 +597,11 @@ * into the Windows setup structure so that the format can * be displayed in the dialog. */ - pageFormatToSetup(env, self, page, &setup, - AwtPrintControl::getPrintDC(env, self)); + pageFormatToSetup(env, self, page, &setup, AwtPrintControl::getPrintDC(env, self)); + if (env->ExceptionCheck()) { + doIt = JNI_FALSE; + goto done; + } setup.lpfnPageSetupHook = reinterpret_cast<LPPAGESETUPHOOK>(pageDlgHook); setup.Flags = PSD_ENABLEPAGESETUPHOOK | PSD_MARGINS; @@ -614,7 +612,10 @@ if (ret) { jobject paper = getPaper(env, page); - + if (paper == NULL) { + doIt = JNI_FALSE; + goto done; + } int units = setup.Flags & PSD_INTHOUSANDTHSOFINCHES ? MM_HIENGLISH : MM_HIMETRIC; @@ -653,19 +654,33 @@ * and place them into a Paper instance. */ setPaperValues(env, paper, &paperSize, &margins, units); - - /* Put the updated Paper instance and the orientation into + if (env->ExceptionCheck()) { + doIt = JNI_FALSE; + goto done; + } + /* + * Put the updated Paper instance and the orientation into * the PageFormat. */ setPaper(env, page, paper); - + if (env->ExceptionCheck()) { + doIt = JNI_FALSE; + goto done; + } setPageFormatOrientation(env, page, orientation); - + if (env->ExceptionCheck()) { + doIt = JNI_FALSE; + goto done; + } if (setup.hDevMode != NULL) { DEVMODE *devmode = (DEVMODE *)::GlobalLock(setup.hDevMode); if (devmode != NULL) { if (devmode->dmFields & DM_PAPERSIZE) { - setPrintPaperSize(env, self, devmode->dmPaperSize); + jboolean err = setPrintPaperSize(env, self, devmode->dmPaperSize); + if (err) { + doIt = JNI_FALSE; + goto done; + } } } ::GlobalUnlock(setup.hDevMode); @@ -673,8 +688,6 @@ doIt = JNI_TRUE; } - DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); - AwtDialog::CheckUninstallModalHook(); AwtDialog::ModalActivateNextWindow(NULL, target, peer); @@ -689,6 +702,7 @@ AwtPrintControl::setPrintHDName(env, self, setup.hDevNames); } +done: env->DeleteGlobalRef(peerGlobalRef); if (target != NULL) { env->DeleteLocalRef(target); @@ -826,8 +840,14 @@ margins.bottom = convertFromPoints(72, units);; jobject paper = getPaper(env, page); + if (paper == NULL) { + goto done; + } + setPaperValues(env, paper, &paperSize, &margins, units); + if (env->ExceptionCheck()) goto done; setPaper(env, page, paper); + if (env->ExceptionCheck()) goto done; if ((pDevMode->dmFields & DM_ORIENTATION) && (pDevMode->dmOrientation == DMORIENT_LANDSCAPE)) { @@ -837,8 +857,10 @@ } } else { - setBooleanField(env, self, NO_DEFAULTPRINTER_STR, (jint)JNI_TRUE); + setBooleanField(env, self, NO_DEFAULTPRINTER_STR, (jint)JNI_TRUE); } + +done: ::GlobalFree(pDevMode); free ((LPTSTR) printerName); @@ -890,9 +912,7 @@ } } - if (printDC == NULL) { - return; - } + JNI_CHECK_NULL_GOTO(printDC, "Invalid printDC", done); /* We try to mitigate the effects of floating point rounding errors * by only setting a value if it would differ from the value in the @@ -903,7 +923,9 @@ const double epsilon = 0.10; jdouble paperWidth, paperHeight; - WORD dmPaperSize = getPrintPaperSize(env, self); + jboolean err; + WORD dmPaperSize = getPrintPaperSize(env, &err, self); + if (err) goto done; double ix, iy, iw, ih, pw, ph; @@ -911,17 +933,24 @@ jmethodID getID; jclass paperClass = env->GetObjectClass(origPaper); + JNI_CHECK_NULL_GOTO(paperClass, "paper class not found", done); getID = env->GetMethodID(paperClass, GETWIDTH_STR, GETWIDTH_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getWidth method", done); pw = env->CallDoubleMethod(origPaper, getID); getID = env->GetMethodID(paperClass, GETHEIGHT_STR, GETHEIGHT_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getHeight method", done); ph = env->CallDoubleMethod(origPaper, getID); getID = env->GetMethodID(paperClass, GETIMG_X_STR, GETIMG_X_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getX method", done); ix = env->CallDoubleMethod(origPaper, getID); getID = env->GetMethodID(paperClass, GETIMG_Y_STR, GETIMG_Y_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getY method", done); iy = env->CallDoubleMethod(origPaper, getID); getID = env->GetMethodID(paperClass, GETIMG_W_STR, GETIMG_W_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getW method", done); iw = env->CallDoubleMethod(origPaper, getID); getID = env->GetMethodID(paperClass, GETIMG_H_STR, GETIMG_H_SIG); + JNI_CHECK_NULL_GOTO(getID, "no getH method", done); ih = env->CallDoubleMethod(origPaper, getID); matchPaperSize(printDC, hDevMode, hDevNames, pw, ph, @@ -1014,12 +1043,16 @@ jmethodID setSizeID = env->GetMethodID(paperClass, SETSIZE_STR, SETSIZE_SIG); + JNI_CHECK_NULL_GOTO(setSizeID, "no setSize method", done); + jmethodID setImageableID = env->GetMethodID(paperClass, SETIMAGEABLE_STR, SETIMAGEABLE_SIG); + JNI_CHECK_NULL_GOTO(setImageableID, "no setImageable method", done); env->CallVoidMethod(newPaper, setSizeID, paperWidth, paperHeight); env->CallVoidMethod(newPaper, setImageableID, ix, iy, iw, ih); +done: /* Free any resources allocated */ if (privateDC == TRUE) { if (printDC != NULL) { @@ -1066,6 +1099,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) { TRY; + jboolean err; initPrinter(env, self); @@ -1089,17 +1123,19 @@ ::GlobalUnlock(devnames); if (devLandRotation == 270) { - setBooleanField(env, self, LANDSCAPE_270_STR, JNI_TRUE); + err = setBooleanField(env, self, LANDSCAPE_270_STR, JNI_TRUE); } else { - setBooleanField(env, self, LANDSCAPE_270_STR, JNI_FALSE); + err = setBooleanField(env, self, LANDSCAPE_270_STR, JNI_FALSE); } + if (err) return; } if (dmFields & DM_COLLATE) { - setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_TRUE); + err = setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_TRUE); } else { - setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE); + err = setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE); } + if (err) return; if (dmFields & DM_COPIES) { setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE); @@ -1110,39 +1146,54 @@ } -static bool setPrintReqAttribute(JNIEnv *env, jobject self, DEVMODE* devmode) { +/* + * returns 0 if print capabilities has been changed + * 1 if print capabilities has not been changed + * -1 in case of error + */ +static int setPrintReqAttribute(JNIEnv *env, jobject self, DEVMODE* devmode) { /* The xRes/yRes fields are only initialised if there is a resolution * attribute. Otherwise they both will be zero, in which case default * resolution should be fine. Consider calling getXRes()/getResY() * rather than accessing the fields directly */ - int xRes=getIntField(env, self, ATTXRES_STR); - int yRes=getIntField(env, self, ATTYRES_STR); - int quality=getIntField(env, self, ATTQUALITY_STR); - int printColor = getIntField(env, self, ATTCHROMATICITY_STR); - int sides = getIntField(env, self, ATTSIDES_STR); - int collate = getIntField(env, self, ATTCOLLATE_STR); + jboolean err; + int xRes=getIntField(env, &err, self, ATTXRES_STR); + if (err) return -1; + int yRes=getIntField(env, &err, self, ATTYRES_STR); + if (err) return -1; + int quality=getIntField(env, &err, self, ATTQUALITY_STR); + if (err) return -1; + int printColor = getIntField(env, &err, self, ATTCHROMATICITY_STR); + if (err) return -1; + int sides = getIntField(env, &err, self, ATTSIDES_STR); + if (err) return -1; + int collate = getIntField(env, &err, self, ATTCOLLATE_STR); + if (err) return -1; int copies = 1; - jclass myClass = env->GetObjectClass(self); // There may be cases when driver reports it cannot handle // multiple copies although it actually can . So this modification // handles that, to make sure that we report copies = 1 because // we already emulated multiple copies. - jfieldID fieldId = env->GetFieldID(myClass, DRIVER_COPIES_STR, "Z"); - if (env->GetBooleanField(self, fieldId)) { - copies = getIntField(env, self, ATTCOPIES_STR); + jboolean driverHandlesCopies = getBooleanField(env, &err, self, DRIVER_COPIES_STR); + if (err) return -1; + if (driverHandlesCopies) { + copies = getIntField(env, &err, self, ATTCOPIES_STR); + if (err) return -1; } // else "driverDoesMultipleCopies" is false, copies should be 1 (default) - int mediatray = getIntField(env, self, ATTMEDIATRAY_STR); - int mediaszname = getIntField(env, self, ATTMEDIASZNAME_STR); - bool ret = true; + int mediatray = getIntField(env, &err, self, ATTMEDIATRAY_STR); + if (err) return -1; + int mediaszname = getIntField(env, &err, self, ATTMEDIASZNAME_STR); + if (err) return -1; + int ret = 1; if (quality && quality < 0) { if (quality != devmode->dmPrintQuality) { devmode->dmPrintQuality = quality; devmode->dmFields |= DM_PRINTQUALITY; - // ret of "false" means that setCapabilities needs to be called - ret = false; + // ret of 0 means that setCapabilities needs to be called + ret = 0; } } else { /* If we didn't set quality, maybe we have resolution settings. */ @@ -1256,7 +1307,7 @@ if (port != NULL && isFilePort(port)) { LPTSTR defPort = GetPrinterPort(env, printer); if (!isFilePort(defPort)) { // not a FILE: port by default - int len = wcslen(defPort); + size_t len = wcslen(defPort); if (len > 0 && port[len-1] == L':') { // is a device port dest = defPort; } else { @@ -1291,12 +1342,19 @@ LPTSTR destination = NULL; if (dest != NULL) { destination = (LPTSTR)JNU_GetStringPlatformChars(env, dest, NULL); + CHECK_NULL_RETURN(destination, JNI_FALSE); } else { destination = VerifyDestination(env, self); } LPTSTR docname = NULL; if (jobname != NULL) { LPTSTR tmp = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL); + if (tmp == NULL) { + if (dest != NULL) { + JNU_ReleaseStringPlatformChars(env, dest, destination); + } + return JNI_FALSE; + } docname = _tcsdup(tmp); JNU_ReleaseStringPlatformChars(env, jobname, tmp); } else { @@ -1317,23 +1375,33 @@ HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, self); if (printDC != NULL && hDevMode != NULL) { DEVMODE *devmode = (DEVMODE *)::GlobalLock(hDevMode); + bool success = true; if (devmode != NULL) { devmode->dmFields |= DM_ORIENTATION; devmode->dmOrientation = DMORIENT_PORTRAIT; /* set attribute values into devmode */ - bool ret = setPrintReqAttribute(env, self, devmode); + int ret = setPrintReqAttribute(env, self, devmode); ::ResetDC(printDC, devmode); RESTORE_CONTROLWORD - if (!ret) { + if (ret == 0) { /* Need to read in updated device capabilities because print quality has been changed. */ setCapabilities(env, self, printDC); + if (env->ExceptionCheck()) success = false; + } else if (ret < 0) { + success = false; } } ::GlobalUnlock(hDevMode); + if (!success) { + if (dest != NULL) { + JNU_ReleaseStringPlatformChars(env, dest, destination); + } + return JNI_FALSE; + } } if (printDC){ @@ -1358,13 +1426,13 @@ } else { err = 0; } - if (dest != NULL) { - JNU_ReleaseStringPlatformChars(env, dest, destination); - } } else { - jclass printerException = env->FindClass(PRINTEREXCEPTION_STR); - env->ThrowNew(printerException, "No printer found."); + JNU_ThrowByName(env, PRINTEREXCEPTION_STR, "No printer found."); + } + + if (dest != NULL) { + JNU_ReleaseStringPlatformChars(env, dest, destination); } if (err && err != ERROR_CANCELLED) { @@ -1481,7 +1549,9 @@ LONG retval = 0; HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, self); HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self); - WORD dmPaperSize = getPrintPaperSize(env, self); + jboolean err; + WORD dmPaperSize = getPrintPaperSize(env, &err, self); + if (err) return; SAVE_CONTROLWORD // Unless the PageFormat has been changed, do not set the paper // size for a new page. Doing so is unnecessary, perhaps expensive, @@ -1492,7 +1562,9 @@ RectDouble paperSize; RectDouble margins; jobject paper = getPaper(env, format); + CHECK_NULL(paper); getPaperValues(env, paper, &paperSize, &margins); + JNU_CHECK_EXCEPTION(env); double paperWidth, paperHeight; matchPaperSize(printDC, hDevMode, hDevNames, paperSize.width, paperSize.height, @@ -1656,6 +1728,7 @@ jbyte *image = NULL; try { image = (jbyte *)env->GetPrimitiveArrayCritical(imageArray, 0); + CHECK_NULL(image); struct { BITMAPINFOHEADER bmiHeader; DWORD* bmiColors; @@ -2194,6 +2267,7 @@ memset(&matchedLogFont, 0, sizeof(matchedLogFont)); LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL); + CHECK_NULL_RETURN(fontNameW, JNI_FALSE); /* Describe the GDI fonts we want enumerated. We * simply supply the java font name and let GDI @@ -2383,6 +2457,7 @@ { SIZE size; LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL); + CHECK_NULL_RETURN(wText, 0); size_t strLen = wcslen(wText); BOOL ok = GetTextExtentPoint32((HDC)printDC, wText, (int)strLen, &size); JNU_ReleaseStringPlatformChars(env, text, wText); @@ -2438,6 +2513,7 @@ long posY = ROUND_TO_LONG(y); int flags = (glyphCodes !=0) ? ETO_GLYPH_INDEX : 0; LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL); + CHECK_NULL(wText); int *advances = NULL, *xadvances = NULL, *xyadvances = NULL; BOOL useYAdvances = FALSE; @@ -2841,10 +2917,12 @@ numCols = MAXCOLS; /* don't write past end of struct */ } bmiCols = (BYTE*)env->GetPrimitiveArrayCritical(bmiColorsArray, 0); + CHECK_NULL(bmiCols); memcpy(&(bmi.bmiColors[0]), bmiCols, (numCols*4)); env->ReleasePrimitiveArrayCritical(bmiColorsArray, bmiCols, 0); } imageBits = (jint *)env->GetPrimitiveArrayCritical(image, 0); + CHECK_NULL(imageBits); // Workaround for drivers/apps that do not support top-down. // Because we don't know if they support or not, @@ -2900,6 +2978,7 @@ try { long scanLineStride = J2DRasterBPP * width; image = (jbyte *)env->GetPrimitiveArrayCritical(imageArray, 0); + CHECK_NULL(image); jbyte *startImage; jbyte *endImage = NULL; long startY = 0; @@ -3132,6 +3211,9 @@ */ int maxCopies = 1; int nCopies = getCopies(env, printerJob); + if (nCopies < 0) { + return NULL; + } SAVE_CONTROLWORD if (pd.hDevNames != NULL) { DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(pd.hDevNames); @@ -3176,11 +3258,14 @@ AwtPrintControl::setPrintHDName(env, printerJob, pd.hDevNames); } - setBooleanField(env, printerJob, DRIVER_COPIES_STR, - (devWillDoCopies ? JNI_TRUE : JNI_FALSE)); - setBooleanField(env, printerJob, DRIVER_COLLATE_STR, JNI_FALSE); - setBooleanField(env, printerJob, USER_COLLATE_STR, JNI_FALSE); - + jboolean err; + err = setBooleanField(env, printerJob, DRIVER_COPIES_STR, + (devWillDoCopies ? JNI_TRUE : JNI_FALSE)); + if (err) return NULL; + err = setBooleanField(env, printerJob, DRIVER_COLLATE_STR, JNI_FALSE); + if (err) return NULL; + err = setBooleanField(env, printerJob, USER_COLLATE_STR, JNI_FALSE); + if (err) return NULL; } return printDC; @@ -3200,6 +3285,7 @@ /* Move the orientation from PageFormat to Windows. */ jint orient = getPageFormatOrientation(env, page); + if (orient < 0) return; int gdiOrientation = (orient == PAGEFORMAT_PORTRAIT) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE; setOrientationInDevMode(setup->hDevMode, orient == PAGEFORMAT_PORTRAIT); @@ -3208,7 +3294,9 @@ ? MM_HIENGLISH : MM_HIMETRIC; jobject paper = getPaper(env, page); + CHECK_NULL(paper); getPaperValues(env, paper, &paperSize, &margins); + JNU_CHECK_EXCEPTION(env); // Setting the paper size appears to be a futile exercise, as its not one // of the values you can initialise - its an out-only arg. Margins are OK. // set it into the DEVMODE if there is one .. @@ -3218,7 +3306,9 @@ if (setup->hDevMode != NULL) { double paperWidth, paperHeight; - WORD dmPaperSize = getPrintPaperSize(env, job); + jboolean err; + WORD dmPaperSize = getPrintPaperSize(env, &err, job); + if (err) return; matchPaperSize(hDC, setup->hDevMode, setup->hDevNames, paperSize.width, paperSize.height, &paperWidth, &paperHeight, &dmPaperSize); @@ -3444,6 +3534,7 @@ jclass printerJobClass = env->GetObjectClass(printerJob); jmethodID getCopiesID = env->GetMethodID(printerJobClass, GETCOPIES_STR, GETCOPIES_SIG); + CHECK_NULL_RETURN(getCopiesID, -1); jint copies = env->CallIntMethod(printerJob, getCopiesID); return copies; @@ -3462,6 +3553,7 @@ jclass pageClass = env->GetObjectClass(page); jmethodID getPaperID = env->GetMethodID(pageClass, GETPAPER_STR, GETPAPER_SIG); + CHECK_NULL_RETURN(getPaperID, NULL); return env->CallObjectMethod(page, getPaperID); } @@ -3479,12 +3571,14 @@ jclass pageClass = env->GetObjectClass(page); jmethodID setPaperID = env->GetMethodID(pageClass, SETPAPER_STR, SETPAPER_SIG); + CHECK_NULL(setPaperID); env->CallVoidMethod(page, setPaperID, paper); } /** * Return the integer ID for the orientation in the PageFormat. * Caution: this is the Java spec ID, not the GDI ID. + * In case of error returns -1 */ static jint getPageFormatOrientation(JNIEnv *env, jobject page) { // Because this function may call client Java code, @@ -3494,6 +3588,7 @@ jclass pageClass = env->GetObjectClass(page); jmethodID getOrientID = env->GetMethodID(pageClass, GETORIENT_STR, GETORIENT_SIG); + CHECK_NULL_RETURN(getOrientID, -1); return env->CallIntMethod(page, getOrientID); } @@ -3506,6 +3601,7 @@ jclass pageClass = env->GetObjectClass(page); jmethodID setOrientID = env->GetMethodID(pageClass, SETORIENT_STR, SETORIENT_SIG); + CHECK_NULL(setOrientID); env->CallVoidMethod(page, setOrientID, orientation); } @@ -3527,24 +3623,29 @@ jclass paperClass = env->GetObjectClass(paper); getID = env->GetMethodID(paperClass, GETWIDTH_STR, GETWIDTH_SIG); + CHECK_NULL(getID); paperSize->width = env->CallDoubleMethod(paper, getID); getID = env->GetMethodID(paperClass, GETHEIGHT_STR, GETHEIGHT_SIG); + CHECK_NULL(getID); paperSize->height = env->CallDoubleMethod(paper, getID); getID = env->GetMethodID(paperClass, GETIMG_X_STR, GETIMG_X_SIG); + CHECK_NULL(getID); margins->x = env->CallDoubleMethod(paper, getID); if (margins-> x < 0 ) { margins-> x = 0; } getID = env->GetMethodID(paperClass, GETIMG_Y_STR, GETIMG_Y_SIG); + CHECK_NULL(getID); margins->y = env->CallDoubleMethod(paper, getID); if (margins-> y < 0 ) { margins-> y = 0; } getID = env->GetMethodID(paperClass, GETIMG_W_STR, GETIMG_W_SIG); + CHECK_NULL(getID); if (widthAsMargin) { margins->width = paperSize->width - margins->x - env->CallDoubleMethod(paper, getID); @@ -3557,6 +3658,7 @@ } getID = env->GetMethodID(paperClass, GETIMG_H_STR, GETIMG_H_SIG); + CHECK_NULL(getID); if (widthAsMargin) { margins->height = paperSize->height - margins->y - env->CallDoubleMethod(paper, getID); @@ -3567,7 +3669,6 @@ if (margins->height < 0) { margins->height = 0; } - } /** @@ -3587,8 +3688,10 @@ jclass paperClass = env->GetObjectClass(paper); jmethodID setSizeID = env->GetMethodID(paperClass, SETSIZE_STR, SETSIZE_SIG); + CHECK_NULL(setSizeID); jmethodID setImageableID = env->GetMethodID(paperClass, SETIMAGEABLE_STR, SETIMAGEABLE_SIG); + CHECK_NULL(setImageableID); /* Set the physical size of the paper. */ @@ -3608,7 +3711,6 @@ jdouble width = convertToPoints(intWidth, units); jdouble height = convertToPoints(intHeight, units); env->CallVoidMethod(paper, setImageableID, x, y, width, height); - } /** @@ -3682,13 +3784,16 @@ */ void setCapabilities(JNIEnv *env, jobject self, HDC printDC) { + jboolean err; // width of page in pixels jint pageWid = GetDeviceCaps(printDC, PHYSICALWIDTH); - setIntField(env, self, PAGEW_STR, pageWid); + err = setIntField(env, self, PAGEW_STR, pageWid); + if (err) return; // height of page in pixels jint pageHgt = GetDeviceCaps(printDC, PHYSICALHEIGHT); - setIntField(env, self, PAGEH_STR, pageHgt); + err = setIntField(env, self, PAGEH_STR, pageHgt); + if (err) return; // x scaling factor of printer jint xsf = GetDeviceCaps(printDC, SCALINGFACTORX); @@ -3716,111 +3821,67 @@ // pixels per inch in x direction jint xRes = GetDeviceCaps(printDC, LOGPIXELSX); - setIntField(env, self, XRES_STR, xRes); + err = setIntField(env, self, XRES_STR, xRes); + if (err) return; // pixels per inch in y direction jint yRes = GetDeviceCaps(printDC, LOGPIXELSY); - setIntField(env, self, YRES_STR, yRes); + err = setIntField(env, self, YRES_STR, yRes); // x coord of printable area in pixels jint xOrg = GetDeviceCaps(printDC, PHYSICALOFFSETX); - setIntField(env, self, PHYSX_STR, xOrg); + err = setIntField(env, self, PHYSX_STR, xOrg); + if (err) return; // y coord of printable area in pixels jint yOrg = GetDeviceCaps(printDC, PHYSICALOFFSETY); - setIntField(env, self, PHYSY_STR, yOrg); + err = setIntField(env, self, PHYSY_STR, yOrg); + if (err) return; // width of printable area in pixels jint printWid = GetDeviceCaps(printDC, HORZRES); - setIntField(env, self, PHYSW_STR, printWid); + err = setIntField(env, self, PHYSW_STR, printWid); + if (err) return; // height of printable area in pixels jint printHgt = GetDeviceCaps(printDC, VERTRES); setIntField(env, self, PHYSH_STR, printHgt); - } - -static inline WORD getPrintPaperSize(JNIEnv *env, jobject self) { - return (WORD)getIntField(env, self, PRINTPAPERSIZE_STR); +static inline WORD getPrintPaperSize(JNIEnv *env, jboolean* err, jobject self) { + return (WORD)getIntField(env, err, self, PRINTPAPERSIZE_STR); } -static inline void setPrintPaperSize(JNIEnv *env, jobject self, WORD sz) { - setIntField(env, self, PRINTPAPERSIZE_STR, (jint)sz); +static inline jboolean setPrintPaperSize(JNIEnv *env, jobject self, WORD sz) { + return setIntField(env, self, PRINTPAPERSIZE_STR, (jint)sz); } /** * Return the java int value of the field 'fieldName' in the * java instance 'self'. */ -static jint getIntField(JNIEnv *env, jobject self, const char *fieldName) { - jfieldID fieldId = getIdOfIntField(env, self, fieldName); - return env->GetIntField(self, fieldId); -} - -/** - * Return the java long value of the field 'fieldName' in the - * java instance 'self'. - */ -static jlong getLongField(JNIEnv *env, jobject self, const char *fieldName) { - jfieldID fieldId = getIdOfLongField(env, self, fieldName); - return env->GetLongField(self, fieldId); +static jint getIntField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName) { + return JNU_GetFieldByName(env, err, self, fieldName, "I").i; } /** * Set the int field named 'fieldName' of the java instance * 'self' to the value 'value'. */ -static void setIntField(JNIEnv *env, jobject self, const char *fieldName, - jint value) { - jfieldID fieldId = getIdOfIntField(env, self, fieldName); - env->SetIntField(self, fieldId, value); -} - -/** - * Set the long field named 'fieldName' of the java instance - * 'self' to the value 'value'. - */ -static void setLongField(JNIEnv *env, jobject self, const char *fieldName, - jlong value) { - jfieldID fieldId = getIdOfLongField(env, self, fieldName); - env->SetLongField(self, fieldId, value); +static jboolean setIntField(JNIEnv *env, jobject self, const char *fieldName, jint value) { + jboolean err; + JNU_SetFieldByName(env, &err, self, fieldName, "I", value); + return err; } -/** - * Return the field id of the java instance 'self' of the - * java int field named 'fieldName'. - */ -static jfieldID getIdOfIntField(JNIEnv *env, jobject self, - const char *fieldName) { - jclass myClass = env->GetObjectClass(self); - jfieldID fieldId = env->GetFieldID(myClass, fieldName, kJavaIntStr); - DASSERT(fieldId != 0); - - return fieldId; - +static jboolean getBooleanField(JNIEnv *env, jboolean* err, jobject self, const char *fieldName) { + return JNU_GetFieldByName(env, err, self, fieldName, "Z").z; } -/** - * Return the field id of the java instance 'self' of the - * java long field named 'fieldName'. - */ -static jfieldID getIdOfLongField(JNIEnv *env, jobject self, - const char *fieldName) { - jclass myClass = env->GetObjectClass(self); - jfieldID fieldId = env->GetFieldID(myClass, fieldName, kJavaLongStr); - DASSERT(fieldId != 0); - - return fieldId; - -} - -static void setBooleanField(JNIEnv *env, jobject self, const char *fieldName, - jboolean value) { - jclass myClass = env->GetObjectClass(self); - jfieldID fieldId = env->GetFieldID(myClass, fieldName, "Z"); - DASSERT(fieldId != 0); - env->SetBooleanField(self, fieldId, value); +static jboolean setBooleanField(JNIEnv *env, jobject self, const char *fieldName, jboolean value) { + jboolean err; + JNU_SetFieldByName(env, &err, self, fieldName, "Z", value); + return err; } /** @@ -3830,8 +3891,6 @@ static void throwPrinterException(JNIEnv *env, DWORD err) { char errStr[256]; TCHAR t_errStr[256]; - jclass printerException = env->FindClass(PRINTEREXCEPTION_STR); - errStr[0] = '\0'; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, @@ -3843,7 +3902,7 @@ WideCharToMultiByte(CP_UTF8, 0, t_errStr, -1, errStr, sizeof(errStr), NULL, NULL); - env->ThrowNew(printerException, errStr); + JNU_ThrowByName(env, PRINTEREXCEPTION_STR, errStr); } @@ -4176,8 +4235,9 @@ jstring printer) { TRY; - LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, - printer, NULL); + LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); + CHECK_NULL(printerName); + HDC hDC = AwtPrintControl::getPrintDC(env, name); if (hDC != NULL) { DeletePrintDC(hDC); @@ -4188,8 +4248,7 @@ hDC = ::CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL); RESTORE_CONTROLWORD if (hDC == NULL) { - jclass printerException = env->FindClass(PRINTEREXCEPTION_STR); - env->ThrowNew(printerException, "Invalid name of PrintService."); + JNU_ThrowByName(env, PRINTEREXCEPTION_STR, "Invalid name of PrintService."); JNU_ReleaseStringPlatformChars(env, printer, printerName); return; } @@ -4223,11 +4282,19 @@ if (devmode != NULL) { if (devmode->dmFields & DM_COPIES) { - setBooleanField(env, name, DRIVER_COPIES_STR, JNI_TRUE); + jboolean err = setBooleanField(env, name, DRIVER_COPIES_STR, JNI_TRUE); + if (err) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + return; + } } if (devmode->dmFields & DM_COLLATE) { - setBooleanField(env, name, DRIVER_COLLATE_STR, JNI_TRUE); + jboolean err = setBooleanField(env, name, DRIVER_COLLATE_STR, JNI_TRUE); + if (err) { + JNU_ReleaseStringPlatformChars(env, printer, printerName); + return; + } } ::GlobalUnlock(hDevMode); @@ -4237,7 +4304,6 @@ JNU_ReleaseStringPlatformChars(env, printer, printerName); CATCH_BAD_ALLOC; - } @@ -4299,14 +4365,15 @@ { TRY; - AwtPrintDialog::controlID = - env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;"); + AwtPrintDialog::controlID = env->GetFieldID(cls, "pjob", "Ljava/awt/print/PrinterJob;"); + DASSERT(AwtPrintDialog::controlID != NULL); + CHECK_NULL(AwtPrintDialog::controlID); + jclass printDialogPeerClass = env->FindClass("sun/awt/windows/WPrintDialogPeer"); - AwtPrintDialog::setHWndMID = - env->GetMethodID(printDialogPeerClass, "setHWnd", "(J)V"); - - DASSERT(AwtPrintDialog::controlID != NULL); + CHECK_NULL(printDialogPeerClass); + AwtPrintDialog::setHWndMID = env->GetMethodID(printDialogPeerClass, "setHWnd", "(J)V"); DASSERT(AwtPrintDialog::setHWndMID != NULL); + CHECK_NULL(AwtPrintDialog::setHWndMID); AwtPrintControl::initIDs(env, cls); CATCH_BAD_ALLOC;
--- a/src/windows/native/sun/windows/awt_Rectangle.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Rectangle.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -46,14 +46,20 @@ TRY; AwtRectangle::xID = env->GetFieldID(cls, "x", "I"); + DASSERT(AwtRectangle::xID != NULL); + CHECK_NULL(AwtRectangle::xID); + AwtRectangle::yID = env->GetFieldID(cls, "y", "I"); - AwtRectangle::widthID = env->GetFieldID(cls, "width", "I"); - AwtRectangle::heightID = env->GetFieldID(cls, "height", "I"); + DASSERT(AwtRectangle::yID != NULL); + CHECK_NULL(AwtRectangle::yID); - DASSERT(AwtRectangle::xID != NULL); - DASSERT(AwtRectangle::yID != NULL); + AwtRectangle::widthID = env->GetFieldID(cls, "width", "I"); DASSERT(AwtRectangle::widthID != NULL); + CHECK_NULL(AwtRectangle::widthID); + + AwtRectangle::heightID = env->GetFieldID(cls, "height", "I"); DASSERT(AwtRectangle::heightID != NULL); + CHECK_NULL(AwtRectangle::heightID); CATCH_BAD_ALLOC; }
--- a/src/windows/native/sun/windows/awt_TextComponent.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_TextComponent.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -852,9 +852,10 @@ TRY; jclass textComponentClassID = env->FindClass("java/awt/TextComponent"); + CHECK_NULL(textComponentClassID); + AwtTextComponent::canAccessClipboardMID = - env->GetMethodID(textComponentClassID, - "canAccessClipboard", "()Z"); + env->GetMethodID(textComponentClassID, "canAccessClipboard", "()Z"); env->DeleteLocalRef(textComponentClassID); DASSERT(AwtTextComponent::canAccessClipboardMID != NULL);
--- a/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,35 +172,22 @@ if (awtAutoShutdownClass == NULL) { jclass awtAutoShutdownClassLocal = env->FindClass("sun/awt/AWTAutoShutdown"); - if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } DASSERT(awtAutoShutdownClassLocal != NULL); - if (awtAutoShutdownClassLocal == NULL) { - return; - } + if (!awtAutoShutdownClassLocal) throw std::bad_alloc(); awtAutoShutdownClass = (jclass)env->NewGlobalRef(awtAutoShutdownClassLocal); env->DeleteLocalRef(awtAutoShutdownClassLocal); + if (!awtAutoShutdownClass) throw std::bad_alloc(); notifyBusyMethodID = env->GetStaticMethodID(awtAutoShutdownClass, "notifyToolkitThreadBusy", "()V"); - if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } + DASSERT(notifyBusyMethodID != NULL); + if (!notifyBusyMethodID) throw std::bad_alloc(); + notifyFreeMethodID = env->GetStaticMethodID(awtAutoShutdownClass, "notifyToolkitThreadFree", "()V"); - if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } - DASSERT(notifyBusyMethodID != NULL); DASSERT(notifyFreeMethodID != NULL); - if (notifyBusyMethodID == NULL || notifyFreeMethodID == NULL) { - return; - } + if (!notifyFreeMethodID) throw std::bad_alloc(); } /* awtAutoShutdownClass == NULL*/ if (busy) { @@ -779,9 +766,11 @@ jclass systemColorClass = env->FindClass("java/awt/SystemColor"); DASSERT(systemColorClass); + if (!systemColorClass) throw std::bad_alloc(); jmethodID mid = env->GetStaticMethodID(systemColorClass, "updateSystemColors", "()V"); DASSERT(mid); + if (!mid) throw std::bad_alloc(); env->CallStaticVoidMethod(systemColorClass, mid); @@ -1041,6 +1030,8 @@ // Notify Java side - call WToolkit.displayChanged() jclass clazz = env->FindClass("sun/awt/windows/WToolkit"); + DASSERT(clazz != NULL); + if (!clazz) throw std::bad_alloc(); env->CallStaticVoidMethod(clazz, AwtToolkit::displayChangeMID); GetInstance().m_displayChanged = TRUE; @@ -2053,15 +2044,20 @@ AwtToolkit::getDefaultToolkitMID = env->GetStaticMethodID(cls,"getDefaultToolkit","()Ljava/awt/Toolkit;"); + DASSERT(AwtToolkit::getDefaultToolkitMID != NULL); + CHECK_NULL(AwtToolkit::getDefaultToolkitMID); + AwtToolkit::getFontMetricsMID = - env->GetMethodID(cls, "getFontMetrics", - "(Ljava/awt/Font;)Ljava/awt/FontMetrics;"); - AwtToolkit::insetsMID = - env->GetMethodID(env->FindClass("java/awt/Insets"), "<init>", "(IIII)V"); - - DASSERT(AwtToolkit::getDefaultToolkitMID != NULL); + env->GetMethodID(cls, "getFontMetrics", "(Ljava/awt/Font;)Ljava/awt/FontMetrics;"); DASSERT(AwtToolkit::getFontMetricsMID != NULL); - DASSERT(AwtToolkit::insetsMID != NULL); + CHECK_NULL(AwtToolkit::getFontMetricsMID); + + jclass insetsClass = env->FindClass("java/awt/Insets"); + DASSERT(insetsClass != NULL); + CHECK_NULL(insetsClass); + AwtToolkit::insetsMID = env->GetMethodID(insetsClass, "<init>", "(IIII)V"); + DASSERT(AwtToolkit::insetsMID != NULL); + CHECK_NULL(AwtToolkit::insetsMID); CATCH_BAD_ALLOC; } @@ -2088,10 +2084,12 @@ AwtToolkit::windowsSettingChangeMID = env->GetMethodID(cls, "windowsSettingChange", "()V"); DASSERT(AwtToolkit::windowsSettingChangeMID != 0); + CHECK_NULL(AwtToolkit::windowsSettingChangeMID); AwtToolkit::displayChangeMID = env->GetStaticMethodID(cls, "displayChanged", "()V"); DASSERT(AwtToolkit::displayChangeMID != 0); + CHECK_NULL(AwtToolkit::displayChangeMID); // Set various global IDs needed by JAWT code. Note: these // variables cannot be set by JAWT code directly due to @@ -2102,24 +2100,37 @@ // negligible penalty. jclass sDataClassLocal = env->FindClass("sun/java2d/SurfaceData"); DASSERT(sDataClassLocal != 0); + CHECK_NULL(sDataClassLocal); + jclass vImgClassLocal = env->FindClass("sun/awt/image/SunVolatileImage"); DASSERT(vImgClassLocal != 0); + CHECK_NULL(vImgClassLocal); + jclass vSMgrClassLocal = env->FindClass("sun/awt/image/VolatileSurfaceManager"); DASSERT(vSMgrClassLocal != 0); + CHECK_NULL(vSMgrClassLocal); + jclass componentClassLocal = env->FindClass("java/awt/Component"); DASSERT(componentClassLocal != 0); + CHECK_NULL(componentClassLocal); + jawtSMgrID = env->GetFieldID(vImgClassLocal, "volSurfaceManager", "Lsun/awt/image/VolatileSurfaceManager;"); DASSERT(jawtSMgrID != 0); + CHECK_NULL(jawtSMgrID); + jawtSDataID = env->GetFieldID(vSMgrClassLocal, "sdCurrent", "Lsun/java2d/SurfaceData;"); DASSERT(jawtSDataID != 0); + CHECK_NULL(jawtSDataID); + jawtPDataID = env->GetFieldID(sDataClassLocal, "pData", "J"); DASSERT(jawtPDataID != 0); - + CHECK_NULL(jawtPDataID); // Save these classes in global references for later use jawtVImgClass = (jclass)env->NewGlobalRef(vImgClassLocal); + CHECK_NULL(jawtVImgClass); jawtComponentClass = (jclass)env->NewGlobalRef(componentClassLocal); CATCH_BAD_ALLOC; @@ -2380,7 +2391,11 @@ TRY; if (AwtToolkit::GetScreenInsets(screen, &rect)) { - insets = env->NewObject(env->FindClass("java/awt/Insets"), + jclass insetsClass = env->FindClass("java/awt/Insets"); + DASSERT(insetsClass != NULL); + CHECK_NULL_RETURN(insetsClass, NULL); + + insets = env->NewObject(insetsClass, AwtToolkit::insetsMID, rect.top, rect.left,
--- a/src/windows/native/sun/windows/awt_Toolkit.h Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Toolkit.h Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,7 @@ int result = m_env->PushLocalFrame(size); if (result < 0) { DASSERT(FALSE); - JNU_ThrowOutOfMemoryError(m_env, "Can't allocate localRefs"); + throw std::bad_alloc(); } } INLINE ~JNILocalFrame() { m_env->PopLocalFrame(NULL); }
--- a/src/windows/native/sun/windows/awt_TrayIcon.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_TrayIcon.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -503,6 +503,7 @@ env->GetMethodID(mouseEventCls, "<init>", "(Ljava/awt/Component;IJIIIIIIZI)V"); DASSERT(mouseEventConst); + CHECK_NULL(mouseEventConst); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -556,6 +557,7 @@ env->GetMethodID(actionEventCls, "<init>", "(Ljava/lang/Object;ILjava/lang/String;JI)V"); DASSERT(actionEventConst); + CHECK_NULL(actionEventConst); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -736,6 +738,7 @@ } tooltipStr = JNU_GetStringPlatformChars(env, jtooltip, (jboolean *)NULL); + if (env->ExceptionCheck()) goto ret; trayIcon->SetToolTip(tooltipStr); JNU_ReleaseStringPlatformChars(env, jtooltip, tooltipStr); ret: @@ -855,9 +858,18 @@ trayIcon = (AwtTrayIcon *)pData; captionStr = JNU_GetStringPlatformChars(env, jcaption, (jboolean *)NULL); + if (env->ExceptionCheck()) goto ret; textStr = JNU_GetStringPlatformChars(env, jtext, (jboolean *)NULL); + if (env->ExceptionCheck()) { + JNU_ReleaseStringPlatformChars(env, jcaption, captionStr); + goto ret; + } msgTypeStr = JNU_GetStringPlatformChars(env, jmsgType, (jboolean *)NULL); - + if (env->ExceptionCheck()) { + JNU_ReleaseStringPlatformChars(env, jcaption, captionStr); + JNU_ReleaseStringPlatformChars(env, jtext, textStr); + goto ret; + } trayIcon->DisplayMessage(captionStr, textStr, msgTypeStr); JNU_ReleaseStringPlatformChars(env, jcaption, captionStr); @@ -889,10 +901,12 @@ /* init field ids */ AwtTrayIcon::idID = env->GetFieldID(cls, "id", "I"); - AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;"); + DASSERT(AwtTrayIcon::idID != NULL); + CHECK_NULL(AwtTrayIcon::idID); - DASSERT(AwtTrayIcon::idID != NULL); + AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;"); DASSERT(AwtTrayIcon::actionCommandID != NULL); + CHECK_NULL( AwtTrayIcon::actionCommandID); CATCH_BAD_ALLOC; } @@ -981,8 +995,11 @@ jint *intRasterDataPtr = NULL; HBITMAP hColor = NULL; try { - intRasterDataPtr = - (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0); + intRasterDataPtr = (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0); + if (intRasterDataPtr == NULL) { + ::DeleteObject(hMask); + return; + } hColor = AwtTrayIcon::CreateBMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH); } catch (...) { if (intRasterDataPtr != NULL) {
--- a/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,7 @@ jobject bounds = NULL; clazz = env->FindClass("java/awt/Rectangle"); + CHECK_NULL_RETURN(clazz, NULL); mid = env->GetMethodID(clazz, "<init>", "(IIII)V"); if (mid != 0) { RECT rRW = {0, 0, 0, 0};
--- a/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -328,16 +328,13 @@ jintArray bitsArray; clazz1 = env->FindClass("java/awt/color/ColorSpace"); + CHECK_NULL_RETURN(clazz1, NULL); mid = env->GetStaticMethodID(clazz1, "getInstance", "(I)Ljava/awt/color/ColorSpace;"); - if (mid == 0) { - return NULL; - } + CHECK_NULL_RETURN(mid, NULL); cspace = env->CallStaticObjectMethod(clazz1, mid, java_awt_color_ColorSpace_CS_GRAY); - if (cspace == 0) { - return NULL; - } + CHECK_NULL_RETURN(cspace, NULL); bits[0] = 8; bitsArray = env->NewIntArray(1); @@ -348,13 +345,10 @@ } clazz = env->FindClass("java/awt/image/ComponentColorModel"); - + CHECK_NULL_RETURN(clazz, NULL); mid = env->GetMethodID(clazz,"<init>", "(Ljava/awt/color/ColorSpace;[IZZII)V"); - - if (mid == 0) { - return NULL; - } + CHECK_NULL_RETURN(mid, NULL); awt_colormodel = env->NewObject(clazz, mid, cspace, @@ -370,12 +364,11 @@ jbyte vbits[256/8]; jobject validBits = NULL; + CHECK_NULL_RETURN(hRGB, NULL); /* Create the LUT from the color map */ try { rgb = (unsigned int *) env->GetPrimitiveArrayCritical(hRGB, 0); - if (rgb == NULL) { - return NULL; - } + CHECK_NULL_RETURN(rgb, NULL); rgbP = rgb; if (!palette) { palette = new AwtPalette(this); @@ -439,10 +432,12 @@ // Construct a new color model if (!allvalid) { jbyteArray bArray = env->NewByteArray(sizeof(vbits)); + CHECK_NULL_RETURN(bArray, NULL); env->SetByteArrayRegion(bArray, 0, sizeof(vbits), vbits); validBits = JNU_NewObjectByName(env, "java/math/BigInteger", "([B)V", bArray); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); } awt_colormodel = JNU_NewObjectByName(env, @@ -500,19 +495,22 @@ jintArray cacheArray = (jintArray)env->GetObjectField(colorModel, AwtWin32GraphicsDevice::indexCMcacheID); if (!rgbArray || !cacheArray) { - JNU_ThrowInternalError(env, - "rgb or lookupcache array of IndexColorModel null"); + JNU_ThrowInternalError(env, "rgb or lookupcache array of IndexColorModel null"); return; } int rgbLength = env->GetArrayLength(rgbArray); int cacheLength = env->GetArrayLength(cacheArray); - jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray, - &isCopy); - jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray, - &isCopy); - if (!cmEntries || !cache) { - JNU_ThrowInternalError(env, - "Problem retrieving rgb or cache critical array"); + jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray, &isCopy); + if (!cmEntries) { + env->ExceptionClear(); + JNU_ThrowInternalError(env, "Problem retrieving rgb critical array"); + return; + } + jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray, &isCopy); + if (!cache) { + env->ExceptionClear(); + env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, JNI_ABORT); + JNU_ThrowInternalError(env, "Problem retrieving cache critical array"); return; } // Set the new rgb values @@ -839,31 +837,36 @@ /* class ids */ AwtWin32GraphicsDevice::indexCMClass = (jclass)env->NewGlobalRef(env->FindClass("java/awt/image/IndexColorModel")); + DASSERT(AwtWin32GraphicsDevice::indexCMClass); + CHECK_NULL(AwtWin32GraphicsDevice::indexCMClass); + AwtWin32GraphicsDevice::wToolkitClass = (jclass)env->NewGlobalRef(env->FindClass("sun/awt/windows/WToolkit")); - - DASSERT(AwtWin32GraphicsDevice::indexCMClass); DASSERT(AwtWin32GraphicsDevice::wToolkitClass); + CHECK_NULL(AwtWin32GraphicsDevice::wToolkitClass); /* field ids */ AwtWin32GraphicsDevice::dynamicColorModelID = env->GetFieldID(cls, "dynamicColorModel", "Ljava/awt/image/ColorModel;"); + DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID); + CHECK_NULL(AwtWin32GraphicsDevice::dynamicColorModelID); + AwtWin32GraphicsDevice::indexCMrgbID = env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "rgb", "[I"); + DASSERT(AwtWin32GraphicsDevice::indexCMrgbID); + CHECK_NULL(AwtWin32GraphicsDevice::indexCMrgbID); + AwtWin32GraphicsDevice::indexCMcacheID = env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "lookupcache", "[I"); + DASSERT(AwtWin32GraphicsDevice::indexCMcacheID); + CHECK_NULL(AwtWin32GraphicsDevice::indexCMcacheID); /* method ids */ AwtWin32GraphicsDevice::paletteChangedMID = env->GetStaticMethodID( AwtWin32GraphicsDevice::wToolkitClass, "paletteChanged", "()V"); - - - DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID); - DASSERT(AwtWin32GraphicsDevice::indexCMrgbID); - DASSERT(AwtWin32GraphicsDevice::indexCMcacheID); - DASSERT(AwtWin32GraphicsDevice::paletteChangedMID); + CHECK_NULL(AwtWin32GraphicsDevice::paletteChangedMID); // Only want to call this once per session make_uns_ordered_dither_array(img_oda_alpha, 256); @@ -1069,16 +1072,15 @@ jclass displayModeClass = env->FindClass("java/awt/DisplayMode"); if (JNU_IsNull(env, displayModeClass)) { - JNU_ThrowInternalError(env, - "Could not get display mode class"); + env->ExceptionClear(); + JNU_ThrowInternalError(env, "Could not get display mode class"); return NULL; } - jmethodID cid = env->GetMethodID(displayModeClass, "<init>", - "(IIII)V"); + jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V"); if (cid == NULL) { - JNU_ThrowInternalError(env, - "Could not get display mode constructor"); + env->ExceptionClear(); + JNU_ThrowInternalError(env, "Could not get display mode constructor"); return NULL; } @@ -1224,6 +1226,7 @@ jmethodID mid = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); if (mid == NULL) { + env->ExceptionClear(); JNU_ThrowInternalError(env, "Could not get method java.util.ArrayList.add()"); return; @@ -1264,6 +1267,7 @@ if (dm.dmBitsPerPel >= 8) { addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); + JNU_CHECK_EXCEPTION(env); } }
--- a/src/windows/native/sun/windows/awt_Window.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_Window.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -483,6 +483,8 @@ env->DeleteLocalRef(target); InitType(env, peer); + JNU_CHECK_EXCEPTION(env); + TweakStyle(windowStyle, windowExStyle); AwtCanvas::CreateHWnd(env, title, @@ -684,15 +686,27 @@ if (point2DClassID == NULL) { jclass point2DClassIDLocal = env->FindClass("java/awt/geom/Point2D"); + if (point2DClassIDLocal == NULL) { + env->DeleteLocalRef(point2D); + return; + } point2DClassID = (jclass)env->NewGlobalRef(point2DClassIDLocal); env->DeleteLocalRef(point2DClassIDLocal); } if (point2DGetXMID == NULL) { point2DGetXMID = env->GetMethodID(point2DClassID, "getX", "()D"); + if (point2DGetXMID == NULL) { + env->DeleteLocalRef(point2D); + return; + } } if (point2DGetYMID == NULL) { point2DGetYMID = env->GetMethodID(point2DClassID, "getY", "()D"); + if (point2DGetYMID == NULL) { + env->DeleteLocalRef(point2D); + return; + } } @@ -1071,6 +1085,7 @@ if (JNU_IsInstanceOfByName(env, target, "javax/swing/Popup$HeavyWeightWindow") > 0) { window->m_isRetainingHierarchyZOrder = TRUE; } + if (env->ExceptionCheck()) goto done; DWORD style = WS_CLIPCHILDREN | WS_POPUP; DWORD exStyle = WS_EX_NOACTIVATE; if (GetRTL()) { @@ -1378,6 +1393,10 @@ ((AwtFrame*)this)->GetMenuBar()) { m_insets.top += ::GetSystemMetrics(SM_CYMENU); } + if (env->ExceptionCheck()) { + env->DeleteLocalRef(target); + return FALSE; + } m_insets.bottom += extraBottomInsets; env->DeleteLocalRef(target); } @@ -1445,14 +1464,13 @@ classEvent = (jclass)env->NewGlobalRef(classEvent); } env->PopLocalFrame(0); + CHECK_NULL(classEvent); } static jmethodID eventInitMID = NULL; if (eventInitMID == NULL) { eventInitMID = env->GetMethodID(classEvent, "<init>", "(Ljava/awt/Component;I)V"); - if (eventInitMID == NULL) { - return; - } + CHECK_NULL(eventInitMID); } if (env->EnsureLocalCapacity(2) < 0) { return; @@ -1462,6 +1480,10 @@ target, eventId); DASSERT(!safe_ExceptionOccurred(env)); DASSERT(event != NULL); + if (event == NULL) { + env->DeleteLocalRef(target); + return; + } SendEvent(event); env->DeleteLocalRef(target); @@ -1503,10 +1525,7 @@ jclass sequencedEventClsLocal = env->FindClass("java/awt/SequencedEvent"); DASSERT(sequencedEventClsLocal); - if (sequencedEventClsLocal == NULL) { - /* exception already thrown */ - return; - } + CHECK_NULL(sequencedEventClsLocal); sequencedEventCls = (jclass)env->NewGlobalRef(sequencedEventClsLocal); env->DeleteLocalRef(sequencedEventClsLocal); @@ -1517,6 +1536,7 @@ sequencedEventConst = env->GetMethodID(sequencedEventCls, "<init>", "(Ljava/awt/AWTEvent;)V"); + CHECK_NULL(sequencedEventConst); } if (env->EnsureLocalCapacity(3) < 0) { @@ -1539,6 +1559,7 @@ env->DeleteLocalRef(jOpposite); jOpposite = NULL; } env->DeleteLocalRef(target); target = NULL; + CHECK_NULL(event); if (id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS || id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS) @@ -2024,10 +2045,15 @@ jclass peerCls = env->GetObjectClass(m_peerObject); DASSERT(peerCls); + CHECK_NULL(peerCls); jmethodID draggedID = env->GetMethodID(peerCls, "draggedToNewScreen", "()V"); DASSERT(draggedID); + if (draggedID == NULL) { + env->DeleteLocalRef(peerCls); + return; + } env->CallVoidMethod(m_peerObject, draggedID); m_screenNum = curScrn; @@ -2505,6 +2531,7 @@ } m_hIconSm = NULL; m_hIcon = CreateIconFromRaster(env, iconRaster, w, h); + JNU_CHECK_EXCEPTION(env); m_hIconSm = CreateIconFromRaster(env, smallIconRaster, smw, smh); m_iconInherited = (m_hIcon == NULL); @@ -3057,22 +3084,23 @@ { TRY; - AwtWindow::warningStringID = - env->GetFieldID(cls, "warningString", "Ljava/lang/String;"); - AwtWindow::locationByPlatformID = - env->GetFieldID(cls, "locationByPlatform", "Z"); - AwtWindow::securityWarningWidthID = - env->GetFieldID(cls, "securityWarningWidth", "I"); - AwtWindow::securityWarningHeightID = - env->GetFieldID(cls, "securityWarningHeight", "I"); - AwtWindow::getWarningStringMID = - env->GetMethodID(cls, "getWarningString", "()Ljava/lang/String;"); - AwtWindow::autoRequestFocusID = - env->GetFieldID(cls, "autoRequestFocus", "Z"); - AwtWindow::calculateSecurityWarningPositionMID = - env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;"); + CHECK_NULL(AwtWindow::warningStringID = + env->GetFieldID(cls, "warningString", "Ljava/lang/String;")); + CHECK_NULL(AwtWindow::locationByPlatformID = + env->GetFieldID(cls, "locationByPlatform", "Z")); + CHECK_NULL(AwtWindow::securityWarningWidthID = + env->GetFieldID(cls, "securityWarningWidth", "I")); + CHECK_NULL(AwtWindow::securityWarningHeightID = + env->GetFieldID(cls, "securityWarningHeight", "I")); + CHECK_NULL(AwtWindow::getWarningStringMID = + env->GetMethodID(cls, "getWarningString", "()Ljava/lang/String;")); + CHECK_NULL(AwtWindow::autoRequestFocusID = + env->GetFieldID(cls, "autoRequestFocus", "Z")); + CHECK_NULL(AwtWindow::calculateSecurityWarningPositionMID = + env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;")); jclass windowTypeClass = env->FindClass("java/awt/Window$Type"); + CHECK_NULL(windowTypeClass); AwtWindow::windowTypeNameMID = env->GetMethodID(windowTypeClass, "name", "()Ljava/lang/String;"); env->DeleteLocalRef(windowTypeClass); @@ -3099,10 +3127,10 @@ { TRY; - AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I"); - AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I"); - AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I"); - AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I"); + CHECK_NULL(AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I")); + CHECK_NULL(AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I")); + CHECK_NULL(AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I")); + CHECK_NULL(AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I")); AwtWindow::windowTypeID = env->GetFieldID(cls, "windowType", "Ljava/awt/Window$Type;");
--- a/src/windows/native/sun/windows/awt_new.cpp Wed Apr 02 10:01:16 2014 -0700 +++ b/src/windows/native/sun/windows/awt_new.cpp Wed Apr 09 12:26:00 2014 -0700 @@ -163,18 +163,13 @@ safe_ExceptionOccurred(JNIEnv *env) throw (std::bad_alloc) { jthrowable xcp = env->ExceptionOccurred(); if (xcp != NULL) { - env->ExceptionClear(); // if we don't do this, FindClass will fail - - jclass outofmem = env->FindClass("java/lang/OutOfMemoryError"); - DASSERT(outofmem != NULL); - jboolean isOutofmem = env->IsInstanceOf(xcp, outofmem); - - env->DeleteLocalRef(outofmem); - - if (isOutofmem) { + env->ExceptionClear(); // if we don't do this, isInstanceOf will fail + jint isOutofmem = JNU_IsInstanceOfByName(env, xcp, "java/lang/OutOfMemoryError"); + if (isOutofmem > 0) { env->DeleteLocalRef(xcp); throw std::bad_alloc(); } else { + env->ExceptionClear(); // rethrow exception env->Throw(xcp); return xcp;
--- a/test/ProblemList.txt Wed Apr 02 10:01:16 2014 -0700 +++ b/test/ProblemList.txt Wed Apr 09 12:26:00 2014 -0700 @@ -234,15 +234,6 @@ java/security/KeyPairGenerator/SolarisShortDSA.java solaris-all sun/security/tools/keytool/standard.sh solaris-all -# 8000439: NPG: REGRESSION : sun/security/krb5/auto/MaxRetries.java fails with timeout -sun/security/krb5/auto/MaxRetries.java solaris-sparcv9 - -# 8006690: sun/security/krb5/auto/BadKdc1.java fails intermittently -sun/security/krb5/auto/BadKdc1.java solaris-sparcv9 -sun/security/krb5/auto/BadKdc2.java solaris-sparcv9 -sun/security/krb5/auto/BadKdc3.java solaris-sparcv9 -sun/security/krb5/auto/BadKdc4.java solaris-sparcv9 - ############################################################################ # jdk_sound
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/nio/sctp/SctpChannel/ReceiveIntoDirect.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8034181 + * @summary SIGBUS in SctpChannelImpl receive + * @author chegar + */ + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.io.IOException; +import java.nio.ByteBuffer; +import com.sun.nio.sctp.AbstractNotificationHandler; +import com.sun.nio.sctp.AssociationChangeNotification; +import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent; +import com.sun.nio.sctp.HandlerResult; +import com.sun.nio.sctp.MessageInfo; +import com.sun.nio.sctp.Notification; +import com.sun.nio.sctp.PeerAddressChangeNotification; +import com.sun.nio.sctp.SctpChannel; +import com.sun.nio.sctp.SctpServerChannel; +import com.sun.nio.sctp.ShutdownNotification; +import static java.lang.System.out; +import static java.lang.System.err; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class ReceiveIntoDirect { + /* suitably small message to NOT overrun small buffers */ + final byte[] msgBytes = "Hello".getBytes(US_ASCII); + + /* number of client connections/combinations (accepted by the server) */ + final int NUM_CONNECTIONS = 75; + + void test(String[] args) throws IOException { + SocketAddress address = null; + Server server; + + if (!Util.isSCTPSupported()) { + out.println("SCTP protocol is not supported"); + out.println("Test cannot be run"); + return; + } + + if (args.length == 2) { + /* requested to connecct to a specific address */ + try { + int port = Integer.valueOf(args[1]); + address = new InetSocketAddress(args[0], port); + } catch (NumberFormatException nfe) { + err.println(nfe); + } + } else { + /* start server on local machine, default */ + server = new Server(); + server.start(); + address = server.address(); + debug("Server started and listening on " + address); + } + + /* many combinations with varing buffer sizes, and offsets */ + runWithManyOffsets(address, 20); + runWithManyOffsets(address, 49); + runWithManyOffsets(address, 50); + runWithManyOffsets(address, 51); + runWithManyOffsets(address, 1024); + } + + void runWithManyOffsets(SocketAddress addr, int bufferSize) + throws IOException + { + doTest(addr, bufferSize, 1); + doTest(addr, bufferSize, 2); + doTest(addr, bufferSize, 3); + doTest(addr, bufferSize, 4); + doTest(addr, bufferSize, 5); + doTest(addr, bufferSize, 6); + doTest(addr, bufferSize, 7); + doTest(addr, bufferSize, 8); + doTest(addr, bufferSize, 9); + doTest(addr, bufferSize, 10); + doTest(addr, bufferSize, 11); + doTest(addr, bufferSize, 12); + doTest(addr, bufferSize, 13); + doTest(addr, bufferSize, 14); + doTest(addr, bufferSize, 15); + } + + void doTest(SocketAddress peerAddress, int bufferSize, int bufferOffset) + throws IOException + { + debug("\n\nTesting with bufferSize " + bufferSize + " and offset " + bufferOffset); + assert bufferOffset + msgBytes.length <= bufferSize : + "buffer offset + message length greater than buffer size "; + + ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); + MessageInfo info; + + try (SctpChannel channel = SctpChannel.open()) { + channel.connect(peerAddress); + + ReceiveNotificationHandler handler = + new ReceiveNotificationHandler(); + + /* TEST 1: Assoc/peer change notif into direct buffer with offest */ + do { + debug("Test 1: Assoc/peer change with offset " + bufferOffset); + buffer.position(bufferOffset); + info = channel.receive(buffer, null, handler); + if (info == null) { + fail("unexpected null from receive"); + return; + } + } while (!info.isComplete()); + + buffer.flip().position(bufferOffset); + check(handler.receivedCommUp(), "SCTP_COMM_UP not received"); + check(info != null, "info is null"); + check(info.address() != null, "address is null"); + check(info.association() != null, "association is null"); + check(info.isComplete(), "message is not complete"); + check(info.isUnordered() != true, + "message should not be unordered"); + check(info.streamNumber() >= 0, "invalid stream number"); + check(info.bytes() == msgBytes.length, + "bytes received not equal to message length"); + check(info.bytes() == buffer.remaining(), "bytes != remaining"); + check(Util.compare(buffer, msgBytes), + "received message not the same as sent message"); + + /* TEST 2: shutdown notification with offset */ + debug("Test 2: shutdown notif with offset " + bufferOffset); + buffer.clear().position(bufferOffset); + while ((info = channel.receive(buffer, null, handler )) != null && + info.bytes() != -1 ); + } + } + + class Server implements Runnable + { + private final InetSocketAddress serverAddr; + private final SctpServerChannel ssc; + + public Server() throws IOException { + ssc = SctpServerChannel.open().bind(null); + java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses(); + if (addrs.isEmpty()) + debug("addrs should not be empty"); + + serverAddr = (InetSocketAddress) addrs.iterator().next(); + } + + public void start() { + (new Thread(this, "Server-" + serverAddr.getPort())).start(); + } + + public InetSocketAddress address() { + return serverAddr; + } + + @Override + public void run() { + try { + for (int i=0; i<NUM_CONNECTIONS; i++) { + SctpChannel sc = ssc.accept(); + + /* send a small message */ + MessageInfo info = MessageInfo.createOutgoing(null, 0); + ByteBuffer buf = ByteBuffer.allocateDirect(Util.SMALL_BUFFER); + buf.put(msgBytes); + buf.flip(); + + debug("sending small message: " + buf); + sc.send(buf, info); + + sc.shutdown(); + sc.close(); + } + } catch (IOException x) { + unexpected(x); + } finally { + try { ssc.close(); } + catch (IOException x) { unexpected(x); } + } + } + } + + class ReceiveNotificationHandler extends AbstractNotificationHandler<Object> + { + boolean receivedCommUp; // false + + public ReceiveNotificationHandler() { } + + public boolean receivedCommUp() { + return receivedCommUp; + } + + @Override + public HandlerResult handleNotification( + Notification notification, Object attachment) { + fail("Unknown notification type"); + return HandlerResult.CONTINUE; + } + + @Override + public HandlerResult handleNotification( + AssociationChangeNotification notification, Object attachment) { + AssocChangeEvent event = notification.event(); + debug("AssociationChangeNotification"); + debug(" Association: " + notification.association()); + debug(" Event: " + event); + + if (event.equals(AssocChangeEvent.COMM_UP)) + receivedCommUp = true; + + return HandlerResult.CONTINUE; + } + + @Override + public HandlerResult handleNotification( + PeerAddressChangeNotification pacn, Object unused) + { + debug("PeerAddressChangeNotification: " + pacn); + return HandlerResult.CONTINUE; + } + + @Override + public HandlerResult handleNotification( + ShutdownNotification notification, Object attachment) { + debug("ShutdownNotification"); + debug(" Association: " + notification.association()); + return HandlerResult.CONTINUE; + } + } + //--------------------- Infrastructure --------------------------- + boolean debug = true; + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} + void debug(String message) {if(debug) { + System.out.println(Thread.currentThread() + " " + message); } } + public static void main(String[] args) throws Throwable { + Class<?> k = new Object(){}.getClass().getEnclosingClass(); + try {k.getMethod("instanceMain",String[].class) + .invoke( k.newInstance(), (Object) args);} + catch (Throwable e) {throw e.getCause();}} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + +}
--- a/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* test - @bug 6998877 + @bug 6998877 8022531 @summary After double-click on the folder names, FileNameOverrideTest FAILED @author Sergey.Bylokhov@oracle.com area=awt.filedialog @library ../../regtesthelpers @@ -59,7 +59,8 @@ String[] instructions = { "1) Click on 'Show File Dialog' button. A file dialog will come up.", - "2) Double-click on '" + clickDirName + "' and click OK.", + "2) Double-click on '" + clickDirName + "' and click a confirmation", + " button, it can be 'OK', 'Save' or any other platform-dependent name.", "3) See result of the test below" };
--- a/test/java/awt/Frame/7024749/bug7024749.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/Frame/7024749/bug7024749.java Wed Apr 09 12:26:00 2014 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 7024749 + * @bug 7024749 8019990 * @summary JDK7 b131---a crash in: Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined+0x75 * @library ../../regtesthelpers * @build Util
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Frame/SlideNotResizableTest/SlideNotResizableTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.awt.SunToolkit; + +import java.awt.*; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.InputEvent; + +/** + * @test + * @bug 8032595 + * @summary setResizable(false) makes a frame slide down + * @author Petr Pchelko + */ + +public class SlideNotResizableTest { + + private static volatile boolean passed = false; + private static final Dimension FRAME_SIZE = new Dimension(100, 100); + private static final Point FRAME_LOCATION = new Point(200, 200); + + public static void main(String[] args) throws Throwable { + Frame aFrame = null; + try { + aFrame = new Frame(); + aFrame.setSize(FRAME_SIZE); + aFrame.setLocation(FRAME_LOCATION); + aFrame.setResizable(false); + aFrame.setVisible(true); + + sync(); + + if (!aFrame.getLocation().equals(FRAME_LOCATION)) { + throw new RuntimeException("FAILED: Wrong frame position"); + } + } finally { + if (aFrame != null) { + aFrame.dispose(); + } + } + } + + private static void sync() throws InterruptedException { + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + Thread.sleep(1000); + } +}
--- a/test/java/awt/Paint/bug8024864.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/Paint/bug8024864.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 8024864 + * @bug 8024864 8031422 * @summary [macosx] Problems with rendering of controls * @author Petr Pchelko * @library ../regtesthelpers @@ -65,7 +65,7 @@ Util.waitForIdle(r); Dimension frameSize = frame.getSize(); - Point loc = new Point(frameSize.width - 5, frameSize.height - 5); + Point loc = new Point(frameSize.width - 15, frameSize.height - 15); SwingUtilities.convertPointToScreen(loc, frame); Color c = r.getPixelColor(loc.x, loc.y);
--- a/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh Wed Apr 09 12:26:00 2014 -0700 @@ -1,7 +1,7 @@ #!/bin/ksh -p # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ # # @test -# @bug 6282388 +# @bug 6282388 8030640 # @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit # @author artem.ananiev@sun.com: area=awt.headless # @compile TestWrapped.java @@ -59,30 +59,14 @@ # Checking for proper OS OS=`uname -s` case "$OS" in - SunOS ) - VAR="One value for Sun" - DEFAULT_JDK=/usr/local/java/jdk1.2/solaris - FILESEP="/" - ;; - - Linux ) - VAR="A different value for Linux" - DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386 + SunOS | Linux | Darwin | CYGWIN* ) FILESEP="/" ;; - - Windows* | CYGWIN* ) - VAR="A different value for Win32" - DEFAULT_JDK=/usr/local/java/jdk1.2/win32 + + Windows* ) FILESEP="\\" ;; - Darwin) - VAR="Lets not forget about Mac" - DEFAULT_JDK=$(/usr/libexec/java_home) - FILESEP="/" - ;; - # catch all other OSs * ) echo "Unrecognized system! $OS" @@ -113,8 +97,7 @@ # THIS IS THE JDK BEING TESTED. if [ -n "$1" ] ; then TESTJAVA=$1 - else echo "no JDK specified on command line so using default!" - TESTJAVA=$DEFAULT_JDK + else fail "no JDK specified on command line!" fi TESTSRC=. TESTCLASSES=.
--- a/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test - @bug 7154072 + @bug 7154072 7161320 @summary Tests that key events with modifiers are not swallowed. @author anton.tarasov: area=awt.focus @library ../../../regtesthelpers @@ -49,6 +49,11 @@ static Robot r; public static void main(String[] args) { + if (sun.awt.OSInfo.getOSType() == sun.awt.OSInfo.OSType.WINDOWS) { + System.out.println("Skipped. Test not for MS Windows."); + return; + } + f.add(t); f.pack(); f.setVisible(true);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/image/MultiResolutionImage/NSImageToMultiResolutionImageTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Image; +import java.awt.Toolkit; +import sun.awt.OSInfo; +import sun.awt.image.MultiResolutionImage; +/* + * @test + * @bug 8033534 8035069 + * @summary [macosx] Get MultiResolution image from native system + * @author Alexander Scherbatiy + * @run main NSImageToMultiResolutionImageTest + */ + +public class NSImageToMultiResolutionImageTest { + + public static void main(String[] args) throws Exception { + + if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) { + return; + } + + String icon = "NSImage://NSApplicationIcon"; + final Image image = Toolkit.getDefaultToolkit().getImage(icon); + + if (!(image instanceof MultiResolutionImage)) { + throw new RuntimeException("Icon does not have resolution variants!"); + } + + MultiResolutionImage multiResolutionImage = (MultiResolutionImage) image; + + int width = 0; + int height = 0; + + for (Image resolutionVariant : multiResolutionImage.getResolutionVariants()) { + int rvWidth = resolutionVariant.getWidth(null); + int rvHeight = resolutionVariant.getHeight(null); + if (rvWidth < width || rvHeight < height) { + throw new RuntimeException("Resolution variants are not sorted!"); + } + width = rvWidth; + height = rvHeight; + } + } +}
--- a/test/java/awt/regtesthelpers/process/ProcessCommunicator.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/awt/regtesthelpers/process/ProcessCommunicator.java Wed Apr 09 12:26:00 2014 -0700 @@ -81,7 +81,7 @@ public static ProcessResults executeChildProcess(final Class classToExecute, final String [] args) { - return executeChildProcess(classToExecute, " ", args); + return executeChildProcess(classToExecute, System.getProperty("java.class.path"), args); } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/ProcessBuilder/CloseRace.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8024521 + * @summary Closing ProcessPipeInputStream at the time the process exits is racy + * and leads to data corruption. Run this test manually (as + * an ordinary java program) with -Xmx8M to repro bug 8024521. + * @run main/othervm -Xmx8M -Dtest.duration=2 CloseRace + */ + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +public class CloseRace { + private static final String BIG_FILE = "bigfile"; + + private static final int[] procFDs = new int[6]; + + /** default value sufficient to repro bug 8024521. */ + private static final int testDurationSeconds + = Integer.getInteger("test.duration", 600); + + private static final CountDownLatch threadsStarted + = new CountDownLatch(2); + + static boolean fdInUse(int i) { + return new File("/proc/self/fd/" + i).exists(); + } + + static boolean[] procFDsInUse() { + boolean[] inUse = new boolean[procFDs.length]; + for (int i = 0; i < procFDs.length; i++) + inUse[i] = fdInUse(procFDs[i]); + return inUse; + } + + static int count(boolean[] bits) { + int count = 0; + for (int i = 0; i < bits.length; i++) + count += bits[i] ? 1 : 0; + return count; + } + + static void dumpAllStacks() { + System.err.println("Start of dump"); + final Map<Thread, StackTraceElement[]> allStackTraces + = Thread.getAllStackTraces(); + for (Thread thread : allStackTraces.keySet()) { + System.err.println("Thread " + thread.getName()); + for (StackTraceElement element : allStackTraces.get(thread)) + System.err.println("\t" + element); + } + System.err.println("End of dump"); + } + + public static void main(String args[]) throws Exception { + if (!(new File("/proc/self/fd").isDirectory())) + return; + + // Catch Errors from process reaper + Thread.setDefaultUncaughtExceptionHandler + ((t, e) -> { e.printStackTrace(); System.exit(1); }); + + try (RandomAccessFile f = new RandomAccessFile(BIG_FILE, "rw")) { + f.setLength(Runtime.getRuntime().maxMemory()); // provoke OOME + } + + for (int i = 0, j = 0; j < procFDs.length; i++) + if (!fdInUse(i)) + procFDs[j++] = i; + + Thread[] threads = { + new Thread(new OpenLoop()), + new Thread(new ExecLoop()), + }; + for (Thread thread : threads) + thread.start(); + + threadsStarted.await(); + Thread.sleep(testDurationSeconds * 1000); + + for (Thread thread : threads) + thread.interrupt(); + for (Thread thread : threads) { + thread.join(10_000); + if (thread.isAlive()) { + dumpAllStacks(); + throw new Error("At least one child thread (" + + thread.getName() + + ") failed to finish gracefully"); + } + } + } + + static class OpenLoop implements Runnable { + public void run() { + threadsStarted.countDown(); + while (!Thread.interrupted()) { + try { + // wait for ExecLoop to finish creating process + do { + if (Thread.interrupted()) + return; + } while (count(procFDsInUse()) != 3); + List<InputStream> iss = new ArrayList<>(4); + + // eat up three "holes" (closed ends of pipe fd pairs) + for (int i = 0; i < 3; i++) + iss.add(new FileInputStream(BIG_FILE)); + do { + if (Thread.interrupted()) + return; + } while (count(procFDsInUse()) == procFDs.length); + // hopefully this will racily occupy empty fd slot + iss.add(new FileInputStream(BIG_FILE)); + Thread.sleep(1); // Widen race window + for (InputStream is : iss) + is.close(); + } catch (InterruptedException e) { + break; + } catch (Exception e) { + throw new Error(e); + } + } + } + } + + static class ExecLoop implements Runnable { + public void run() { + threadsStarted.countDown(); + ProcessBuilder builder = new ProcessBuilder("/bin/true"); + while (!Thread.interrupted()) { + try { + // wait for OpenLoop to finish + do { + if (Thread.interrupted()) + return; + } while (count(procFDsInUse()) > 0); + Process process = builder.start(); + InputStream is = process.getInputStream(); + process.waitFor(); + is.close(); + } catch (InterruptedException e) { + break; + } catch (Exception e) { + throw new Error(e); + } + } + } + } +}
--- a/test/java/lang/Runtime/exec/CloseRace.java Wed Apr 02 10:01:16 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8024521 - * @summary Closing ProcessPipeInputStream at the time the process exits is racy - * and leads to the data corruption. - * @library /lib/testlibrary - * @run main/othervm/timeout=80 CloseRace - */ - -/** - * This test has a little chance to catch the race during the given default - * time gap of 20 seconds. To increase the time gap, set the system property - * CloseRaceTimeGap=N to the number of seconds. - * Jtreg's timeoutFactor should also be set appropriately. - * - * For example, to run the test for 10 minutes: - * > jtreg \ - * -testjdk:$(PATH_TO_TESTED_JDK) \ - * -timeoutFactor:10 \ - * -DCloseRaceTimeGap=600 \ - * $(PATH_TO_TESTED_JDK_SOURCE)/test/java/lang/Runtime/exec/CloseRace.java - */ - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import jdk.testlibrary.OutputAnalyzer; -import static jdk.testlibrary.ProcessTools.*; - -public class CloseRace { - - public static void main(String args[]) throws Exception { - ProcessBuilder pb = createJavaProcessBuilder("-Xmx64M", "CloseRace$Child", - System.getProperty("CloseRaceTimeGap", "20")); - OutputAnalyzer oa = new OutputAnalyzer(pb.start()); - oa.stderrShouldNotContain("java.lang.OutOfMemoryError"); - } - - public static class Child { - private static final String BIG_FILE = "bigfile"; - private static final String SMALL_FILE = "smallfile"; - private static int timeGap = 20; // seconds - - public static void main(String args[]) throws Exception { - if (args.length > 0) { - try { - timeGap = Integer.parseUnsignedInt(args[0]); - timeGap = Integer.max(timeGap, 10); - timeGap = Integer.min(timeGap, 10 * 60 * 60); // no more than 10 hours - } catch (NumberFormatException ignore) {} - } - try (RandomAccessFile f = new RandomAccessFile(BIG_FILE, "rw")) { - f.setLength(1024 * 1024 * 1024); // 1 Gb, greater than max heap size - } - try (FileOutputStream fs = new FileOutputStream(SMALL_FILE); - PrintStream ps = new PrintStream(fs)) { - for (int i = 0; i < 128; ++i) - ps.println("line of text"); - } - - List<Thread> threads = new LinkedList<>(); - for (int i = 0; i < 99; ++i) { - Thread t = new Thread (new OpenLoop()); - t.start(); - threads.add(t); - } - Thread t2 = new Thread (new ExecLoop()); - t2.start(); - threads.add(t2); - - Thread.sleep(timeGap); - - for (Thread t : threads) { - t.interrupt(); - t.join(); - } - } - - private static class OpenLoop implements Runnable { - public void run() { - final Path bigFilePath = Paths.get(BIG_FILE); - while (!Thread.interrupted()) { - try (InputStream in = Files.newInputStream(bigFilePath)) { - // Widen the race window by sleeping 1ms - Thread.sleep(1); - } catch (InterruptedException e) { - break; - } catch (Exception e) { - System.err.println(e); - } - } - } - } - - private static class ExecLoop implements Runnable { - public void run() { - List<String> command = new ArrayList<>( - Arrays.asList("/bin/cat", SMALL_FILE)); - while (!Thread.interrupted()) { - try { - ProcessBuilder builder = new ProcessBuilder(command); - final Process process = builder.start(); - InputStream is = process.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - while (br.readLine() != null) {} - process.waitFor(); - isr.close(); - } catch (InterruptedException e) { - break; - } catch (Exception e) { - System.err.println(e); - } - } - } - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.java.lang.invoke.MethodHandles; + +import com.oracle.testlibrary.jsr292.Helper; +import jdk.testlibrary.Asserts; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +/* @test + * @library /lib/testlibrary/jsr292 /lib/testlibrary/ + * @compile CatchExceptionTest.java + * @run main/othervm -esa test.java.lang.invoke.MethodHandles.CatchExceptionTest + */ +public class CatchExceptionTest { + private static final List<Class<?>> ARGS_CLASSES; + protected static final int MAX_ARITY = Helper.MAX_ARITY - 1; + static { + Class<?> classes[] = { + Object.class, + long.class, + int.class, + byte.class, + Integer[].class, + double[].class, + String.class, + }; + List<Class<?>> list = new ArrayList<>(MAX_ARITY); + for (int i = 0; i < MAX_ARITY; ++i) { + list.add(classes[Helper.RNG.nextInt(classes.length)]); + } + ARGS_CLASSES = Collections.unmodifiableList(list); + } + + private final TestCase testCase; + private final int nargs; + private final int argsCount; + private final MethodHandle catcher; + private int dropped; + private MethodHandle thrower; + + + public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount, + final int catchDrops) { + this.testCase = testCase; + this.dropped = catchDrops; + if (Helper.IS_VERBOSE) { + System.out.printf("CatchException::CatchException(%s, isVararg=%b " + + "argsCount=%d catchDrops=%d)%n", + testCase, isVararg, argsCount, catchDrops + ); + } + MethodHandle thrower = testCase.thrower; + int throwerLen = thrower.type().parameterCount(); + List<Class<?>> classes; + int extra = Math.max(0, argsCount - throwerLen); + classes = getThrowerParams(isVararg, extra); + this.argsCount = throwerLen + classes.size(); + thrower = Helper.addTrailingArgs(thrower, this.argsCount, classes); + if (isVararg && argsCount > throwerLen) { + MethodType mt = thrower.type(); + Class<?> lastParam = mt.parameterType(mt.parameterCount() - 1); + thrower = thrower.asVarargsCollector(lastParam); + } + this.thrower = thrower; + this.dropped = Math.min(this.argsCount, catchDrops); + catcher = testCase.getCatcher(getCatcherParams()); + nargs = Math.max(2, this.argsCount); + } + + public static void main(String[] args) throws Throwable { + for (CatchExceptionTest test : TestFactory.MANDATORY_TEST_CASES) { + test.runTest(); + } + TestFactory factory = new TestFactory(); + CatchExceptionTest test; + while ((test = factory.nextTest()) != null ) { + test.runTest(); + } + } + + private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) { + boolean unmodifiable = true; + List<Class<?>> classes; + classes = ARGS_CLASSES.subList(0, + Math.min(argsCount, (MAX_ARITY / 2) - 1)); + int extra = 0; + if (argsCount >= MAX_ARITY / 2) { + classes = new ArrayList<>(classes); + unmodifiable = false; + extra = (int) classes.stream().filter(Helper::isDoubleCost).count(); + int i = classes.size(); + while (classes.size() + extra < argsCount) { + Class<?> aClass = ARGS_CLASSES.get(i); + if (Helper.isDoubleCost(aClass)) { + ++extra; + if (classes.size() + extra >= argsCount) { + break; + } + } + classes.add(aClass); + } + } + if (isVararg && classes.size() > 0) { + if (unmodifiable) { + classes = new ArrayList<>(classes); + } + int last = classes.size() - 1; + Class<?> aClass = classes.get(classes.size() - 1); + aClass = Array.newInstance(aClass, 2).getClass(); + classes.set(last, aClass); + } + return classes; + } + + + private List<Class<?>> getCatcherParams() { + int catchArgc = 1 + this.argsCount - dropped; + List<Class<?>> result = new ArrayList<>( + thrower.type().parameterList().subList(0, catchArgc - 1)); + // prepend throwable + result.add(0, testCase.throwableClass); + return result; + } + + private void runTest() { + Helper.clear(); + + Object[] args = Helper.randomArgs( + argsCount, thrower.type().parameterArray()); + Object arg0 = Helper.MISSING_ARG; + Object arg1 = testCase.thrown; + if (argsCount > 0) { + arg0 = args[0]; + } + if (argsCount > 1) { + args[1] = arg1; + } + Asserts.assertEQ(nargs, thrower.type().parameterCount()); + if (argsCount < nargs) { + Object[] appendArgs = {arg0, arg1}; + appendArgs = Arrays.copyOfRange(appendArgs, argsCount, nargs); + thrower = MethodHandles.insertArguments( + thrower, argsCount, appendArgs); + } + Asserts.assertEQ(argsCount, thrower.type().parameterCount()); + + MethodHandle target = MethodHandles.catchException( + testCase.filter(thrower), testCase.throwableClass, + testCase.filter(catcher)); + + Asserts.assertEQ(thrower.type(), target.type()); + Asserts.assertEQ(argsCount, target.type().parameterCount()); + + Object returned; + try { + returned = target.invokeWithArguments(args); + } catch (Throwable ex) { + testCase.assertCatch(ex); + returned = ex; + } + + testCase.assertReturn(returned, arg0, arg1, dropped, args); + } +} + +class TestFactory { + public static final List<CatchExceptionTest> MANDATORY_TEST_CASES = new ArrayList<>(); + + private static final int MIN_TESTED_ARITY = 10; + + static { + for (int[] args : new int[][]{ + {0, 0}, + {MIN_TESTED_ARITY, 0}, + {MIN_TESTED_ARITY, MIN_TESTED_ARITY}, + {CatchExceptionTest.MAX_ARITY, 0}, + {CatchExceptionTest.MAX_ARITY, CatchExceptionTest.MAX_ARITY}, + }) { + MANDATORY_TEST_CASES.addAll(createTests(args[0], args[1])); + } + } + + private int count; + private int args; + private int dropArgs; + private int currentMaxDrops; + private int maxArgs; + private int maxDrops; + private int constructor; + private int constructorSize; + private boolean isVararg; + + public TestFactory() { + if (Helper.IS_THOROUGH) { + maxArgs = maxDrops = CatchExceptionTest.MAX_ARITY; + } else { + maxArgs = MIN_TESTED_ARITY + + Helper.RNG.nextInt(CatchExceptionTest.MAX_ARITY + - MIN_TESTED_ARITY) + + 1; + maxDrops = MIN_TESTED_ARITY + + Helper.RNG.nextInt(maxArgs - MIN_TESTED_ARITY) + + 1; + args = 1; + } + + if (Helper.IS_VERBOSE) { + System.out.printf("maxArgs = %d%nmaxDrops = %d%n", + maxArgs, maxDrops); + } + constructorSize = TestCase.CONSTRUCTORS.size(); + } + + private static List<CatchExceptionTest> createTests(int argsCount, + int catchDrops) { + if (catchDrops > argsCount || argsCount < 0 || catchDrops < 0) { + throw new IllegalArgumentException("argsCount = " + argsCount + + ", catchDrops = " + catchDrops + ); + } + List<CatchExceptionTest> result = new ArrayList<>( + TestCase.CONSTRUCTORS.size()); + for (Supplier<TestCase> constructor : TestCase.CONSTRUCTORS) { + result.add(new CatchExceptionTest(constructor.get(), + /* isVararg = */ true, + argsCount, + catchDrops)); + result.add(new CatchExceptionTest(constructor.get(), + /* isVararg = */ false, + argsCount, + catchDrops)); + } + return result; + } + + /** + * @return next test from test matrix: + * {varArgs, noVarArgs} x TestCase.rtypes x TestCase.THROWABLES x {1, .., maxArgs } x {1, .., maxDrops} + */ + public CatchExceptionTest nextTest() { + if (constructor < constructorSize) { + return createTest(); + } + constructor = 0; + count++; + if (!Helper.IS_THOROUGH && count > Helper.TEST_LIMIT) { + System.out.println("test limit is exceeded"); + return null; + } + if (dropArgs <= currentMaxDrops) { + if (dropArgs == 1) { + if (Helper.IS_THOROUGH || Helper.RNG.nextBoolean()) { + ++dropArgs; + return createTest(); + } else if (Helper.IS_VERBOSE) { + System.out.printf( + "argsCount=%d : \"drop\" scenarios are skipped%n", + args); + } + } else { + ++dropArgs; + return createTest(); + } + } + + if (args <= maxArgs) { + dropArgs = 1; + currentMaxDrops = Math.min(args, maxDrops); + ++args; + return createTest(); + } + return null; + } + + private CatchExceptionTest createTest() { + if (!Helper.IS_THOROUGH) { + return new CatchExceptionTest( + TestCase.CONSTRUCTORS.get(constructor++).get(), + Helper.RNG.nextBoolean(), args, dropArgs); + } else { + if (isVararg) { + isVararg = false; + return new CatchExceptionTest( + TestCase.CONSTRUCTORS.get(constructor++).get(), + isVararg, args, dropArgs); + } else { + isVararg = true; + return new CatchExceptionTest( + TestCase.CONSTRUCTORS.get(constructor).get(), + isVararg, args, dropArgs); + } + } + } +} + +class TestCase<T> { + private static enum ThrowMode { + NOTHING, + CAUGHT, + UNCAUGHT, + ADAPTER + } + + @SuppressWarnings("unchecked") + public static final List<Supplier<TestCase>> CONSTRUCTORS; + private static final MethodHandle FAKE_IDENTITY; + private static final MethodHandle THROW_OR_RETURN; + private static final MethodHandle CATCHER; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + THROW_OR_RETURN = lookup.findStatic( + TestCase.class, + "throwOrReturn", + MethodType.methodType(Object.class, Object.class, + Throwable.class) + ); + CATCHER = lookup.findStatic( + TestCase.class, + "catcher", + MethodType.methodType(Object.class, Object.class)); + FAKE_IDENTITY = lookup.findVirtual( + TestCase.class, "fakeIdentity", + MethodType.methodType(Object.class, Object.class)); + + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new Error(e); + } + PartialConstructor[] constructors = { + create(Object.class, Object.class::cast), + create(String.class, Objects::toString), + create(int[].class, x -> new int[]{Objects.hashCode(x)}), + create(long.class, + x -> Objects.hashCode(x) & (-1L >>> 32)), + create(void.class, TestCase::noop)}; + Throwable[] throwables = { + new ClassCastException("testing"), + new java.io.IOException("testing"), + new LinkageError("testing")}; + List<Supplier<TestCase>> list = new ArrayList<>(constructors.length * + throwables.length * ThrowMode.values().length); + //noinspection unchecked + for (PartialConstructor f : constructors) { + for (ThrowMode mode : ThrowMode.values()) { + for (Throwable t : throwables) { + list.add(f.apply(mode, t)); + } + } + } + CONSTRUCTORS = Collections.unmodifiableList(list); + } + + public final Class<T> rtype; + public final ThrowMode throwMode; + public final Throwable thrown; + public final Class<? extends Throwable> throwableClass; + /** + * MH which takes 2 args (Object,Throwable), 1st is the return value, + * 2nd is the exception which will be thrown, if it's supposed in current + * {@link #throwMode}. + */ + public final MethodHandle thrower; + private final Function<Object, T> cast; + protected MethodHandle filter; + private int fakeIdentityCount; + + private TestCase(Class<T> rtype, Function<Object, T> cast, + ThrowMode throwMode, Throwable thrown) + throws NoSuchMethodException, IllegalAccessException { + this.cast = cast; + filter = MethodHandles.lookup().findVirtual( + Function.class, + "apply", + MethodType.methodType(Object.class, Object.class)) + .bindTo(cast); + this.rtype = rtype; + this.throwMode = throwMode; + this.throwableClass = thrown.getClass(); + switch (throwMode) { + case NOTHING: + this.thrown = null; + break; + case ADAPTER: + case UNCAUGHT: + this.thrown = new Error("do not catch this"); + break; + default: + this.thrown = thrown; + } + + MethodHandle throwOrReturn = THROW_OR_RETURN; + if (throwMode == ThrowMode.ADAPTER) { + MethodHandle fakeIdentity = FAKE_IDENTITY.bindTo(this); + for (int i = 0; i < 10; ++i) { + throwOrReturn = MethodHandles.filterReturnValue( + throwOrReturn, fakeIdentity); + } + } + thrower = throwOrReturn.asType(MethodType.genericMethodType(2)); + } + + private static Void noop(Object x) { + return null; + } + + private static <T2> PartialConstructor create( + Class<T2> rtype, Function<Object, T2> cast) { + return (t, u) -> () -> { + try { + return new TestCase<>(rtype, cast, t, u); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new Error(e); + } + }; + } + + private static <T extends Throwable> + Object throwOrReturn(Object normal, T exception) throws T { + if (exception != null) { + Helper.called("throwOrReturn/throw", normal, exception); + throw exception; + } + Helper.called("throwOrReturn/normal", normal, exception); + return normal; + } + + private static <T extends Throwable> + Object catcher(Object o) { + Helper.called("catcher", o); + return o; + } + + public MethodHandle filter(MethodHandle target) { + return MethodHandles.filterReturnValue(target, filter); + } + + public MethodHandle getCatcher(List<Class<?>> classes) { + return MethodHandles.filterReturnValue(Helper.AS_LIST.asType( + MethodType.methodType(Object.class, classes)), + CATCHER + ); + } + + @Override + public String toString() { + return "TestCase{" + + "rtype=" + rtype + + ", throwMode=" + throwMode + + ", throwableClass=" + throwableClass + + '}'; + } + + public String callName() { + return "throwOrReturn/" + + (throwMode == ThrowMode.NOTHING + ? "normal" + : "throw"); + } + + public void assertReturn(Object returned, Object arg0, Object arg1, + int catchDrops, Object... args) { + int lag = 0; + if (throwMode == ThrowMode.CAUGHT) { + lag = 1; + } + Helper.assertCalled(lag, callName(), arg0, arg1); + + if (throwMode == ThrowMode.NOTHING) { + assertEQ(cast.apply(arg0), returned); + } else if (throwMode == ThrowMode.CAUGHT) { + List<Object> catchArgs = new ArrayList<>(Arrays.asList(args)); + // catcher receives an initial subsequence of target arguments: + catchArgs.subList(args.length - catchDrops, args.length).clear(); + // catcher also receives the exception, prepended: + catchArgs.add(0, thrown); + Helper.assertCalled("catcher", catchArgs); + assertEQ(cast.apply(catchArgs), returned); + } + Asserts.assertEQ(0, fakeIdentityCount); + } + + private void assertEQ(T t, Object returned) { + if (rtype.isArray()) { + Asserts.assertEQ(t.getClass(), returned.getClass()); + int n = Array.getLength(t); + Asserts.assertEQ(n, Array.getLength(returned)); + for (int i = 0; i < n; ++i) { + Asserts.assertEQ(Array.get(t, i), Array.get(returned, i)); + } + } else { + Asserts.assertEQ(t, returned); + } + } + + private Object fakeIdentity(Object x) { + System.out.println("should throw through this!"); + ++fakeIdentityCount; + return x; + } + + public void assertCatch(Throwable ex) { + try { + Asserts.assertSame(thrown, ex, + "must get the out-of-band exception"); + } catch (Throwable t) { + ex.printStackTrace(); + } + } + + public interface PartialConstructor + extends BiFunction<ThrowMode, Throwable, Supplier<TestCase>> { + } +}
--- a/test/java/lang/invoke/MethodHandles/TestCatchException.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/lang/invoke/MethodHandles/TestCatchException.java Wed Apr 09 12:26:00 2014 -0700 @@ -72,10 +72,99 @@ assertEquals(x, 17); } + final static Object masterParam = new Object(); + final static Object[] masterTail = new Object[] { "str" }; + static Exception masterEx = new Exception(); + + public static Object m1(Object o1, Object o2, Object o3, Object o4, Object o5, + Object o6, Object o7, Object o8, Object... tail) { + assertEquals(masterParam, o1); + assertEquals(masterParam, o2); + assertEquals(masterParam, o3); + assertEquals(masterParam, o4); + assertEquals(masterParam, o5); + assertEquals(masterParam, o6); + assertEquals(masterParam, o7); + assertEquals(masterParam, o8); + assertEquals(masterTail, tail); + return tail; + } + + public static Object m2(Exception e, Object o1, Object o2, Object o3, Object o4, + Object o5, Object o6, Object o7, Object o8, Object... tail) { + assertEquals(masterEx, e); + assertEquals(masterParam, o1); + assertEquals(masterParam, o2); + assertEquals(masterParam, o3); + assertEquals(masterParam, o4); + assertEquals(masterParam, o5); + assertEquals(masterParam, o6); + assertEquals(masterParam, o7); + assertEquals(masterParam, o8); + assertEquals(masterTail, tail); + return tail; + } + + public static Object throwEx(Object o1, Object o2, Object o3, Object o4, Object o5, + Object o6, Object o7, Object o8, Object... tail) throws Exception { + assertEquals(masterParam, o1); + assertEquals(masterParam, o2); + assertEquals(masterParam, o3); + assertEquals(masterParam, o4); + assertEquals(masterParam, o5); + assertEquals(masterParam, o6); + assertEquals(masterParam, o7); + assertEquals(masterParam, o8); + assertEquals(masterTail, tail); + throw masterEx; + } + + @Test + public void testVarargsCollectorNoThrow() throws Throwable { + MethodType t1 = MethodType.methodType(Object.class, Object.class, Object.class, Object.class, Object.class, + Object.class, Object.class, Object.class, Object.class, Object[].class); + + MethodType t2 = t1.insertParameterTypes(0, Exception.class); + + MethodHandle target = LOOKUP.findStatic(TestCatchException.class, "m1", t1) + .asVarargsCollector(Object[].class); + MethodHandle catcher = LOOKUP.findStatic(TestCatchException.class, "m2", t2) + .asVarargsCollector(Object[].class); + MethodHandle gwc = MethodHandles.catchException(target, Exception.class, catcher); + + Object o = masterParam; + Object[] obj1 = masterTail; + + Object r2 = gwc.invokeExact(o, o, o, o, o, o, o, o, obj1); + assertEquals(r2, obj1); + } + + @Test + public void testVarargsCollectorThrow() throws Throwable { + MethodType t1 = MethodType.methodType(Object.class, Object.class, Object.class, Object.class, Object.class, + Object.class, Object.class, Object.class, Object.class, Object[].class); + + MethodType t2 = t1.insertParameterTypes(0, Exception.class); + + MethodHandle target = LOOKUP.findStatic(TestCatchException.class, "throwEx", t1) + .asVarargsCollector(Object[].class); + MethodHandle catcher = LOOKUP.findStatic(TestCatchException.class, "m2", t2) + .asVarargsCollector(Object[].class); + MethodHandle gwc = MethodHandles.catchException(target, Exception.class, catcher); + + Object o = masterParam; + Object[] obj1 = masterTail; + + Object r2 = gwc.invokeExact(o, o, o, o, o, o, o, o, obj1); + assertEquals(r2, obj1); + } + public static void main(String[] args) throws Throwable { TestCatchException test = new TestCatchException(); test.testNoThrowPath(); test.testThrowPath(); + test.testVarargsCollectorNoThrow(); + test.testVarargsCollectorThrow(); System.out.println("TEST PASSED"); } }
--- a/test/java/lang/invoke/MethodHandlesTest.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/lang/invoke/MethodHandlesTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -2406,108 +2406,6 @@ } @Test - public void testCatchException() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("catchException"); - for (int nargs = 0; nargs < 40; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int throwMode = 0; throwMode < THROW_MODE_LIMIT; throwMode++) { - testCatchException(int.class, new ClassCastException("testing"), throwMode, nargs); - if (CAN_TEST_LIGHTLY && nargs > 3) continue; - testCatchException(void.class, new java.io.IOException("testing"), throwMode, nargs); - testCatchException(String.class, new LinkageError("testing"), throwMode, nargs); - } - } - } - - static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4; - - void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable { - testCatchException(returnType, thrown, throwMode, nargs, 0); - if (nargs <= 5 || nargs % 10 == 3) { - for (int catchDrops = 1; catchDrops <= nargs; catchDrops++) - testCatchException(returnType, thrown, throwMode, nargs, catchDrops); - } - } - - private static <T extends Throwable> - Object throwOrReturn(Object normal, T exception) throws T { - if (exception != null) { - called("throwOrReturn/throw", normal, exception); - throw exception; - } - called("throwOrReturn/normal", normal, exception); - return normal; - } - private int fakeIdentityCount; - private Object fakeIdentity(Object x) { - System.out.println("should throw through this!"); - fakeIdentityCount++; - return x; - } - - void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable { - countTest(); - if (verbosity >= 3) - System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops); - Class<? extends Throwable> exType = thrown.getClass(); - if (throwMode > THROW_CAUGHT) thrown = new UnsupportedOperationException("do not catch this"); - MethodHandle throwOrReturn - = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn", - MethodType.methodType(Object.class, Object.class, Throwable.class)); - if (throwMode == THROW_THROUGH_ADAPTER) { - MethodHandle fakeIdentity - = PRIVATE.findVirtual(MethodHandlesTest.class, "fakeIdentity", - MethodType.methodType(Object.class, Object.class)).bindTo(this); - for (int i = 0; i < 10; i++) - throwOrReturn = MethodHandles.filterReturnValue(throwOrReturn, fakeIdentity); - } - int nargs1 = Math.max(2, nargs); - MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2)); - thrower = addTrailingArgs(thrower, nargs, Object.class); - int catchArgc = 1 + nargs - catchDrops; - MethodHandle catcher = varargsList(catchArgc).asType(MethodType.genericMethodType(catchArgc)); - Object[] args = randomArgs(nargs, Object.class); - Object arg0 = MISSING_ARG; - Object arg1 = (throwMode == THROW_NOTHING) ? (Throwable) null : thrown; - if (nargs > 0) arg0 = args[0]; - if (nargs > 1) args[1] = arg1; - assertEquals(nargs1, thrower.type().parameterCount()); - if (nargs < nargs1) { - Object[] appendArgs = { arg0, arg1 }; - appendArgs = Arrays.copyOfRange(appendArgs, nargs, nargs1); - thrower = MethodHandles.insertArguments(thrower, nargs, appendArgs); - } - assertEquals(nargs, thrower.type().parameterCount()); - MethodHandle target = MethodHandles.catchException(thrower, exType, catcher); - assertEquals(thrower.type(), target.type()); - assertEquals(nargs, target.type().parameterCount()); - //System.out.println("catching with "+target+" : "+throwOrReturn); - Object returned; - try { - returned = target.invokeWithArguments(args); - } catch (Throwable ex) { - assertSame("must get the out-of-band exception", thrown, ex); - if (throwMode <= THROW_CAUGHT) - assertEquals(THROW_UNCAUGHT, throwMode); - returned = ex; - } - assertCalled("throwOrReturn/"+(throwMode == THROW_NOTHING ? "normal" : "throw"), arg0, arg1); - //System.out.println("return from "+target+" : "+returned); - if (throwMode == THROW_NOTHING) { - assertSame(arg0, returned); - } else if (throwMode == THROW_CAUGHT) { - List<Object> catchArgs = new ArrayList<>(Arrays.asList(args)); - // catcher receives an initial subsequence of target arguments: - catchArgs.subList(nargs - catchDrops, nargs).clear(); - // catcher also receives the exception, prepended: - catchArgs.add(0, thrown); - assertEquals(catchArgs, returned); - } - assertEquals(0, fakeIdentityCount); - } - - @Test public void testThrowException() throws Throwable { if (CAN_SKIP_WORKING) return; startTest("throwException");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Arrays/StreamAndSpliterator.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test 8037857 + * @summary tests for stream and spliterator factory methods + * @run testng StreamAndSpliterator + */ + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Spliterators; + +import static org.testng.Assert.assertNotNull; + +public class StreamAndSpliterator { + @Test + public void testStreamNPEs() { + assertThrowsNPE(() -> Arrays.stream((int[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((long[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((double[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.stream((String[]) null, 0, 0)); + } + + @Test + public void testStreamAIOBEs() { + // origin > fence + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 1, 0)); + + // bad origin + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, -1, 0)); + + // bad fence + assertThrowsAIOOB(() -> Arrays.stream(new int[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new long[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new double[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.stream(new String[]{}, 0, 1)); + } + + + @Test + public void testSpliteratorNPEs() { + assertThrowsNPE(() -> Arrays.spliterator((int[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((long[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((double[]) null, 0, 0)); + assertThrowsNPE(() -> Arrays.spliterator((String[]) null, 0, 0)); + } + + @Test + public void testSpliteratorAIOBEs() { + // origin > fence + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 1, 0)); + + // bad origin + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, -1, 0)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, -1, 0)); + + // bad fence + assertThrowsAIOOB(() -> Arrays.spliterator(new int[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new long[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new double[]{}, 0, 1)); + assertThrowsAIOOB(() -> Arrays.spliterator(new String[]{}, 0, 1)); + } + + + @Test + public void testSpliteratorNPEsFromSpliterators() { + assertThrowsNPE(() -> Spliterators.spliterator((int[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((long[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((double[]) null, 0, 0, 0)); + assertThrowsNPE(() -> Spliterators.spliterator((String[]) null, 0, 0, 0)); + } + + @Test + public void testSpliteratorAIOBEsFromSpliterators() { + // origin > fence + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 1, 0, 0)); + + // bad origin + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, -1, 0, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, -1, 0, 0)); + + // bad fence + assertThrowsAIOOB(() -> Spliterators.spliterator(new int[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new long[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new double[]{}, 0, 1, 0)); + assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0)); + } + + void assertThrowsNPE(Runnable r) { + NullPointerException caught = null; + try { + r.run(); + } + catch (NullPointerException e) { + caught = e; + } + assertNotNull(caught, "NullPointerException not thrown"); + } + + void assertThrowsAIOOB(Runnable r) { + ArrayIndexOutOfBoundsException caught = null; + try { + r.run(); + } + catch (ArrayIndexOutOfBoundsException e) { + caught = e; + } + assertNotNull(caught, "ArrayIndexOutOfBoundsException not thrown"); + } +}
--- a/test/java/util/Collection/CollectionDefaults.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/util/Collection/CollectionDefaults.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -44,8 +45,8 @@ import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; +import java.util.function.Function; import java.util.function.Predicate; -import java.util.function.Supplier; /** * @test @@ -59,26 +60,25 @@ public static final Predicate<Integer> pEven = x -> 0 == x % 2; public static final Predicate<Integer> pOdd = x -> 1 == x % 2; - @SuppressWarnings("unchecked") - private static final Supplier<?>[] TEST_CLASSES = { - // Collection - ExtendsAbstractCollection<Integer>::new, + private static final List<Function<Collection<Integer>, Collection<Integer>>> TEST_SUPPLIERS = Arrays.asList( + // Collection + ExtendsAbstractCollection<Integer>::new, - // Lists - java.util.ArrayList<Integer>::new, - java.util.LinkedList<Integer>::new, - java.util.Vector<Integer>::new, - java.util.concurrent.CopyOnWriteArrayList<Integer>::new, - ExtendsAbstractList<Integer>::new, + // Lists + java.util.ArrayList<Integer>::new, + java.util.LinkedList<Integer>::new, + java.util.Vector<Integer>::new, + java.util.concurrent.CopyOnWriteArrayList<Integer>::new, + ExtendsAbstractList<Integer>::new, - // Sets - java.util.HashSet<Integer>::new, - java.util.LinkedHashSet<Integer>::new, - java.util.TreeSet<Integer>::new, - java.util.concurrent.ConcurrentSkipListSet<Integer>::new, - java.util.concurrent.CopyOnWriteArraySet<Integer>::new, - ExtendsAbstractSet<Integer>::new - }; + // Sets + java.util.HashSet<Integer>::new, + java.util.LinkedHashSet<Integer>::new, + java.util.TreeSet<Integer>::new, + java.util.concurrent.ConcurrentSkipListSet<Integer>::new, + java.util.concurrent.CopyOnWriteArraySet<Integer>::new, + ExtendsAbstractSet<Integer>::new + ); private static final int SIZE = 100; @@ -94,7 +94,7 @@ cases.add(new Object[] { new ExtendsAbstractSet<>() }); cases.add(new Object[] { Collections.newSetFromMap(new HashMap<>()) }); - cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap()) }); + cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap<>()) }); cases.add(new Object[] { Collections.newSetFromMap(new TreeMap<>()) }); cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentHashMap<>()) }); cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentSkipListMap<>()) }); @@ -107,24 +107,23 @@ } @Test(dataProvider = "setProvider") - public void testProvidedWithNull(final Set<Integer> set) throws Exception { + public void testProvidedWithNull(final Set<Integer> set) { try { set.forEach(null); fail("expected NPE not thrown"); - } catch (NullPointerException expected) { - ; // expected - } + } catch (NullPointerException expected) { // expected + } try { set.removeIf(null); fail("expected NPE not thrown"); - } catch (NullPointerException expected) { - ; // expected + } catch (NullPointerException expected) { // expected } } @Test - public void testForEach() throws Exception { - final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE); + public void testForEach() { + @SuppressWarnings("unchecked") + final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) { final Collection<Integer> original = test.expected; @@ -133,8 +132,7 @@ try { set.forEach(null); fail("expected NPE not thrown"); - } catch (NullPointerException expected) { - ; // expected + } catch (NullPointerException expected) { // expected } if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) { CollectionAsserts.assertContentsUnordered(set, original, test.toString()); @@ -155,8 +153,9 @@ } @Test - public void testRemoveIf() throws Exception { - final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier((Supplier<Collection<Integer>>[]) TEST_CLASSES, SIZE); + public void testRemoveIf() { + @SuppressWarnings("unchecked") + final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(TEST_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) { final Collection<Integer> original = test.expected; final Collection<Integer> set = test.collection; @@ -164,8 +163,7 @@ try { set.removeIf(null); fail("expected NPE not thrown"); - } catch (NullPointerException expected) { - ; // expected + } catch (NullPointerException expected) { // expected } if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) { CollectionAsserts.assertContentsUnordered(set, original, test.toString());
--- a/test/java/util/Collection/testlibrary/CollectionSupplier.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/util/Collection/testlibrary/CollectionSupplier.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.lang.Integer; import java.lang.Iterable; import java.lang.Override; +import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -36,6 +37,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.function.Function; import java.util.function.Supplier; /** @@ -44,20 +46,24 @@ */ public final class CollectionSupplier<C extends Collection<Integer>> implements Supplier<Iterable<CollectionSupplier.TestCase<C>>> { - private final Supplier<C>[] classes; + private final List<Function<Collection<Integer>, C>> suppliers; private final int size; /** * A Collection test case. */ public static final class TestCase<C extends Collection<Integer>> { - /** * The name of the test case. */ public final String name; /** + * The supplier of a collection + */ + public Function<Collection<Integer>, C> supplier; + + /** * Unmodifiable reference collection, useful for comparisons. */ public final List<Integer> expected; @@ -71,11 +77,11 @@ * Create a Collection test case. * * @param name name of the test case - * @param expected reference collection * @param collection the modifiable test collection */ - public TestCase(String name, C collection) { + public TestCase(String name, Function<Collection<Integer>, C> supplier, C collection) { this.name = name; + this.supplier = supplier; this.expected = Collections.unmodifiableList( Arrays.asList(collection.toArray(new Integer[0]))); this.collection = collection; @@ -107,54 +113,52 @@ } /** - * Create a {@code Supplier} that creates instances of specified collection - * classes of specified length. + * Create a {@code CollectionSupplier} that creates instances of specified + * collection suppliers of the specified size. * - * @param classNames class names that implement {@code Collection} + * @param suppliers the suppliers names that supply {@code Collection} + * instances * @param size the desired size of each collection */ - public CollectionSupplier(Supplier<C>[] classes, int size) { - this.classes = Arrays.copyOf(classes, classes.length); + public CollectionSupplier(List<Function<Collection<Integer>, C>> suppliers, int size) { + this.suppliers = suppliers; this.size = size; } @Override public Iterable<TestCase<C>> get() { final Collection<TestCase<C>> cases = new LinkedList<>(); - for (final Supplier<C> type : classes) { + for (final Function<Collection<Integer>, C> supplier : suppliers) try { - final Collection<Integer> empty = type.get(); - cases.add(new TestCase("empty", empty)); + cases.add(new TestCase<>("empty", supplier, supplier.apply(Collections.emptyList()))); - final Collection<Integer> single = type.get(); - single.add(42); - cases.add(new TestCase("single", single)); + cases.add(new TestCase<>("single", supplier, supplier.apply(Arrays.asList(42)))); - final Collection<Integer> regular = type.get(); + final Collection<Integer> regular = new ArrayList<>(); for (int i = 0; i < size; i++) { regular.add(i); } - cases.add(new TestCase("regular", regular)); + cases.add(new TestCase<>("regular", supplier, supplier.apply(regular))); - final Collection<Integer> reverse = type.get(); + final Collection<Integer> reverse = new ArrayList<>(); for (int i = size; i >= 0; i--) { reverse.add(i); } - cases.add(new TestCase("reverse", reverse)); + cases.add(new TestCase<>("reverse", supplier, supplier.apply(reverse))); - final Collection<Integer> odds = type.get(); + final Collection<Integer> odds = new ArrayList<>(); for (int i = 0; i < size; i++) { odds.add((i * 2) + 1); } - cases.add(new TestCase("odds", odds)); + cases.add(new TestCase<>("odds", supplier, supplier.apply(odds))); - final Collection<Integer> evens = type.get(); + final Collection<Integer> evens = new ArrayList<>(); for (int i = 0; i < size; i++) { evens.add(i * 2); } - cases.add(new TestCase("evens", evens)); + cases.add(new TestCase<>("evens", supplier, supplier.apply(evens))); - final Collection<Integer> fibonacci = type.get(); + final Collection<Integer> fibonacci = new ArrayList<>(); int prev2 = 0; int prev1 = 1; for (int i = 0; i < size; i++) { @@ -166,58 +170,62 @@ prev2 = prev1; prev1 = n; } - cases.add(new TestCase("fibonacci", fibonacci)); + cases.add(new TestCase<>("fibonacci", supplier, supplier.apply(fibonacci))); + - // variants where the size of the backing storage != reported size + boolean isStructurallyModifiable = false; + try { + C t = supplier.apply(Collections.emptyList()); + t.add(1); + isStructurallyModifiable = true; + } catch (UnsupportedOperationException e) { } + + if (!isStructurallyModifiable) + continue; + + + // variants where the size of the backing storage != reported size // created by removing half of the elements - final Collection<Integer> emptyWithSlack = type.get(); + final C emptyWithSlack = supplier.apply(Collections.emptyList()); emptyWithSlack.add(42); assertTrue(emptyWithSlack.remove(42)); - cases.add(new TestCase("emptyWithSlack", emptyWithSlack)); + cases.add(new TestCase<>("emptyWithSlack", supplier, emptyWithSlack)); - final Collection<Integer> singleWithSlack = type.get(); + final C singleWithSlack = supplier.apply(Collections.emptyList()); singleWithSlack.add(42); singleWithSlack.add(43); assertTrue(singleWithSlack.remove(43)); - cases.add(new TestCase("singleWithSlack", singleWithSlack)); + cases.add(new TestCase<>("singleWithSlack", supplier, singleWithSlack)); - final Collection<Integer> regularWithSlack = type.get(); + final C regularWithSlack = supplier.apply(Collections.emptyList()); for (int i = 0; i < (2 * size); i++) { regularWithSlack.add(i); } - assertTrue(regularWithSlack.removeIf((x) -> { - return x >= size; - })); - cases.add(new TestCase("regularWithSlack", regularWithSlack)); + assertTrue(regularWithSlack.removeIf(x -> x < size)); + cases.add(new TestCase<>("regularWithSlack", supplier, regularWithSlack)); - final Collection<Integer> reverseWithSlack = type.get(); + final C reverseWithSlack = supplier.apply(Collections.emptyList()); for (int i = 2 * size; i >= 0; i--) { reverseWithSlack.add(i); } - assertTrue(reverseWithSlack.removeIf((x) -> { - return x < size; - })); - cases.add(new TestCase("reverseWithSlack", reverseWithSlack)); + assertTrue(reverseWithSlack.removeIf(x -> x < size)); + cases.add(new TestCase<>("reverseWithSlack", supplier, reverseWithSlack)); - final Collection<Integer> oddsWithSlack = type.get(); + final C oddsWithSlack = supplier.apply(Collections.emptyList()); for (int i = 0; i < 2 * size; i++) { oddsWithSlack.add((i * 2) + 1); } - assertTrue(oddsWithSlack.removeIf((x) -> { - return x >= size; - })); - cases.add(new TestCase("oddsWithSlack", oddsWithSlack)); + assertTrue(oddsWithSlack.removeIf(x -> x >= size)); + cases.add(new TestCase<>("oddsWithSlack", supplier, oddsWithSlack)); - final Collection<Integer> evensWithSlack = type.get(); + final C evensWithSlack = supplier.apply(Collections.emptyList()); for (int i = 0; i < 2 * size; i++) { evensWithSlack.add(i * 2); } - assertTrue(evensWithSlack.removeIf((x) -> { - return x >= size; - })); - cases.add(new TestCase("evensWithSlack", evensWithSlack)); + assertTrue(evensWithSlack.removeIf(x -> x >= size)); + cases.add(new TestCase<>("evensWithSlack", supplier, evensWithSlack)); - final Collection<Integer> fibonacciWithSlack = type.get(); + final C fibonacciWithSlack = supplier.apply(Collections.emptyList()); prev2 = 0; prev1 = 1; for (int i = 0; i < size; i++) { @@ -229,15 +237,12 @@ prev2 = prev1; prev1 = n; } - assertTrue(fibonacciWithSlack.removeIf((x) -> { - return x < 20; - })); - cases.add(new TestCase("fibonacciWithSlack", - fibonacciWithSlack)); - } catch (Exception failed) { + assertTrue(fibonacciWithSlack.removeIf(x -> x < 20)); + cases.add(new TestCase<>("fibonacciWithSlack", supplier, fibonacciWithSlack)); + } + catch (Exception failed) { throw new TestException(failed); } - } return cases; }
--- a/test/java/util/List/ListDefaults.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/java/util/List/ListDefaults.java Wed Apr 09 12:26:00 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -43,31 +44,45 @@ import java.lang.reflect.Constructor; import java.util.ConcurrentModificationException; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * @test * @summary Unit tests for extension methods on List - * @bug 8023367 + * @bug 8023367 8037106 * @library ../Collection/testlibrary * @build CollectionAsserts CollectionSupplier ExtendsAbstractList * @run testng ListDefaults */ public class ListDefaults { - private static final Supplier<?>[] LIST_CLASSES = { - java.util.ArrayList::new, - java.util.LinkedList::new, - java.util.Vector::new, - java.util.concurrent.CopyOnWriteArrayList::new, - ExtendsAbstractList::new - }; + // Suppliers of lists that can support structural modifications + private static final List<Function<Collection, List>> LIST_STRUCT_MOD_SUPPLIERS = Arrays.asList( + java.util.ArrayList::new, + java.util.LinkedList::new, + java.util.Vector::new, + java.util.concurrent.CopyOnWriteArrayList::new, + ExtendsAbstractList::new + ); - private static final Supplier<?>[] LIST_CME_CLASSES = { - java.util.ArrayList::new, - java.util.Vector::new - }; + // Suppliers of lists that can support in place modifications + private static final List<Function<Collection, List>> LIST_SUPPLIERS = Arrays.asList( + java.util.ArrayList::new, + java.util.LinkedList::new, + java.util.Vector::new, + java.util.concurrent.CopyOnWriteArrayList::new, + ExtendsAbstractList::new, + c -> Arrays.asList(c.toArray()) + ); + + // Suppliers of lists supporting CMEs + private static final List<Function<Collection, List>> LIST_CME_SUPPLIERS = Arrays.asList( + java.util.ArrayList::new, + java.util.Vector::new + ); private static final Predicate<Integer> pEven = x -> 0 == x % 2; private static final Predicate<Integer> pOdd = x -> 1 == x % 2; @@ -83,17 +98,13 @@ private static final int SUBLIST_TO = SIZE - 5; private static final int SUBLIST_SIZE = SUBLIST_TO - SUBLIST_FROM; - private static interface Callback { - void call(List<Integer> list); - } - // call the callback for each recursive subList - private void trimmedSubList(final List<Integer> list, final Callback callback) { + private void trimmedSubList(final List<Integer> list, final Consumer<List<Integer>> callback) { int size = list.size(); if (size > 1) { // trim 1 element from both ends final List<Integer> subList = list.subList(1, size - 1); - callback.call(subList); + callback.accept(subList); trimmedSubList(subList, callback); } } @@ -107,17 +118,21 @@ cases.add(new Object[] { new Vector<>() }); cases.add(new Object[] { new Stack<>() }); cases.add(new Object[] { new CopyOnWriteArrayList<>() }); + cases.add(new Object[] { Arrays.asList() }); - cases.add(new Object[] { new ArrayList(){{add(42);}} }); - cases.add(new Object[] { new LinkedList(){{add(42);}} }); - cases.add(new Object[] { new Vector(){{add(42);}} }); - cases.add(new Object[] { new Stack(){{add(42);}} }); - cases.add(new Object[] { new CopyOnWriteArrayList(){{add(42);}} }); + List<Integer> l = Arrays.asList(42); + cases.add(new Object[] { new ArrayList<>(l) }); + cases.add(new Object[] { new LinkedList<>(l) }); + cases.add(new Object[] { new Vector<>(l) }); + Stack<Integer> s = new Stack<>(); s.addAll(l); + cases.add(new Object[]{s}); + cases.add(new Object[] { new CopyOnWriteArrayList<>(l) }); + cases.add(new Object[] { l }); return cases.toArray(new Object[0][cases.size()]); } @Test(dataProvider = "listProvider") - public void testProvidedWithNull(final List<Integer> list) throws Exception { + public void testProvidedWithNull(final List<Integer> list) { try { list.forEach(null); fail("expected NPE not thrown"); @@ -138,11 +153,12 @@ } @Test - public void testForEach() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE); + public void testForEach() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; try { list.forEach(null); @@ -165,23 +181,21 @@ } } - trimmedSubList(list, new Callback() { - @Override - public void call(final List<Integer> list) { - final List<Integer> actual = new LinkedList<>(); - list.forEach(actual::add); - CollectionAsserts.assertContents(actual, list); - } - }); + trimmedSubList(list, l -> { + final List<Integer> a = new LinkedList<>(); + l.forEach(a::add); + CollectionAsserts.assertContents(a, l); + }); } } @Test - public void testRemoveIf() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE); + public void testRemoveIf() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_STRUCT_MOD_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; try { list.removeIf(null); @@ -195,9 +209,9 @@ } } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; list.removeIf(pOdd); for (int i : list) { assertTrue((i % 2) == 0); @@ -211,9 +225,9 @@ assertTrue(list.isEmpty()); } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; final List<Integer> listCopy = new ArrayList<>(list); if (original.size() > SUBLIST_SIZE) { final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO); @@ -237,22 +251,19 @@ } } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); - trimmedSubList(list, new Callback() { - @Override - public void call(final List<Integer> list) { - final List<Integer> copy = new ArrayList<>(list); - list.removeIf(pOdd); - for (int i : list) { - assertTrue((i % 2) == 0); - } - for (int i : copy) { - if (i % 2 == 0) { - assertTrue(list.contains(i)); - } else { - assertFalse(list.contains(i)); - } + for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { + final List<Integer> list = test.collection; + trimmedSubList(list, l -> { + final List<Integer> copy = new ArrayList<>(l); + l.removeIf(pOdd); + for (int i : l) { + assertTrue((i % 2) == 0); + } + for (int i : copy) { + if (i % 2 == 0) { + assertTrue(l.contains(i)); + } else { + assertFalse(l.contains(i)); } } }); @@ -267,12 +278,13 @@ } @Test - public void testReplaceAll() throws Exception { + public void testReplaceAll() { final int scale = 3; - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE); + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; try { list.replaceAll(null); @@ -281,7 +293,7 @@ CollectionAsserts.assertContents(list, original); list.replaceAll(x -> scale * x); - for (int i=0; i < original.size(); i++) { + for (int i = 0; i < original.size(); i++) { assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i); } @@ -306,28 +318,26 @@ } } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); - trimmedSubList(list, new Callback() { - @Override - public void call(final List<Integer> list) { - final List<Integer> copy = new ArrayList<>(list); - final int offset = 5; - list.replaceAll(x -> offset + x); - for (int i=0; i < copy.size(); i++) { - assertTrue(list.get(i) == (offset + copy.get(i)), "mismatch at index " + i); - } + for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { + final List<Integer> list = test.collection; + trimmedSubList(list, l -> { + final List<Integer> copy = new ArrayList<>(l); + final int offset = 5; + l.replaceAll(x -> offset + x); + for (int i = 0; i < copy.size(); i++) { + assertTrue(l.get(i) == (offset + copy.get(i)), "mismatch at index " + i); } }); } } @Test - public void testSort() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CLASSES, SIZE); + public void testSort() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> original = test.expected; + final List<Integer> list = test.collection; CollectionSupplier.shuffle(list); list.sort(Integer::compare); CollectionAsserts.assertSorted(list, Integer::compare); @@ -338,23 +348,23 @@ CollectionSupplier.shuffle(list); list.sort(null); - CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder()); + CollectionAsserts.assertSorted(list, Comparator.naturalOrder()); if (test.name.startsWith("reverse")) { Collections.reverse(list); } CollectionAsserts.assertContents(list, original); CollectionSupplier.shuffle(list); - list.sort(Comparator.<Integer>naturalOrder()); - CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder()); + list.sort(Comparator.naturalOrder()); + CollectionAsserts.assertSorted(list, Comparator.naturalOrder()); if (test.name.startsWith("reverse")) { Collections.reverse(list); } CollectionAsserts.assertContents(list, original); CollectionSupplier.shuffle(list); - list.sort(Comparator.<Integer>reverseOrder()); - CollectionAsserts.assertSorted(list, Comparator.<Integer>reverseOrder()); + list.sort(Comparator.reverseOrder()); + CollectionAsserts.assertSorted(list, Comparator.reverseOrder()); if (!test.name.startsWith("reverse")) { Collections.reverse(list); } @@ -365,32 +375,35 @@ CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR); // check sort by verifying that bitCount increases and never drops int minBitCount = 0; - int bitCount = 0; for (final Integer i : list) { - bitCount = Integer.bitCount(i); + int bitCount = Integer.bitCount(i); assertTrue(bitCount >= minBitCount); minBitCount = bitCount; } + // Resuse the supplier to store AtomicInteger instead of Integer + // Hence the use of raw type and cast + List<AtomicInteger> incomparablesData = new ArrayList<>(); + for (int i = 0; i < test.expected.size(); i++) { + incomparablesData.add(new AtomicInteger(i)); + } + Function f = test.supplier; @SuppressWarnings("unchecked") - final Constructor<? extends List<?>> defaultConstructor = ((Class<? extends List<?>>)test.collection.getClass()).getConstructor(); - final List<AtomicInteger> incomparables = (List<AtomicInteger>) defaultConstructor.newInstance(); + List<AtomicInteger> incomparables = (List<AtomicInteger>) f.apply(incomparablesData); - for (int i=0; i < test.expected.size(); i++) { - incomparables.add(new AtomicInteger(i)); - } CollectionSupplier.shuffle(incomparables); incomparables.sort(ATOMIC_INTEGER_COMPARATOR); - for (int i=0; i < test.expected.size(); i++) { + for (int i = 0; i < test.expected.size(); i++) { assertEquals(i, incomparables.get(i).intValue()); } + if (original.size() > SUBLIST_SIZE) { final List<Integer> copy = new ArrayList<>(list); final List<Integer> subList = list.subList(SUBLIST_FROM, SUBLIST_TO); CollectionSupplier.shuffle(subList); - subList.sort(Comparator.<Integer>naturalOrder()); - CollectionAsserts.assertSorted(subList, Comparator.<Integer>naturalOrder()); + subList.sort(Comparator.naturalOrder()); + CollectionAsserts.assertSorted(subList, Comparator.naturalOrder()); // verify that elements [0, from) remain unmodified for (int i = 0; i < SUBLIST_FROM; i++) { assertTrue(list.get(i) == copy.get(i), @@ -404,25 +417,22 @@ } } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); - trimmedSubList(list, new Callback() { - @Override - public void call(final List<Integer> list) { - final List<Integer> copy = new ArrayList<>(list); - CollectionSupplier.shuffle(list); - list.sort(Comparator.<Integer>naturalOrder()); - CollectionAsserts.assertSorted(list, Comparator.<Integer>naturalOrder()); - } + for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { + final List<Integer> list = test.collection; + trimmedSubList(list, l -> { + CollectionSupplier.shuffle(l); + l.sort(Comparator.naturalOrder()); + CollectionAsserts.assertSorted(l, Comparator.naturalOrder()); }); } } @Test - public void testForEachThrowsCME() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE); + public void testForEachThrowsCME() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> list = test.collection; if (list.size() <= 1) { continue; @@ -430,7 +440,7 @@ boolean gotException = false; try { // bad predicate that modifies its list, should throw CME - list.forEach((x) -> {list.add(x);}); + list.forEach(list::add); } catch (ConcurrentModificationException cme) { gotException = true; } @@ -441,11 +451,11 @@ } @Test - public void testRemoveIfThrowsCME() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE); + public void testRemoveIfThrowsCME() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> original = ((List<Integer>) test.expected); - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> list = test.collection; if (list.size() <= 1) { continue; @@ -453,7 +463,7 @@ boolean gotException = false; try { // bad predicate that modifies its list, should throw CME - list.removeIf((x) -> {return list.add(x);}); + list.removeIf(list::add); } catch (ConcurrentModificationException cme) { gotException = true; } @@ -464,10 +474,11 @@ } @Test - public void testReplaceAllThrowsCME() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE); + public void testReplaceAllThrowsCME() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> list = test.collection; if (list.size() <= 1) { continue; @@ -486,10 +497,11 @@ } @Test - public void testSortThrowsCME() throws Exception { - final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier((Supplier<List<Integer>>[])LIST_CME_CLASSES, SIZE); + public void testSortThrowsCME() { + @SuppressWarnings("unchecked") + final CollectionSupplier<List<Integer>> supplier = new CollectionSupplier(LIST_CME_SUPPLIERS, SIZE); for (final CollectionSupplier.TestCase<List<Integer>> test : supplier.get()) { - final List<Integer> list = ((List<Integer>) test.collection); + final List<Integer> list = test.collection; if (list.size() <= 1) { continue; @@ -523,7 +535,7 @@ } @Test(dataProvider = "shortIntListProvider") - public void testRemoveIfFromSlice(final List<Integer> list) throws Exception { + public void testRemoveIfFromSlice(final List<Integer> list) { final List<Integer> sublist = list.subList(3, 6); assertTrue(sublist.removeIf(x -> x == 4)); CollectionAsserts.assertContents(list, SLICED_EXPECTED);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JComboBox/8032878/bug8032878.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8032878 + * @summary Checks that JComboBox as JTable cell editor processes key events + * even where setSurrendersFocusOnKeystroke flag in JTable is false and + * that it does not lose the first key press where the flag is true. + * @library ../../regtesthelpers + * @build Util + * @author Alexey Ivanov + */ + +import java.awt.*; +import java.awt.event.KeyEvent; +import javax.swing.*; +import javax.swing.text.JTextComponent; + +import sun.awt.SunToolkit; + +public class bug8032878 implements Runnable { + private static final String ONE = "one"; + private static final String TWO = "two"; + private static final String THREE = "three"; + + private static final String EXPECTED = "one123"; + + private final Robot robot; + + private JFrame frame; + private JComboBox cb; + + private volatile boolean surrender; + private volatile String text; + + public static void main(String[] args) throws Exception { + final bug8032878 test = new bug8032878(); + + test.test(false); + test.test(true); + } + + public bug8032878() throws AWTException { + robot = new Robot(); + robot.setAutoDelay(100); + } + + private void setupUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JTable table = new JTable(new String[][] {{ONE}, {TWO}, {THREE}}, + new String[] { "#"}); + table.setSurrendersFocusOnKeystroke(surrender); + + cb = new JComboBox(new String[]{ONE, TWO, THREE}); + cb.setEditable(true); + DefaultCellEditor comboEditor = new DefaultCellEditor(cb); + comboEditor.setClickCountToStart(1); + table.getColumnModel().getColumn(0).setCellEditor(comboEditor); + frame.add(table); + + frame.pack(); + frame.setVisible(true); + } + + private void test(final boolean flag) throws Exception { + try { + surrender = flag; + SwingUtilities.invokeAndWait(this); + + runTest(); + checkResult(); + } finally { + if (frame != null) { + frame.dispose(); + } + } + } + + private void runTest() throws Exception { + realSync(); + // Select 'one' + Util.hitKeys(robot, KeyEvent.VK_TAB); + realSync(); + Util.hitKeys(robot, KeyEvent.VK_1); + Util.hitKeys(robot, KeyEvent.VK_2); + Util.hitKeys(robot, KeyEvent.VK_3); + Util.hitKeys(robot, KeyEvent.VK_ENTER); + realSync(); + } + + private void checkResult() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + text = ((JTextComponent) cb.getEditor().getEditorComponent()).getText(); + } + }); + if (text.equals(EXPECTED)) { + System.out.println("Test with surrender = " + surrender + " passed"); + } else { + System.out.println("Test with surrender = " + surrender + " failed"); + throw new RuntimeException("Expected value in JComboBox editor '" + + EXPECTED + "' but found '" + text + "'."); + } + } + + private static void realSync() { + ((SunToolkit) (Toolkit.getDefaultToolkit())).realSync(); + } + + @Override + public void run() { + setupUI(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/text/GlyphView/4984669/bug4984669.html Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,30 @@ +<html> +<!-- + Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<body> +<applet code="bug4984669.class" width=300 height=300></applet> +The four lines printed above in a bold typeface should all be underlined. +It is a bug if any of these lines is underlined only partially. +The very first line should not be underlined at all. +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/text/GlyphView/4984669/bug4984669.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4984669 8002148 + @summary Tests HTML underlining + @author Peter Zhelezniakov + @run applet/manual=yesno bug4984669.html +*/ +import javax.swing.*; +import javax.swing.text.*; + +public class bug4984669 extends JApplet +{ + public void init() { + JEditorPane pane = new JEditorPane(); + this.getContentPane().add(new JScrollPane(pane)); + pane.setEditorKit(new StyledEditorKit()); + + try { + pane.getDocument().insertString(0,"12 \n",null); + MutableAttributeSet attrs = new SimpleAttributeSet(); + + StyleConstants.setFontSize(attrs, 36); + StyleConstants.setBold(attrs, true); + StyleConstants.setUnderline(attrs, true); + pane.getDocument().insertString(6, "aa\n", attrs); + pane.getDocument().insertString(9, "bbb\n", attrs); + pane.getDocument().insertString(13, "cccc\n", attrs); + pane.getDocument().insertString(18, "ddddd\n", attrs); + } catch (Exception e) { + throw new Error("Failed: Unexpected Exception", e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/text/html/8034955/bug8034955.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8034955 + * @author Alexander Scherbatiy + * @summary JLabel/JToolTip throw ClassCastException for "<html>a<title>" + * @run main bug8034955 + */ +public class bug8034955 { + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + JFrame frame = new JFrame(); + frame.getContentPane().add(new JLabel("<html>a<title>")); + frame.pack(); + frame.setVisible(true); + } + }); + } +}
--- a/test/lib/testlibrary/jdk/testlibrary/Asserts.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/lib/testlibrary/jdk/testlibrary/Asserts.java Wed Apr 09 12:26:00 2014 -0700 @@ -23,6 +23,8 @@ package jdk.testlibrary; +import java.util.Objects; + /** * Asserts that can be used for verifying assumptions in tests. * @@ -171,6 +173,34 @@ } /** + * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertSame(Object, Object, String) + */ + public static void assertSame(Object lhs, Object rhs) { + assertSame(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is the same as {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertSame(Object lhs, Object rhs, String msg) { + if (lhs != rhs) { + msg = Objects.toString(msg, "assertSame") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + throw new RuntimeException(msg); + } + } + + /** * Shorthand for {@link #assertGreaterThanOrEqual(T, T)}. * * @see #assertGreaterThanOrEqual(T, T)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.testlibrary.jsr292; + +import jdk.testlibrary.Asserts; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.*; + +public class Helper { + /** Flag for verbose output, true if {@code -Dverbose} specified */ + public static final boolean IS_VERBOSE + = System.getProperty("verbose") != null; + /** + * Flag for thorough testing -- all test will be executed, + * true if {@code -Dthorough} specified. */ + public static final boolean IS_THOROUGH + = System.getProperty("thorough") != null; + /** Random number generator w/ initial seed equal to {@code -Dseed} */ + public static final Random RNG; + + static { + String str = System.getProperty("seed"); + long seed = str != null ? Long.parseLong(str) : new Random().nextLong(); + RNG = new Random(seed); + System.out.printf("-Dseed=%d%n", seed); + } + + public static final long TEST_LIMIT; + static { + String str = System.getProperty("testLimit"); + TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L; + System.out.printf("-DtestLimit=%d%n", TEST_LIMIT); + } + + public static final int MAX_ARITY = 254; + public static final String MISSING_ARG = "missingArg"; + public static final String MISSING_ARG_2 = "missingArg#2"; + + private static final int + // first int value + ONE_MILLION = (1000 * 1000), + // scale factor to reach upper 32 bits + TEN_BILLION = (10 * 1000 * 1000 * 1000), + // <<1 makes space for sign bit; + INITIAL_ARG_VAL = ONE_MILLION << 1; + + public static final MethodHandle AS_LIST; + + static { + try { + AS_LIST = MethodHandles.lookup().findStatic( + Arrays.class, "asList", + MethodType.methodType(List.class, Object[].class)); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new Error(ex); + } + } + + public static boolean isDoubleCost(Class<?> aClass) { + return aClass == double.class || aClass == long.class; + } + + private static List<List<Object>> calledLog = new ArrayList<>(); + private static long nextArgVal; + + public static void assertCalled(String name, Object... args) { + assertCalled(0, name, args); + } + + public static void assertCalled(int lag, String name, Object... args) { + Object expected = logEntry(name, args); + Object actual = getCalled(lag); + Asserts.assertEQ(expected, actual, "method call w/ lag = " + lag); + } + + public static Object called(String name, Object... args) { + List<Object> entry = logEntry(name, args); + calledLog.add(entry); + return entry; + } + + private static List<Object> logEntry(String name, Object... args) { + return Arrays.asList(name, Arrays.asList(args)); + } + + public static void clear() { + calledLog.clear(); + } + + public static List<Object> getCalled(int lag) { + int size = calledLog.size(); + return size <= lag ? null : calledLog.get(size - lag - 1); + } + + public static MethodHandle addTrailingArgs(MethodHandle target, int nargs, + List<Class<?>> classes) { + int targetLen = target.type().parameterCount(); + int extra = (nargs - targetLen); + if (extra <= 0) { + return target; + } + List<Class<?>> fakeArgs = new ArrayList<>(extra); + for (int i = 0; i < extra; ++i) { + fakeArgs.add(classes.get(i % classes.size())); + } + return MethodHandles.dropArguments(target, targetLen, fakeArgs); + } + + public static MethodHandle varargsList(int arity) { + return AS_LIST.asCollector(Object[].class, arity); + } + + private static long nextArg(boolean moreBits) { + long val = nextArgVal++; + long sign = -(val & 1); // alternate signs + val >>= 1; + if (moreBits) + // Guarantee some bits in the high word. + // In any case keep the decimal representation simple-looking, + // with lots of zeroes, so as not to make the printed decimal + // strings unnecessarily noisy. + { + val += (val % ONE_MILLION) * TEN_BILLION; + } + return val ^ sign; + } + + private static int nextArg() { + // Produce a 32-bit result something like ONE_MILLION+(smallint). + // Example: 1_000_042. + return (int) nextArg(false); + } + + private static long nextArg(Class<?> kind) { + if (kind == long.class || kind == Long.class || + kind == double.class || kind == Double.class) + // produce a 64-bit result something like + // ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) + // Example: 10_000_420_001_000_042. + { + return nextArg(true); + } + return (long) nextArg(); + } + + private static Object randomArg(Class<?> param) { + Object wrap = castToWrapperOrNull(nextArg(param), param); + if (wrap != null) { + return wrap; + } + + if (param.isInterface()) { + for (Class<?> c : param.getClasses()) { + if (param.isAssignableFrom(c) && !c.isInterface()) { + param = c; + break; + } + } + } + if (param.isArray()) { + Class<?> ctype = param.getComponentType(); + Object arg = Array.newInstance(ctype, 2); + Array.set(arg, 0, randomArg(ctype)); + return arg; + } + if (param.isInterface() && param.isAssignableFrom(List.class)) { + return Arrays.asList("#" + nextArg()); + } + if (param.isInterface() || param.isAssignableFrom(String.class)) { + return "#" + nextArg(); + } + + try { + return param.newInstance(); + } catch (InstantiationException | IllegalAccessException ex) { + } + return null; // random class not Object, String, Integer, etc. + } + + public static Object[] randomArgs(Class<?>... params) { + Object[] args = new Object[params.length]; + for (int i = 0; i < args.length; i++) { + args[i] = randomArg(params[i]); + } + return args; + } + + public static Object[] randomArgs(int nargs, Class<?> param) { + Object[] args = new Object[nargs]; + for (int i = 0; i < args.length; i++) { + args[i] = randomArg(param); + } + return args; + } + + public static Object[] randomArgs(int nargs, Class<?>... params) { + Object[] args = new Object[nargs]; + for (int i = 0; i < args.length; i++) { + Class<?> param = params[i % params.length]; + args[i] = randomArg(param); + } + return args; + } + + public static Object[] randomArgs(List<Class<?>> params) { + return randomArgs(params.toArray(new Class<?>[params.size()])); + } + + private static Object castToWrapper(Object value, Class<?> dst) { + Object wrap = null; + if (value instanceof Number) { + wrap = castToWrapperOrNull(((Number) value).longValue(), dst); + } + if (value instanceof Character) { + wrap = castToWrapperOrNull((char) (Character) value, dst); + } + if (wrap != null) { + return wrap; + } + return dst.cast(value); + } + + @SuppressWarnings("cast") + // primitive cast to (long) is part of the pattern + private static Object castToWrapperOrNull(long value, Class<?> dst) { + if (dst == int.class || dst == Integer.class) { + return (int) (value); + } + if (dst == long.class || dst == Long.class) { + return (long) (value); + } + if (dst == char.class || dst == Character.class) { + return (char) (value); + } + if (dst == short.class || dst == Short.class) { + return (short) (value); + } + if (dst == float.class || dst == Float.class) { + return (float) (value); + } + if (dst == double.class || dst == Double.class) { + return (double) (value); + } + if (dst == byte.class || dst == Byte.class) { + return (byte) (value); + } + if (dst == boolean.class || dst == boolean.class) { + return ((value % 29) & 1) == 0; + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/java2d/DrawXORModeTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8036022 + * @summary Test verifies that drawing shapes with XOR composite + * does not trigger an InternalError in GDI surface data. + * @run main/othervm -Dsun.java2d.d3d=True DrawXORModeTest + */ +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Stroke; +import java.awt.geom.Line2D; +import java.util.concurrent.CountDownLatch; + +public class DrawXORModeTest extends Component { + + public static void main(String[] args) { + final DrawXORModeTest c = new DrawXORModeTest(); + + final Frame f = new Frame("XOR mode test"); + f.add(c); + f.pack(); + + f.setVisible(true); + + try { + c.checkResult(); + } finally { + f.dispose(); + } + } + + @Override + public void paint(Graphics g) { + if (g == null || !(g instanceof Graphics2D)) { + return; + } + g.setColor(Color.white); + g.setXORMode(Color.black); + Graphics2D dg = (Graphics2D) g; + Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 10.0f, + new float[]{1.0f, 1.0f}, + 0.0f); + dg.setStroke(stroke); + try { + dg.draw(new Line2D.Float(10, 10, 20, 20)); + } catch (Throwable e) { + synchronized (this) { + theError = e; + } + } finally { + didDraw.countDown(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(400, 100); + } + + public void checkResult() { + try { + didDraw.await(); + } catch (InterruptedException e) { + } + + synchronized (this) { + if (theError != null) { + System.out.println("Error: " + theError); + + throw new RuntimeException("Test FAILED."); + } + } + System.out.println("Test PASSED."); + + } + + private Throwable theError = null; + + private final CountDownLatch didDraw = new CountDownLatch(1); +}
--- a/test/sun/security/krb5/auto/BadKdc.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/security/krb5/auto/BadKdc.java Wed Apr 09 12:26:00 2014 -0700 @@ -39,7 +39,29 @@ // ^ kdc# ^ timeout static final Pattern re = Pattern.compile( ">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " + - "timeout=(\\d)000,"); + "timeout=(\\d+),"); + + // Ratio for timeout values of all timeout tests. Not final so that + // each test can choose their own. + static float ratio = 2f; + + static void setRatio(float ratio) { + BadKdc.ratio = ratio; + } + + static float getRatio() { + return ratio; + } + + // Gets real timeout value. This method is called when writing krb5.conf + static int toReal(int from) { + return (int)(from * ratio + .5); + } + + // De-ratio a millisecond value to second + static int toSymbolicSec(int from) { + return (int)(from / ratio / 1000f + 0.5); + } /* * There are several cases this test fails: @@ -101,7 +123,7 @@ fw.write("[libdefaults]\n" + "default_realm = " + OneKDC.REALM + "\n" + - "kdc_timeout = 2000\n"); + "kdc_timeout = " + toReal(2000) + "\n"); fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" + @@ -184,7 +206,8 @@ Matcher m = re.matcher(line); if (m.find()) { System.out.println(line); - sb.append(m.group(1)).append(m.group(2)); + sb.append(m.group(1)) + .append(toSymbolicSec(Integer.parseInt(m.group(2)))); } } if (failed) sb.append('-');
--- a/test/sun/security/krb5/auto/BadKdc1.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/security/krb5/auto/BadKdc1.java Wed Apr 09 12:26:00 2014 -0700 @@ -28,14 +28,21 @@ * @summary krb5 should not try to access unavailable kdc too often */ -import java.io.*; import java.security.Security; public class BadKdc1 { public static void main(String[] args) throws Exception { - Security.setProperty("krb5.kdc.bad.policy", "tryLess"); + + // 5 sec is default timeout for tryLess + if (BadKdc.getRatio() > 2.5) { + Security.setProperty("krb5.kdc.bad.policy", + "tryLess:1," + BadKdc.toReal(2000)); + } else { + Security.setProperty("krb5.kdc.bad.policy", "tryLess"); + } + BadKdc.go( "121212222222(32){1,2}1222(32){1,2}", // 1 2 // The above line means try kdc1 for 2 seconds then kdc1
--- a/test/sun/security/krb5/auto/BadKdc2.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/security/krb5/auto/BadKdc2.java Wed Apr 09 12:26:00 2014 -0700 @@ -35,7 +35,12 @@ public static void main(String[] args) throws Exception { - Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000"); + + // 1 sec is too short. + BadKdc.setRatio(3.0f); + + Security.setProperty( + "krb5.kdc.bad.policy", "tryLess:2," + BadKdc.toReal(1000)); BadKdc.go( "121212222222(32){1,2}11112121(32){1,2}", // 1 2 "11112121(32){1,2}11112121(32){1,2}", // 1 2
--- a/test/sun/security/krb5/auto/MaxRetries.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/security/krb5/auto/MaxRetries.java Wed Apr 09 12:26:00 2014 -0700 @@ -60,7 +60,7 @@ test1(5000, 2); // 2 2 // For tryLess - Security.setProperty("krb5.kdc.bad.policy", "tryless"); + Security.setProperty("krb5.kdc.bad.policy", "tryless:1," + BadKdc.toReal(5000)); rewriteMaxRetries(4); test1(4000, 7); // 1 1 1 1 2 1 2 test1(4000, 4); // 1 2 1 2 @@ -94,7 +94,7 @@ * @param count the expected total try */ private static void test1(int timeout, int count) throws Exception { - String timeoutTag = "timeout=" + timeout; + String timeoutTag = "timeout=" + BadKdc.toReal(timeout); ByteArrayOutputStream bo = new ByteArrayOutputStream(); PrintStream oldout = System.out; System.setOut(new PrintStream(bo)); @@ -192,12 +192,12 @@ if (s.startsWith("[realms]")) { // Reconfig global setting fw.write("max_retries = 2\n"); - fw.write("kdc_timeout = 5000\n"); + fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n"); } else if (s.trim().startsWith("kdc = ")) { if (value != -1) { // Reconfig for realm fw.write(" max_retries = " + value + "\n"); - fw.write(" kdc_timeout = " + (value*1000) + "\n"); + fw.write(" kdc_timeout = " + BadKdc.toReal(value*1000) + "\n"); } // Add a bad KDC as the first candidate fw.write(" kdc = localhost:33333\n");
--- a/test/sun/security/krb5/auto/TcpTimeout.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/security/krb5/auto/TcpTimeout.java Wed Apr 09 12:26:00 2014 -0700 @@ -63,7 +63,7 @@ "udp_preference_limit = 1\n" + "max_retries = 2\n" + "default_realm = " + OneKDC.REALM + "\n" + - "kdc_timeout = 5000\n"); + "kdc_timeout = " + BadKdc.toReal(5000) + "\n"); fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/krb5/config/ExtraLines.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8036971 + * @compile -XDignore.symbol.file ExtraLines.java + * @run main/othervm ExtraLines + * @summary krb5.conf does not accept directive lines before the first section + */ + +import sun.security.krb5.Config; +import java.nio.file.*; +import java.util.Objects; + +public class ExtraLines { + public static void main(String[] args) throws Exception { + Path base = Paths.get("krb5.conf"); + Path include = Paths.get("included.conf"); + String baseConf = "include " + include.toAbsolutePath().toString() + + "\n[x]\na = b\n"; + String includeConf = "[y]\nc = d\n"; + Files.write(include, includeConf.getBytes()); + Files.write(base, baseConf.getBytes()); + + System.setProperty("java.security.krb5.conf", base.toString()); + Config.refresh(); + + if (!Objects.equals(Config.getInstance().get("x", "a"), "b")) { + throw new Exception("Failed"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/provider/certpath/PKIXCertPathValidator/Validity.java Wed Apr 09 12:26:00 2014 -0700 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/** + * @test + * @bug 8021804 + * @summary CertPath should validate even if the validity period of the + * root cert does not include the validity period of a subordinate + * cert. + */ + +import java.io.ByteArrayInputStream; +import java.security.cert.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class Validity { + + /* + * Subject: OU=TestOrg, CN=TestCA + * Issuer: OU=TestOrg, CN=TestCA + * Validity + * Not Before: Feb 26 21:33:55 2014 GMT + Not After : Feb 26 21:33:55 2024 GMT + * Version 1 + */ + static String CACertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvTCCASYCCQCQRiTo4lBCFjANBgkqhkiG9w0BAQUFADAjMRAwDgYDVQQLDAdU\n" + + "ZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTQwMjI2MjEzMzU1WhcNMjQwMjI2\n" + + "MjEzMzU1WjAjMRAwDgYDVQQLDAdUZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwgZ8w\n" + + "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOtKS4ZrsM3ansd61ZxitcrN0w184I+A\n" + + "z0kyrSP1eMtlam+cC2U91NpTz11FYV4XUfBhqqxaXW043AWTUer8pS90Pt4sCrUX\n" + + "COx1+QA1M3ZhbZ4sTM7XQ90JbGaBJ/sEza9mlQP7hQ2yQO/hATKbP6J5qvgG2sT2\n" + + "S2WYjEgwNwmFAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQ/CXEpnx2WY4LJtv4jwE\n" + + "4jIVirur3pdzV5oBhPyqqHMsyhQBkukCfX7uD7L5wN1+xuM81DfANpIxlnUfybp5\n" + + "CpjcmktLpmyK4kJ6XnSd2blbLOIpsr9x6FqxPxpVDlyw/ySHYrIG/GZdsLHgmzGn\n" + + "B06jeYzH8OLf879VxAxSsPc=\n" + + "-----END CERTIFICATE-----"; + + /* + * Subject: OU=TestOrg, CN=TestEE0 + * Issuer: OU=TestOrg, CN=TestCA + * Validity + * Not Before: Feb 26 22:55:12 2014 GMT + * Not After : Feb 25 22:55:12 2025 GMT + * Version 1 + */ + static String EECertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIIBtjCCAR8CAQQwDQYJKoZIhvcNAQEFBQAwIzEQMA4GA1UECwwHVGVzdE9yZzEP\n" + + "MA0GA1UEAwwGVGVzdENBMB4XDTE0MDIyNjIyNTUxMloXDTI1MDIyNTIyNTUxMlow\n" + + "JDEQMA4GA1UECwwHVGVzdE9yZzEQMA4GA1UEAwwHVGVzdEVFMDCBnzANBgkqhkiG\n" + + "9w0BAQEFAAOBjQAwgYkCgYEAt8xz9W3ruCTHjSOtTX6cxsUZ0nRP6EavEfzgcOYh\n" + + "CXGA0gr+viSHq3c2vQBxiRny2hm5rLcqpPo+2OxZtw/ajxfyrV6d/r8YyQLBvyl3\n" + + "xdCZdOkG1DCM1oFAQDaSRt9wN5Zm5kyg7uMig5Y4L45fP9Yee4x6Xyh36qYbsR89\n" + + "rFMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDZrPqSo08va1m9TOWOztTuWilGdjK/\n" + + "2Ed2WXg8utIpy6uAV+NaOYtHQ7ULQBVRNmwg9nKghbVbh+E/xpoihjl1x7OXass4\n" + + "TbwXA5GKFIFpNtDvATQ/QQZoCuCzw1FW/mH0Q7UEQ/9/iJdDad6ebkapeMwtj/8B\n" + + "s2IZV7s85CEOXw==\n" + + "-----END CERTIFICATE-----"; + + public static void main(String[] args) throws Exception { + + String[] certStrs = {EECertStr}; + String[] trustedCertStrs = {CACertStr}; + runTest(certStrs, trustedCertStrs); + + System.out.println("Test passed."); + } + + private static void runTest(String[] certStrs, + String[] trustedCertStrs) + throws Exception { + + CertificateFactory cf = CertificateFactory.getInstance("X509"); + + // Generate the CertPath from the certs named in certStrs + ArrayList<X509Certificate> certs = new ArrayList<>(); + for (String certStr : certStrs) { + certs.add(generateCert(certStr, cf)); + } + CertPath cp = cf.generateCertPath(certs); + + // Generate the set of Trust Anchors from the certs named in + // trustedCertStrs + Set<TrustAnchor> trustAnchors = new HashSet<>(); + for (String trustedCertStr : trustedCertStrs) { + TrustAnchor ta = new TrustAnchor(generateCert(trustedCertStr, cf), + null); + trustAnchors.add(ta); + } + PKIXParameters params = new PKIXParameters(trustAnchors); + params.setDate(new Date(114, 3, 1)); // 2014-03-01 + params.setRevocationEnabled(false); + + // Attempt to validate the CertPath. If no exception thrown, successful. + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + cpv.validate(cp, params); + System.out.println("CertPath validation successful."); + } + + private static X509Certificate generateCert(String certStr, + CertificateFactory cf) + throws Exception { + ByteArrayInputStream stream + = new ByteArrayInputStream(certStr.getBytes()); + return (X509Certificate) cf.generateCertificate(stream); + + } +}
--- a/test/sun/text/resources/LocaleData Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/text/resources/LocaleData Wed Apr 09 12:26:00 2014 -0700 @@ -431,10 +431,6 @@ FormatData/es_CL/NumberPatterns/0=#,##0.###;-#,##0.### # FormatData/es_CL/NumberPatterns/1=Ch$#,##0.00;Ch$-#,##0.00 # Changed; see bug 4122840 FormatData/es_CL/NumberPatterns/2=#,##0% -FormatData/es_CL/TimePatterns/0=hh:mm:ss a z -FormatData/es_CL/TimePatterns/1=hh:mm:ss a z -FormatData/es_CL/TimePatterns/2=hh:mm:ss a -FormatData/es_CL/TimePatterns/3=hh:mm a FormatData/es_CL/DatePatterns/0=EEEE d' de 'MMMM' de 'yyyy FormatData/es_CL/DatePatterns/1=d' de 'MMMM' de 'yyyy FormatData/es_CL/DatePatterns/2=dd-MM-yyyy @@ -498,10 +494,6 @@ FormatData/es_EC/NumberPatterns/2=#,##0% #changed for 4945388 CurrencyNames/es_EC/USD=$ -FormatData/es_EC/TimePatterns/0=hh:mm:ss a z -FormatData/es_EC/TimePatterns/1=hh:mm:ss a z -FormatData/es_EC/TimePatterns/2=hh:mm:ss a -FormatData/es_EC/TimePatterns/3=hh:mm a FormatData/es_EC/DatePatterns/0=EEEE d' de 'MMMM' de 'yyyy FormatData/es_EC/DatePatterns/1=d' de 'MMMM' de 'yyyy FormatData/es_EC/DatePatterns/2=dd/MM/yyyy @@ -7693,3 +7685,13 @@ # bug 8027695 FormatData/sv_SE/NumberPatterns/2=#,##0 % + +# bug 8017142 +FormatData/es_CL/TimePatterns/0=HH:mm:ss zzzz +FormatData/es_CL/TimePatterns/1=H:mm:ss z +FormatData/es_CL/TimePatterns/2=H:mm:ss +FormatData/es_CL/TimePatterns/3=H:mm +FormatData/es_EC/TimePatterns/0=HH:mm:ss zzzz +FormatData/es_EC/TimePatterns/1=H:mm:ss z +FormatData/es_EC/TimePatterns/2=H:mm:ss +FormatData/es_EC/TimePatterns/3=H:mm
--- a/test/sun/text/resources/LocaleDataTest.java Wed Apr 02 10:01:16 2014 -0700 +++ b/test/sun/text/resources/LocaleDataTest.java Wed Apr 09 12:26:00 2014 -0700 @@ -36,6 +36,7 @@ * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826 + * 8017142 * @summary Verify locale data * */