OpenJDK / bsd-port / jdk9 / jdk
changeset 14800:216b0ecea3af
Merge
author | prr |
---|---|
date | Wed, 18 May 2016 12:04:26 -0700 |
parents | 3dc009028cab 6b5c8b0f6b74 |
children | 49ad64d12e8f |
files | src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java test/sun/tools/jinfo/JInfoHelper.java test/sun/tools/jinfo/JInfoLauncherTest.java test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java test/sun/tools/jinfo/JInfoRunningProcessTest.java test/sun/tools/jinfo/JInfoSanityTest.java test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java |
diffstat | 284 files changed, 10816 insertions(+), 8621 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed May 18 20:40:17 2016 +0300 +++ b/.hgtags Wed May 18 12:04:26 2016 -0700 @@ -360,3 +360,4 @@ 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115 baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117 +e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118
--- a/make/Import.gmk Wed May 18 20:40:17 2016 +0300 +++ b/make/Import.gmk Wed May 18 12:04:26 2016 -0700 @@ -112,7 +112,7 @@ $(LN) -s ../$(@F) $@ ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(BASE_INSTALL_LIBRARIES_HERE)/%.dSYM + $(BASE_INSTALL_LIBRARIES_HERE)/server/%.dSYM: $(MKDIR) -p $(@D) $(RM) $@ $(LN) -s ../$(@F) $@
--- a/make/launcher/Launcher-java.base.gmk Wed May 18 20:40:17 2016 +0300 +++ b/make/launcher/Launcher-java.base.gmk Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ include LauncherCommon.gmk -JAVA_RC_FLAGS += -i $(JDK_TOPDIR)/src/java.base/windows/native/common +JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/common ifdef OPENJDK - JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons" + JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons else - JAVA_RC_FLAGS += -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons" + JAVA_RC_FLAGS += -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons endif ################################################################################
--- a/make/lib/Awt2dLibraries.gmk Wed May 18 20:40:17 2016 +0300 +++ b/make/lib/Awt2dLibraries.gmk Wed May 18 12:04:26 2016 -0700 @@ -213,9 +213,9 @@ endif ifdef OPENJDK - LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons" + LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/java.base/windows/native/launcher/icons else - LIBAWT_RC_FLAGS := -i "$(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons" + LIBAWT_RC_FLAGS := -I $(JDK_TOPDIR)/src/closed/java.base/windows/native/launcher/icons endif LIBAWT_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc endif
--- a/make/mapfiles/libj2ucrypto/mapfile-vers Wed May 18 20:40:17 2016 +0300 +++ b/make/mapfiles/libj2ucrypto/mapfile-vers Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,28 +30,35 @@ JNI_OnLoad; Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries; Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList; - Java_com_oracle_security_ucrypto_NativeDigest_nativeInit; + Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit; + Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate; + Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest; + Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone; + Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree; + Java_com_oracle_security_ucrypto_NativeDigest_nativeInit; Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate; Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest; - Java_com_oracle_security_ucrypto_NativeDigest_nativeClone; Java_com_oracle_security_ucrypto_NativeDigest_nativeFree; - Java_com_oracle_security_ucrypto_NativeCipher_nativeInit; - Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate; - Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal; + Java_com_oracle_security_ucrypto_NativeCipher_nativeInit; + Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate; + Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal; Java_com_oracle_security_ucrypto_NativeKey_nativeFree; Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit; Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit; Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit; - Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; - Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; - Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; - Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; - Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic; - + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; + Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic; + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate; + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest; + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone; + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree; JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit; JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate; JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest; - JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone; JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree; JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit; JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate; @@ -60,10 +67,10 @@ JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit; JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit; JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit; - JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; - JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; - JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; - JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic; local:
--- a/make/mapfiles/libjava/mapfile-vers Wed May 18 20:40:17 2016 +0300 +++ b/make/mapfiles/libjava/mapfile-vers Wed May 18 12:04:26 2016 -0700 @@ -262,7 +262,7 @@ Java_jdk_internal_reflect_Reflection_getCallerClass__; Java_jdk_internal_reflect_Reflection_getCallerClass__I; Java_jdk_internal_reflect_Reflection_getClassAccessFlags; - Java_jdk_internal_misc_VM_latestUserDefinedLoader; + Java_jdk_internal_misc_VM_latestUserDefinedLoader0; Java_jdk_internal_misc_VM_getuid; Java_jdk_internal_misc_VM_geteuid; Java_jdk_internal_misc_VM_getgid;
--- a/src/java.base/share/classes/java/io/BufferedWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/BufferedWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,13 +153,18 @@ * needed. If the requested length is at least as large as the buffer, * however, then this method will flush the buffer and write the characters * directly to the underlying stream. Thus redundant - * <code>BufferedWriter</code>s will not copy data unnecessarily. + * {@code BufferedWriter}s will not copy data unnecessarily. * * @param cbuf A character array * @param off Offset from which to start reading characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { synchronized (lock) { @@ -195,17 +200,24 @@ /** * Writes a portion of a String. * - * <p> If the value of the {@code len} parameter is negative then no - * characters are written. This is contrary to the specification of this - * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int) - * superclass}, which requires that an {@link IndexOutOfBoundsException} be - * thrown. + * @implSpec + * While the specification of this method in the + * {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass} + * recommends that an {@link IndexOutOfBoundsException} be thrown + * if {@code len} is negative or {@code off + len} is negative, + * the implementation in this class does not throw such an exception in + * these cases but instead simply writes no characters. * * @param s String to be written * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, + * or {@code off + len} is greater than the length + * of the given string + * + * @throws IOException If an I/O error occurs */ public void write(String s, int off, int len) throws IOException { synchronized (lock) {
--- a/src/java.base/share/classes/java/io/CharArrayWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/CharArrayWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,11 @@ * @param c the data to be written * @param off the start offset in the data * @param len the number of chars that are written + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array */ public void write(char c[], int off, int len) { if ((off < 0) || (off > c.length) || (len < 0) || @@ -114,6 +119,11 @@ * @param str String to be written from * @param off Offset from which to start reading characters * @param len Number of characters to be written + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string */ public void write(String str, int off, int len) { synchronized (lock) {
--- a/src/java.base/share/classes/java/io/FilterWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/FilterWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,12 @@ * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { out.write(cbuf, off, len); @@ -85,7 +90,12 @@ * @param off Offset from which to start reading characters * @param len Number of characters to be written * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} + * + * @throws IOException If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { out.write(str, off, len);
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java Wed May 18 12:04:26 2016 -0700 @@ -603,12 +603,12 @@ * Class.forName(desc.getName(), false, loader) * </pre> * where <code>loader</code> is determined as follows: if there is a - * method on the current thread's stack whose declaring class was - * defined by a user-defined class loader (and was not a generated to - * implement reflective invocations), then <code>loader</code> is class - * loader corresponding to the closest such method to the currently - * executing frame; otherwise, <code>loader</code> is - * <code>null</code>. If this call results in a + * method on the current thread's stack whose declaring class is not a + * <a href="../lang/ClassLoader.html#builtinLoaders"> + * <em>platform class</em></a>, then <code>loader</code> is + * the class loader of such class; otherwise, <code>loader</code> + * is the {@linkplain ClassLoader#getPlatformClassLoader() + * platform class loader}. If this call results in a * <code>ClassNotFoundException</code> and the name of the passed * <code>ObjectStreamClass</code> instance is the Java language keyword * for a primitive type or void, then the <code>Class</code> object @@ -666,12 +666,15 @@ * <pre> * Class.forName(i, false, loader) * </pre> - * where <code>loader</code> is that of the first non-<code>null</code> - * class loader up the execution stack, or <code>null</code> if no - * non-<code>null</code> class loaders are on the stack (the same class - * loader choice used by the <code>resolveClass</code> method). Unless any - * of the resolved interfaces are non-public, this same value of - * <code>loader</code> is also the class loader passed to + * where <code>loader</code> is determined as follows: if there is a + * method on the current thread's stack whose declaring class is not a + * <a href="../lang/ClassLoader.html#builtinLoaders"> + * <em>platform class</em></a>, then <code>loader</code> is + * the class loader of such class; otherwise, <code>loader</code> + * is the {@linkplain ClassLoader#getPlatformClassLoader() + * platform class loader}. + * Unless any of the resolved interfaces are non-public, this same value + * of <code>loader</code> is also the class loader passed to * <code>Proxy.getProxyClass</code>; if non-public interfaces are present, * their class loader is passed instead (if more than one non-public * interface class loader is encountered, an @@ -2154,10 +2157,11 @@ int ndoubles); /** - * Returns the first non-null class loader (not counting class loaders of - * generated reflection implementation classes) up the execution stack, or - * null if only code from the null class loader is on the stack. This - * method is also called via reflection by the following RMI-IIOP class: + * Returns the first non-null and non-platform class loader + * (not counting class loaders of generated reflection implementation classes) + * up the execution stack, or null if only code from the bootstrap and + * platform class loader is on the stack. + * This method is also called via reflection by the following RMI-IIOP class: * * com.sun.corba.se.internal.util.JDKClassLoader *
--- a/src/java.base/share/classes/java/io/OutputStreamWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,7 +202,12 @@ * @param off Offset from which to start writing characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException If an I/O error occurs */ public void write(char cbuf[], int off, int len) throws IOException { se.write(cbuf, off, len); @@ -215,7 +220,12 @@ * @param off Offset from which to start writing characters * @param len Number of characters to write * - * @exception IOException If an I/O error occurs + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string + * + * @throws IOException If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { se.write(str, off, len);
--- a/src/java.base/share/classes/java/io/PipedWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/PipedWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,19 +125,25 @@ } /** - * Writes <code>len</code> characters from the specified character array - * starting at offset <code>off</code> to this piped output stream. + * Writes {@code len} characters from the specified character array + * starting at offset {@code off} to this piped output stream. * This method blocks until all the characters are written to the output * stream. * If a thread was reading data characters from the connected piped input * stream, but the thread is no longer alive, then an - * <code>IOException</code> is thrown. + * {@code IOException} is thrown. * * @param cbuf the data. * @param off the start offset in the data. * @param len the number of characters to write. - * @exception IOException if the pipe is - * <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>, + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * + * @throws IOException if the pipe is + * <a href=PipedOutputStream.html#BROKEN><code>broken</code></a>, * {@link #connect(java.io.PipedReader) unconnected}, closed * or an I/O error occurs. */
--- a/src/java.base/share/classes/java/io/PrintWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/PrintWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -410,6 +410,11 @@ * @param buf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} */ public void write(char buf[], int off, int len) { try { @@ -440,6 +445,11 @@ * @param s A String * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If the values of the {@code off} and {@code len} parameters + * cause the corresponding method of the underlying {@code Writer} + * to throw an {@code IndexOutOfBoundsException} */ public void write(String s, int off, int len) { try {
--- a/src/java.base/share/classes/java/io/StringWriter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/StringWriter.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,11 @@ * @param cbuf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array */ public void write(char cbuf[], int off, int len) { if ((off < 0) || (off > cbuf.length) || (len < 0) || @@ -107,6 +112,11 @@ * @param str String to be written * @param off Offset from which to start writing characters * @param len Number of characters to write + * + * @throws IndexOutOfBoundsException + * If {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given string */ public void write(String str, int off, int len) { buf.append(str, off, off + len);
--- a/src/java.base/share/classes/java/io/Writer.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/io/Writer.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,12 +32,11 @@ * Most subclasses, however, will override some of the methods defined here in * order to provide higher efficiency, additional functionality, or both. * - * @see Writer * @see BufferedWriter * @see CharArrayWriter * @see FilterWriter * @see OutputStreamWriter - * @see FileWriter + * @see FileWriter * @see PipedWriter * @see PrintWriter * @see StringWriter @@ -139,6 +138,12 @@ * @param len * Number of characters to write * + * @throws IndexOutOfBoundsException + * Implementations should throw this exception + * if {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length + * of the given array + * * @throws IOException * If an I/O error occurs */ @@ -160,6 +165,11 @@ /** * Writes a portion of a string. * + * @implSpec + * The implementation in this class throws an + * {@code IndexOutOfBoundsException} for the indicated conditions; + * overriding methods may choose to do otherwise. + * * @param str * A String * @@ -170,8 +180,9 @@ * Number of characters to write * * @throws IndexOutOfBoundsException - * If {@code off} is negative, or {@code len} is negative, - * or {@code off+len} is negative or greater than the length + * Implementations should throw this exception + * if {@code off} is negative, or {@code len} is negative, + * or {@code off + len} is negative or greater than the length * of the given string * * @throws IOException
--- a/src/java.base/share/classes/java/lang/Thread.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/Thread.java Wed May 18 12:04:26 2016 -0700 @@ -341,6 +341,45 @@ } /** + * Indicates that the caller is momentarily unable to progress, until the + * occurrence of one or more actions on the part of other activities. By + * invoking this method within each iteration of a spin-wait loop construct, + * the calling thread indicates to the runtime that it is busy-waiting. + * The runtime may take action to improve the performance of invoking + * spin-wait loop constructions. + * <p> + * @apiNote + * As an example consider a method in a class that spins in a loop until + * some flag is set outside of that method. A call to the {@code onSpinWait} + * method should be placed inside the spin loop. + * <pre>{@code + * class EventHandler { + * volatile boolean eventNotificationNotReceived; + * void waitForEventAndHandleIt() { + * while ( eventNotificationNotReceived ) { + * java.lang.Thread.onSpinWait(); + * } + * readAndProcessEvent(); + * } + * + * void readAndProcessEvent() { + * // Read event from some source and process it + * . . . + * } + * } + * }</pre> + * <p> + * The code above would remain correct even if the {@code onSpinWait} + * method was not called at all. However on some architectures the Java + * Virtual Machine may issue the processor instructions to address such + * code patterns in a more beneficial way. + * <p> + * @since 9 + */ + @HotSpotIntrinsicCandidate + public static void onSpinWait() {} + + /** * Initializes a Thread with the current AccessControlContext. * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean) */
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed May 18 12:04:26 2016 -0700 @@ -706,6 +706,9 @@ case ARRAY_STORE: emitArrayStore(name); continue; + case ARRAY_LENGTH: + emitArrayLength(name); + continue; case IDENTITY: assert(name.arguments.length == 1); emitPushArguments(name); @@ -740,15 +743,16 @@ return classFile; } - void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } - void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } + void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + void emitArrayLength(Name name) { emitArrayOp(name, Opcodes.ARRAYLENGTH); } void emitArrayOp(Name name, int arrayOpcode) { - assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE; + assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE || arrayOpcode == Opcodes.ARRAYLENGTH; Class<?> elementType = name.function.methodType().parameterType(0).getComponentType(); assert elementType != null; emitPushArguments(name); - if (elementType.isPrimitive()) { + if (arrayOpcode != Opcodes.ARRAYLENGTH && elementType.isPrimitive()) { Wrapper w = Wrapper.forPrimitiveType(elementType); arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode); }
--- a/src/java.base/share/classes/java/lang/invoke/Invokers.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/Invokers.java Wed May 18 12:04:26 2016 -0700 @@ -95,12 +95,12 @@ /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) { // TODO cache invoker - return makeVarHandleMethodInvoker(ak); + return makeVarHandleMethodInvoker(ak, false); } /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) { // TODO cache invoker - return makeVarHandleMethodExactInvoker(ak); + return makeVarHandleMethodInvoker(ak, true); } private MethodHandle cachedInvoker(int idx) { @@ -127,26 +127,11 @@ return invoker; } - private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) { + private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak, boolean isExact) { MethodType mtype = targetType; MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class); - LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.methodName(), mtype); - VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal()); - MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad); - - invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.methodName(), mtype), false); - assert(checkVarHandleInvoker(invoker)); - - maybeCompileToBytecode(invoker); - return invoker; - } - - private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) { - MethodType mtype = targetType; - MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class); - - LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.methodName(), mtype); + LambdaForm lform = varHandleMethodInvokerHandleForm(ak.methodName(), mtype, isExact); VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal()); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad); @@ -400,59 +385,7 @@ return lform; } - private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) { - // TODO Cache form? - - final int THIS_MH = 0; - final int CALL_VH = THIS_MH + 1; - final int ARG_BASE = CALL_VH + 1; - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); - int nameCursor = ARG_LIMIT; - final int VAD_ARG = nameCursor++; - final int CHECK_TYPE = nameCursor++; - final int GET_MEMBER = nameCursor++; - final int LINKER_CALL = nameCursor++; - - MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class) - .basicType() - .appendParameterTypes(MemberName.class); - - MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic); - try { - linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - - Name[] names = new Name[LINKER_CALL + 1]; - names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class)); - names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class)); - for (int i = 0; i < mtype.parameterCount(); i++) { - names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i))); - } - - BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L(); - names[THIS_MH] = names[THIS_MH].withConstraint(speciesData); - - NamedFunction getter = speciesData.getterFunction(0); - names[VAD_ARG] = new Name(getter, names[THIS_MH]); - - Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class); - - names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]); - - names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]); - outArgs[outArgs.length - 1] = names[GET_MEMBER]; - - names[LINKER_CALL] = new Name(linker, outArgs); - LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)), - ARG_LIMIT, names); - - lform.compileToBytecode(); - return lform; - } - - private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) { + private static LambdaForm varHandleMethodInvokerHandleForm(String name, MethodType mtype, boolean isExact) { // TODO Cache form? final int THIS_MH = 0; @@ -477,8 +410,11 @@ NamedFunction getter = speciesData.getterFunction(0); names[VAD_ARG] = new Name(getter, names[THIS_MH]); - names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]); - + if (isExact) { + names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]); + } else { + names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]); + } Object[] outArgs = new Object[ARG_LIMIT]; outArgs[0] = names[CHECK_TYPE]; for (int i = 1; i < ARG_LIMIT; i++) { @@ -488,7 +424,8 @@ MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class) .basicType(); names[LINKER_CALL] = new Name(outCallType, outArgs); - LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)), + String debugName = isExact ? ":VarHandle_exactInvoker" : ":VarHandle_invoker"; + LambdaForm lform = new LambdaForm(name + debugName + shortenSignature(basicTypeSignature(mtype)), ARG_LIMIT, names); lform.prepare(); @@ -511,21 +448,13 @@ /*non-public*/ static @ForceInline - void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) { - MethodType erasedTarget = handle.vform.methodType_table[ad.type]; - MethodType erasedSymbolic = ad.symbolicMethodTypeErased; - if (erasedTarget != erasedSymbolic) - throw newWrongMethodTypeException(erasedTarget, erasedSymbolic); - } - - /*non-public*/ static - @ForceInline - MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) { - MemberName mn = handle.vform.memberName_table[ad.mode]; - if (mn == null) { - throw handle.unsupported(); + MethodHandle checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) { + MethodHandle mh = handle.getMethodHandle(ad.mode); + MethodType mt = mh.type(); + if (mt != ad.symbolicMethodTypeInvoker) { + throw newWrongMethodTypeException(mt, ad.symbolicMethodTypeInvoker); } - return mn; + return mh; } /*non-public*/ static @@ -649,8 +578,7 @@ NF_getCallSiteTarget, NF_checkCustomized, NF_checkVarHandleGenericType, - NF_checkVarHandleExactType, - NF_getVarHandleMemberName; + NF_checkVarHandleExactType; static { try { NamedFunction nfs[] = { @@ -666,8 +594,6 @@ .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)), NF_checkVarHandleExactType = new NamedFunction(Invokers.class .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)), - NF_getVarHandleMemberName = new NamedFunction(Invokers.class - .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class)) }; // Each nf must be statically invocable or we get tied up in our bootstraps. assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed May 18 12:04:26 2016 -0700 @@ -66,25 +66,28 @@ /// Factory methods to create method handles: - static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) { - if (arrayClass == Object[].class) - return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER); + static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) { + if (arrayClass == Object[].class) { + return ArrayAccess.objectAccessor(access); + } if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); - int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX); + int cacheIndex = ArrayAccess.cacheIndex(access); MethodHandle mh = cache[cacheIndex]; if (mh != null) return mh; - mh = ArrayAccessor.getAccessor(arrayClass, isSetter); - MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter); + mh = ArrayAccessor.getAccessor(arrayClass, access); + MethodType correctType = ArrayAccessor.correctType(arrayClass, access); if (mh.type() != correctType) { assert(mh.type().parameterType(0) == Object[].class); - assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class); - assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType()); + /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class); + /* if access == GET */ assert(access != ArrayAccess.GET || + (mh.type().returnType() == Object.class && + correctType.parameterType(0).getComponentType() == correctType.returnType())); // safe to view non-strictly, because element type follows from array type mh = mh.viewAsType(correctType, false); } - mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD)); + mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access)); // Atomically update accessor cache. synchronized(cache) { if (cache[cacheIndex] == null) { @@ -97,9 +100,52 @@ return mh; } + enum ArrayAccess { + GET, SET, LENGTH; + + // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in + // final fields. + + static String opName(ArrayAccess a) { + switch (a) { + case GET: return "getElement"; + case SET: return "setElement"; + case LENGTH: return "length"; + } + throw new AssertionError(); + } + + static MethodHandle objectAccessor(ArrayAccess a) { + switch (a) { + case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER; + case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER; + case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH; + } + throw new AssertionError(); + } + + static int cacheIndex(ArrayAccess a) { + switch (a) { + case GET: return ArrayAccessor.GETTER_INDEX; + case SET: return ArrayAccessor.SETTER_INDEX; + case LENGTH: return ArrayAccessor.LENGTH_INDEX; + } + throw new AssertionError(); + } + + static Intrinsic intrinsic(ArrayAccess a) { + switch (a) { + case GET: return Intrinsic.ARRAY_LOAD; + case SET: return Intrinsic.ARRAY_STORE; + case LENGTH: return Intrinsic.ARRAY_LENGTH; + } + throw new AssertionError(); + } + } + static final class ArrayAccessor { - /// Support for array element access - static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2; + /// Support for array element and length access + static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3; static final ClassValue<MethodHandle[]> TYPED_ACCESSORS = new ClassValue<MethodHandle[]>() { @Override @@ -107,14 +153,16 @@ return new MethodHandle[INDEX_LIMIT]; } }; - static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER; + static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH; static { MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); - cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD); - cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true), Intrinsic.ARRAY_STORE); + cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET), Intrinsic.ARRAY_LOAD); + cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET), Intrinsic.ARRAY_STORE); + cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH); assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName())); assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName())); + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName())); } static int getElementI(int[] a, int i) { return a[i]; } @@ -137,31 +185,47 @@ static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static String name(Class<?> arrayClass, boolean isSetter) { + static int lengthI(int[] a) { return a.length; } + static int lengthJ(long[] a) { return a.length; } + static int lengthF(float[] a) { return a.length; } + static int lengthD(double[] a) { return a.length; } + static int lengthZ(boolean[] a) { return a.length; } + static int lengthB(byte[] a) { return a.length; } + static int lengthS(short[] a) { return a.length; } + static int lengthC(char[] a) { return a.length; } + static int lengthL(Object[] a) { return a.length; } + + static String name(Class<?> arrayClass, ArrayAccess access) { Class<?> elemClass = arrayClass.getComponentType(); if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); - return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); + return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass); } - static MethodType type(Class<?> arrayClass, boolean isSetter) { + static MethodType type(Class<?> arrayClass, ArrayAccess access) { Class<?> elemClass = arrayClass.getComponentType(); Class<?> arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; elemClass = Object.class; } - return !isSetter ? - MethodType.methodType(elemClass, arrayArgClass, int.class) : - MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); + switch (access) { + case GET: return MethodType.methodType(elemClass, arrayArgClass, int.class); + case SET: return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); + case LENGTH: return MethodType.methodType(int.class, arrayArgClass); + } + throw new IllegalStateException("should not reach here"); } - static MethodType correctType(Class<?> arrayClass, boolean isSetter) { + static MethodType correctType(Class<?> arrayClass, ArrayAccess access) { Class<?> elemClass = arrayClass.getComponentType(); - return !isSetter ? - MethodType.methodType(elemClass, arrayClass, int.class) : - MethodType.methodType(void.class, arrayClass, int.class, elemClass); + switch (access) { + case GET: return MethodType.methodType(elemClass, arrayClass, int.class); + case SET: return MethodType.methodType(void.class, arrayClass, int.class, elemClass); + case LENGTH: return MethodType.methodType(int.class, arrayClass); + } + throw new IllegalStateException("should not reach here"); } - static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) { - String name = name(arrayClass, isSetter); - MethodType type = type(arrayClass, isSetter); + static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) { + String name = name(arrayClass, access); + MethodType type = type(arrayClass, access); try { return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type); } catch (ReflectiveOperationException ex) { @@ -1282,6 +1346,7 @@ NEW_ARRAY, ARRAY_LOAD, ARRAY_STORE, + ARRAY_LENGTH, IDENTITY, ZERO, NONE // no intrinsic associated
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed May 18 12:04:26 2016 -0700 @@ -2245,6 +2245,20 @@ } /** + * Produces a method handle returning the length of an array. + * The type of the method handle will have {@code int} as return type, + * and its sole argument will be the array type. + * @param arrayClass an array type + * @return a method handle which can retrieve the length of an array of the given array type + * @throws NullPointerException if the argument is {@code null} + * @throws IllegalArgumentException if arrayClass is not an array type + */ + public static + MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException { + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH); + } + + /** * Produces a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's * element type. Its first argument will be the array type, @@ -2256,7 +2270,7 @@ */ public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false); + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET); } /** @@ -2271,7 +2285,7 @@ */ public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException { - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true); + return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET); } /**
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java Wed May 18 12:04:26 2016 -0700 @@ -26,6 +26,7 @@ package java.lang.invoke; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; @@ -33,7 +34,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; @@ -1475,11 +1475,11 @@ TypesAndInvokers tis = getTypesAndInvokers(); MethodHandle mh = tis.methodHandle_table[mode]; if (mh == null) { - mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode); + mh = tis.methodHandle_table[mode] = getMethodHandleUncached(mode); } return mh; } - private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) { + private final MethodHandle getMethodHandleUncached(int mode) { MethodType mt = accessModeType(AccessMode.values()[mode]). insertParameterTypes(0, VarHandle.class); MemberName mn = vform.getMemberName(mode); @@ -1501,7 +1501,7 @@ } static final BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> - AIOOBE_SUPPLIER = Objects.outOfBoundsExceptionFormatter( + AIOOBE_SUPPLIER = Preconditions.outOfBoundsExceptionFormatter( new Function<String, ArrayIndexOutOfBoundsException>() { @Override public ArrayIndexOutOfBoundsException apply(String s) {
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Wed May 18 12:04:26 2016 -0700 @@ -24,8 +24,10 @@ */ package java.lang.invoke; +import jdk.internal.util.Preconditions; +import jdk.internal.vm.annotation.ForceInline; + import java.util.Objects; -import jdk.internal.vm.annotation.ForceInline; import static java.lang.invoke.MethodHandleStatics.UNSAFE; @@ -163,8 +165,7 @@ @ForceInline static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) { - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)), + return UNSAFE.weakCompareAndSwap$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)), handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, {#if[Object]?handle.fieldType.cast(value):value}); @@ -345,8 +346,7 @@ @ForceInline static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) { - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(handle.base, + return UNSAFE.weakCompareAndSwap$Type$Volatile(handle.base, handle.fieldOffset, {#if[Object]?handle.fieldType.cast(expected):expected}, {#if[Object]?handle.fieldType.cast(value):value}); @@ -447,7 +447,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -458,7 +458,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -470,7 +470,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -481,7 +481,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -493,7 +493,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -504,7 +504,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #if[CAS] @@ -517,7 +517,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -530,7 +530,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -543,7 +543,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -556,7 +556,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -569,7 +569,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -581,9 +581,8 @@ #else[Object] $type$[] array = ($type$[]) oarray; #end[Object] - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + return UNSAFE.weakCompareAndSwap$Type$Volatile(array, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -596,7 +595,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -609,7 +608,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -622,7 +621,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndSet$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #end[CAS] @@ -636,7 +635,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value); } @@ -648,7 +647,7 @@ $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value) + value; } #end[AtomicAdd]
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Wed May 18 12:04:26 2016 -0700 @@ -25,6 +25,7 @@ package java.lang.invoke; import jdk.internal.misc.Unsafe; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import java.nio.ByteBuffer; @@ -81,7 +82,7 @@ @ForceInline static int index(byte[] ba, int index) { - return Objects.checkIndex(index, ba.length - ALIGN, null); + return Preconditions.checkIndex(index, ba.length - ALIGN, null); } @ForceInline @@ -233,8 +234,7 @@ @ForceInline static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) { byte[] ba = (byte[]) oba; - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$RawType$( + return UNSAFE.weakCompareAndSwap$RawType$Volatile( ba, address(ba, index(ba, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); @@ -271,22 +271,33 @@ #if[AtomicAdd] @ForceInline - static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) { + static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ delta) { byte[] ba = (byte[]) oba; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))); + if (handle.be == BE) { + return UNSAFE.getAndAdd$RawType$( + ba, + address(ba, index(ba, index)), + delta); + } else { + return getAndAddConvEndianWithCAS(ba, index, delta); + } } @ForceInline - static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) { - byte[] ba = (byte[]) oba; - return convEndian(handle.be, UNSAFE.getAndAdd$RawType$( - ba, - address(ba, index(ba, index)), - convEndian(handle.be, value))) + value; + static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) { + $type$ nativeExpectedValue, expectedValue; + long offset = address(ba, index(ba, index)); + do { + nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset); + expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); + } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(ba, offset, + nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); + return expectedValue; + } + + @ForceInline + static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ delta) { + return getAndAdd(handle, oba, index, delta) + delta; } #end[AtomicAdd] @@ -307,14 +318,14 @@ @ForceInline static int index(ByteBuffer bb, int index) { - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline static int indexRO(ByteBuffer bb, int index) { if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY)) throw new ReadOnlyBufferException(); - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline @@ -466,8 +477,7 @@ @ForceInline static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) { ByteBuffer bb = (ByteBuffer) obb; - // TODO defer to strong form until new Unsafe method is added - return UNSAFE.compareAndSwap$RawType$( + return UNSAFE.weakCompareAndSwap$RawType$Volatile( UNSAFE.getObject(bb, BYTE_BUFFER_HB), address(bb, indexRO(bb, index)), convEndian(handle.be, expected), convEndian(handle.be, value)); @@ -504,23 +514,34 @@ #if[AtomicAdd] @ForceInline - static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) { + static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ delta) { ByteBuffer bb = (ByteBuffer) obb; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - UNSAFE.getObject(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, value))); + if (handle.be == BE) { + return UNSAFE.getAndAdd$RawType$( + UNSAFE.getObject(bb, BYTE_BUFFER_HB), + address(bb, indexRO(bb, index)), + delta); + } else { + return getAndAddConvEndianWithCAS(bb, index, delta); + } } @ForceInline - static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) { - ByteBuffer bb = (ByteBuffer) obb; - return convEndian(handle.be, - UNSAFE.getAndAdd$RawType$( - UNSAFE.getObject(bb, BYTE_BUFFER_HB), - address(bb, indexRO(bb, index)), - convEndian(handle.be, value))) + value; + static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) { + $type$ nativeExpectedValue, expectedValue; + Object base = UNSAFE.getObject(bb, BYTE_BUFFER_HB); + long offset = address(bb, indexRO(bb, index)); + do { + nativeExpectedValue = UNSAFE.get$RawType$Volatile(base, offset); + expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue); + } while (!UNSAFE.weakCompareAndSwap$RawType$Volatile(base, offset, + nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta))); + return expectedValue; + } + + @ForceInline + static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ delta) { + return getAndAdd(handle, obb, index, delta) + delta; } #end[AtomicAdd]
--- a/src/java.base/share/classes/java/nio/Buffer.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/nio/Buffer.java Wed May 18 12:04:26 2016 -0700 @@ -111,7 +111,7 @@ * to zero. * * - * <h2> Clearing, flipping, and rewinding </h2> + * <h2> Additional operations </h2> * * <p> In addition to methods for accessing the position, limit, and capacity * values and for marking and resetting, this class also defines the following @@ -131,6 +131,12 @@ * it already contains: It leaves the limit unchanged and sets the position * to zero. </p></li> * + * <li><p> {@link #slice} creates a subsequence of a buffer: It leaves the + * limit and the position unchanged. </p></li> + * + * <li><p> {@link #duplicate} creates a shallow copy of a buffer: It leaves + * the limit and the position unchanged. </p></li> + * * </ul> * * @@ -567,6 +573,46 @@ */ public abstract boolean isDirect(); + /** + * Creates a new buffer whose content is a shared subsequence of + * this buffer's content. + * + * <p> The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + * <p> The new buffer's position will be zero, its capacity and its limit + * will be the number of elements remaining in this buffer, its mark will be + * undefined. The new buffer will be direct if, and only if, this buffer is + * direct, and it will be read-only if, and only if, this buffer is + * read-only. </p> + * + * @return The new buffer + * + * @since 9 + */ + public abstract Buffer slice(); + + /** + * Creates a new buffer that shares this buffer's content. + * + * <p> The content of the new buffer will be that of this buffer. Changes + * to this buffer's content will be visible in the new buffer, and vice + * versa; the two buffers' position, limit, and mark values will be + * independent. + * + * <p> The new buffer's capacity, limit, position and mark values will be + * identical to those of this buffer. The new buffer will be direct if, and + * only if, this buffer is direct, and it will be read-only if, and only if, + * this buffer is read-only. </p> + * + * @return The new buffer + * + * @since 9 + */ + public abstract Buffer duplicate(); + // -- Package-private methods for bounds checking, etc. --
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template Wed May 18 12:04:26 2016 -0700 @@ -70,8 +70,7 @@ * #end[byte] * - * <li><p> Methods for {@link #compact compacting}, {@link - * #duplicate duplicating}, and {@link #slice slicing} + * <li><p> A method for {@link #compact compacting} * $a$ $type$ buffer. </p></li> * * </ul> @@ -535,6 +534,7 @@ * @see #alignedSlice(int) #end[byte] */ + @Override public abstract $Type$Buffer slice(); /** @@ -557,6 +557,7 @@ * * @return The new $type$ buffer */ + @Override public abstract $Type$Buffer duplicate(); /**
--- a/src/java.base/share/classes/java/text/MessageFormat.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/text/MessageFormat.java Wed May 18 12:04:26 2016 -0700 @@ -1068,7 +1068,7 @@ * index information as described above. * @return An <code>Object</code> array parsed from the string. In case of * error, returns null. - * @throws NullPointerException if {@code source} or {@code pos} is null. + * @throws NullPointerException if {@code pos} is null. */ public Object parseObject(String source, ParsePosition pos) { return parse(source, pos);
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Wed May 18 12:04:26 2016 -0700 @@ -308,6 +308,7 @@ * N nano-of-day number 1234000000 * * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 + * v generic time-zone name zone-name Pacific Time; PT * z time-zone name zone-name Pacific Standard Time; PST * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00 * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 @@ -365,9 +366,17 @@ * letters throws {@code IllegalArgumentException}. * <p> * <b>Zone names</b>: This outputs the display name of the time-zone ID. If the - * count of letters is one, two or three, then the short name is output. If the - * count of letters is four, then the full name is output. Five or more letters - * throws {@code IllegalArgumentException}. + * pattern letter is 'z' the output is the daylight savings aware zone name. + * If there is insufficient information to determine whether DST applies, + * the name ignoring daylight savings time will be used. + * If the count of letters is one, two or three, then the short name is output. + * If the count of letters is four, then the full name is output. + * Five or more letters throws {@code IllegalArgumentException}. + * <p> + * If the pattern letter is 'v' the output provides the zone name ignoring + * daylight savings time. If the count of letters is one, then the short name is output. + * If the count of letters is four, then the full name is output. + * Two, three and five or more letters throw {@code IllegalArgumentException}. * <p> * <b>Offset X and x</b>: This formats the offset based on the number of pattern * letters. One letter outputs just the hour, such as '+01', unless the minute
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Wed May 18 12:04:26 2016 -0700 @@ -81,9 +81,11 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.Chronology; import java.time.chrono.Era; import java.time.chrono.IsoChronology; @@ -1157,10 +1159,11 @@ * result of {@link ZoneOffset#getId()}. * If the zone is not an offset, the textual name will be looked up * for the locale set in the {@link DateTimeFormatter}. - * If the temporal object being printed represents an instant, then the text - * will be the summer or winter time text as appropriate. + * If the temporal object being printed represents an instant, or if it is a + * local date-time that is not in a daylight saving gap or overlap then + * the text will be the summer or winter time text as appropriate. * If the lookup for text does not find any suitable result, then the - * {@link ZoneId#getId() ID} will be printed instead. + * {@link ZoneId#getId() ID} will be printed. * If the zone cannot be obtained then an exception is thrown unless the * section of the formatter is optional. * <p> @@ -1177,7 +1180,7 @@ * @return this, for chaining, not null */ public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) { - appendInternal(new ZoneTextPrinterParser(textStyle, null)); + appendInternal(new ZoneTextPrinterParser(textStyle, null, false)); return this; } @@ -1193,10 +1196,11 @@ * result of {@link ZoneOffset#getId()}. * If the zone is not an offset, the textual name will be looked up * for the locale set in the {@link DateTimeFormatter}. - * If the temporal object being printed represents an instant, then the text + * If the temporal object being printed represents an instant, or if it is a + * local date-time that is not in a daylight saving gap or overlap, then the text * will be the summer or winter time text as appropriate. * If the lookup for text does not find any suitable result, then the - * {@link ZoneId#getId() ID} will be printed instead. + * {@link ZoneId#getId() ID} will be printed. * If the zone cannot be obtained then an exception is thrown unless the * section of the formatter is optional. * <p> @@ -1220,7 +1224,70 @@ public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle, Set<ZoneId> preferredZones) { Objects.requireNonNull(preferredZones, "preferredZones"); - appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones)); + appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, false)); + return this; + } + //---------------------------------------------------------------------- + /** + * Appends the generic time-zone name, such as 'Pacific Time', to the formatter. + * <p> + * This appends an instruction to format/parse the generic textual + * name of the zone to the builder. The generic name is the same throughout the whole + * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the + * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the + * specific names, see {@link #appendZoneText(TextStyle)}. + * <p> + * During formatting, the zone is obtained using a mechanism equivalent + * to querying the temporal with {@link TemporalQueries#zoneId()}. + * If the zone is a {@code ZoneOffset} it will be printed using the + * result of {@link ZoneOffset#getId()}. + * If the zone is not an offset, the textual name will be looked up + * for the locale set in the {@link DateTimeFormatter}. + * If the lookup for text does not find any suitable result, then the + * {@link ZoneId#getId() ID} will be printed. + * If the zone cannot be obtained then an exception is thrown unless the + * section of the formatter is optional. + * <p> + * During parsing, either the textual zone name, the zone ID or the offset + * is accepted. Many textual zone names are not unique, such as CST can be + * for both "Central Standard Time" and "China Standard Time". In this + * situation, the zone id will be determined by the region information from + * formatter's {@link DateTimeFormatter#getLocale() locale} and the standard + * zone id for that area, for example, America/New_York for the America Eastern zone. + * The {@link #appendGenericZoneText(TextStyle, Set)} may be used + * to specify a set of preferred {@link ZoneId} in this situation. + * + * @param textStyle the text style to use, not null + * @return this, for chaining, not null + */ + public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle) { + appendInternal(new ZoneTextPrinterParser(textStyle, null, true)); + return this; + } + + /** + * Appends the generic time-zone name, such as 'Pacific Time', to the formatter. + * <p> + * This appends an instruction to format/parse the generic textual + * name of the zone to the builder. The generic name is the same throughout the whole + * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the + * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the + * specific names, see {@link #appendZoneText(TextStyle)}. + * <p> + * This method also allows a set of preferred {@link ZoneId} to be + * specified for parsing. The matched preferred zone id will be used if the + * textural zone name being parsed is not unique. + * <p> + * See {@link #appendGenericZoneText(TextStyle)} for details about + * formatting and parsing. + * + * @param textStyle the text style to use, not null + * @param preferredZones the set of preferred zone ids, not null + * @return this, for chaining, not null + */ + public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle, + Set<ZoneId> preferredZones) { + appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, true)); return this; } @@ -1416,6 +1483,7 @@ * N nano-of-day number 1234000000 * * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 + * v generic time-zone name zone-name PT, Pacific Time * z time-zone name zone-name Pacific Standard Time; PST * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00; * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 @@ -1537,6 +1605,8 @@ * Pattern Count Equivalent builder methods * ------- ----- -------------------------- * VV 2 appendZoneId() + * v 1 appendGenericZoneText(TextStyle.SHORT) + * vvvv 4 appendGenericZoneText(TextStyle.FULL) * z 1 appendZoneText(TextStyle.SHORT) * zz 2 appendZoneText(TextStyle.SHORT) * zzz 3 appendZoneText(TextStyle.SHORT) @@ -1643,6 +1713,14 @@ throw new IllegalArgumentException("Pattern letter count must be 2: " + cur); } appendZoneId(); + } else if (cur == 'v') { + if (count == 1) { + appendGenericZoneText(TextStyle.SHORT); + } else if (count == 4) { + appendGenericZoneText(TextStyle.FULL); + } else { + throw new IllegalArgumentException("Wrong number of pattern letters: " + cur); + } } else if (cur == 'Z') { if (count < 4) { appendOffset("+HHMM", "+0000"); @@ -1894,6 +1972,8 @@ // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 // 310 - Z - matches SimpleDateFormat and LDML // 310 - V - time-zone id, matches LDML + // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back + // to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data // 310 - p - prefix for padding // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5 // 310 - x - matches LDML @@ -1901,7 +1981,6 @@ // LDML - U - cycle year name, not supported by 310 yet // LDML - l - deprecated // LDML - j - not relevant - // LDML - v,V - extended time-zone names } //----------------------------------------------------------------------- @@ -3723,9 +3802,12 @@ /** The preferred zoneid map */ private Set<String> preferredZones; - ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones) { + /** Display in generic time-zone format. True in case of pattern letter 'v' */ + private final boolean isGeneric; + ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) { super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")"); this.textStyle = Objects.requireNonNull(textStyle, "textStyle"); + this.isGeneric = isGeneric; if (preferredZones != null && preferredZones.size() != 0) { this.preferredZones = new HashSet<>(); for (ZoneId id : preferredZones) { @@ -3788,11 +3870,21 @@ String zname = zone.getId(); if (!(zone instanceof ZoneOffset)) { TemporalAccessor dt = context.getTemporal(); - String name = getDisplayName(zname, - dt.isSupported(ChronoField.INSTANT_SECONDS) - ? (zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD) - : GENERIC, - context.getLocale()); + int type = GENERIC; + if (!isGeneric) { + if (dt.isSupported(ChronoField.INSTANT_SECONDS)) { + type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD; + } else if (dt.isSupported(ChronoField.EPOCH_DAY) && + dt.isSupported(ChronoField.NANO_OF_DAY)) { + LocalDate date = LocalDate.ofEpochDay(dt.getLong(ChronoField.EPOCH_DAY)); + LocalTime time = LocalTime.ofNanoOfDay(dt.getLong(ChronoField.NANO_OF_DAY)); + LocalDateTime ldt = date.atTime(time); + if (zone.getRules().getTransition(ldt) == null) { + type = zone.getRules().isDaylightSavings(ldt.atZone(zone).toInstant()) ? DST : STD; + } + } + } + String name = getDisplayName(zname, type, context.getLocale()); if (name != null) { zname = name; }
--- a/src/java.base/share/classes/java/time/zone/ZoneRules.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/time/zone/ZoneRules.java Wed May 18 12:04:26 2016 -0700 @@ -614,7 +614,7 @@ * One technique, using this method, would be: * <pre> * ZoneOffsetTransition trans = rules.getTransition(localDT); - * if (trans == null) { + * if (trans != null) { * // Gap or Overlap: determine what to do from transition * } else { * // Normal case: only one valid offset
--- a/src/java.base/share/classes/java/util/DualPivotQuicksort.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/util/DualPivotQuicksort.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,12 +146,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge @@ -598,12 +612,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge @@ -1086,12 +1114,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge @@ -1574,12 +1616,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge @@ -2158,12 +2214,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge @@ -2701,12 +2771,26 @@ } } - // Check special cases - // Implementation note: variable "right" is increased by 1. - if (run[count] == right++) { // The last run contains one element + // These invariants should hold true: + // run[0] = 0 + // run[<last>] = right + 1; (terminator) + + if (count == 0) { + // A single equal run + return; + } else if (count == 1 && run[count] > right) { + // Either a single ascending or a transformed descending run. + // Always check that a final run is a proper terminator, otherwise + // we have an unterminated trailing run, to handle downstream. + return; + } + right++; + if (run[count] < right) { + // Corner case: the final run is not a terminator. This may happen + // if a final run is an equals run, or there is a single-element run + // at the end. Fix up by adding a proper terminator at the end. + // Note that we terminate with (right + 1), incremented earlier. run[++count] = right; - } else if (count <= 1) { // The array is already sorted - return; } // Determine alternation base for merge
--- a/src/java.base/share/classes/java/util/Objects.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/util/Objects.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,9 @@ package java.util; -import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.Preconditions; +import jdk.internal.vm.annotation.ForceInline; -import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Supplier; /** @@ -349,172 +348,6 @@ } /** - * Maps out-of-bounds values to a runtime exception. - * - * @param checkKind the kind of bounds check, whose name may correspond - * to the name of one of the range check methods, checkIndex, - * checkFromToIndex, checkFromIndexSize - * @param args the out-of-bounds arguments that failed the range check. - * If the checkKind corresponds a the name of a range check method - * then the bounds arguments are those that can be passed in order - * to the method. - * @param oobef the exception formatter that when applied with a checkKind - * and a list out-of-bounds arguments returns a runtime exception. - * If {@code null} then, it is as if an exception formatter was - * supplied that returns {@link IndexOutOfBoundsException} for any - * given arguments. - * @return the runtime exception - */ - private static RuntimeException outOfBounds( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobef, - String checkKind, - Integer... args) { - List<Integer> largs = List.of(args); - RuntimeException e = oobef == null - ? null : oobef.apply(checkKind, largs); - return e == null - ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; - } - - // Specific out-of-bounds exception producing methods that avoid - // the varargs-based code in the critical methods there by reducing their - // the byte code size, and therefore less likely to peturb inlining - - private static RuntimeException outOfBoundsCheckIndex( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int index, int length) { - return outOfBounds(oobe, "checkIndex", index, length); - } - - private static RuntimeException outOfBoundsCheckFromToIndex( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int fromIndex, int toIndex, int length) { - return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); - } - - private static RuntimeException outOfBoundsCheckFromIndexSize( - BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, - int fromIndex, int size, int length) { - return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); - } - - /** - * Returns an out-of-bounds exception formatter from an given exception - * factory. The exception formatter is a function that formats an - * out-of-bounds message from its arguments and applies that message to the - * given exception factory to produce and relay an exception. - * - * <p>The exception formatter accepts two arguments: a {@code String} - * describing the out-of-bounds range check that failed, referred to as the - * <em>check kind</em>; and a {@code List<Integer>} containing the - * out-of-bound integer values that failed the check. The list of - * out-of-bound values is not modified. - * - * <p>Three check kinds are supported {@code checkIndex}, - * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding - * respectively to the specified application of an exception formatter as an - * argument to the out-of-bounds range check methods - * {@link #checkIndex(int, int, BiFunction) checkIndex}, - * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and - * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. - * Thus a supported check kind corresponds to a method name and the - * out-of-bound integer values correspond to method argument values, in - * order, preceding the exception formatter argument (similar in many - * respects to the form of arguments required for a reflective invocation of - * such a range check method). - * - * <p>Formatter arguments conforming to such supported check kinds will - * produce specific exception messages describing failed out-of-bounds - * checks. Otherwise, more generic exception messages will be produced in - * any of the following cases: the check kind is supported but fewer - * or more out-of-bounds values are supplied, the check kind is not - * supported, the check kind is {@code null}, or the list of out-of-bound - * values is {@code null}. - * - * @apiNote - * This method produces an out-of-bounds exception formatter that can be - * passed as an argument to any of the supported out-of-bounds range check - * methods declared by {@code Objects}. For example, a formatter producing - * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a - * {@code static final} field as follows: - * <pre>{@code - * static final - * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF = - * outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new); - * }</pre> - * The formatter instance {@code AIOOBEF} may be passed as an argument to an - * out-of-bounds range check method, such as checking if an {@code index} - * is within the bounds of a {@code limit}: - * <pre>{@code - * checkIndex(index, limit, AIOOBEF); - * }</pre> - * If the bounds check fails then the range check method will throw an - * {@code ArrayIndexOutOfBoundsException} with an appropriate exception - * message that is a produced from {@code AIOOBEF} as follows: - * <pre>{@code - * AIOOBEF.apply("checkIndex", List.of(index, limit)); - * }</pre> - * - * @param f the exception factory, that produces an exception from a message - * where the message is produced and formatted by the returned - * exception formatter. If this factory is stateless and side-effect - * free then so is the returned formatter. - * Exceptions thrown by the factory are relayed to the caller - * of the returned formatter. - * @param <X> the type of runtime exception to be returned by the given - * exception factory and relayed by the exception formatter - * @return the out-of-bounds exception formatter - */ - public static <X extends RuntimeException> - BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) { - // Use anonymous class to avoid bootstrap issues if this method is - // used early in startup - return new BiFunction<String, List<Integer>, X>() { - @Override - public X apply(String checkKind, List<Integer> args) { - return f.apply(outOfBoundsMessage(checkKind, args)); - } - }; - } - - private static String outOfBoundsMessage(String checkKind, List<Integer> args) { - if (checkKind == null && args == null) { - return String.format("Range check failed"); - } else if (checkKind == null) { - return String.format("Range check failed: %s", args); - } else if (args == null) { - return String.format("Range check failed: %s", checkKind); - } - - int argSize = 0; - switch (checkKind) { - case "checkIndex": - argSize = 2; - break; - case "checkFromToIndex": - case "checkFromIndexSize": - argSize = 3; - break; - default: - } - - // Switch to default if fewer or more arguments than required are supplied - switch ((args.size() != argSize) ? "" : checkKind) { - case "checkIndex": - return String.format("Index %d out-of-bounds for length %d", - args.get(0), args.get(1)); - case "checkFromToIndex": - return String.format("Range [%d, %d) out-of-bounds for length %d", - args.get(0), args.get(1), args.get(2)); - case "checkFromIndexSize": - return String.format("Range [%d, %<d + %d) out-of-bounds for length %d", - args.get(0), args.get(1), args.get(2)); - default: - return String.format("Range check failed: %s %s", checkKind, args); - } - } - - /** * Checks if the {@code index} is within the bounds of the range from * {@code 0} (inclusive) to {@code length} (exclusive). * @@ -526,72 +359,16 @@ * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkIndex(int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param index the index * @param length the upper-bound (exclusive) of the range * @return {@code index} if it is within bounds of the range * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds * @since 9 */ + @ForceInline public static int checkIndex(int index, int length) { - return checkIndex(index, length, null); - } - - /** - * Checks if the {@code index} is within the bounds of the range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - * <p>The {@code index} is defined to be out-of-bounds if any of the - * following inequalities is true: - * <ul> - * <li>{@code index < 0}</li> - * <li>{@code index >= length}</li> - * <li>{@code length < 0}, which is implied from the former inequalities</li> - * </ul> - * - * <p>If the {@code index} is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkIndex}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code index} and {@code length}. - * - * @param <X> the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param index the index - * @param length the upper-bound (exclusive) of the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code index} if it is within bounds of the range - * @throws X if the {@code index} is out-of-bounds and the exception - * formatter is non-{@code null} - * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds - * and the exception formatter is {@code null} - * @since 9 - * - * @implNote - * This method is made intrinsic in optimizing compilers to guide them to - * perform unsigned comparisons of the index and length when it is known the - * length is a non-negative value (such as that of an array length or from - * the upper bound of a loop) - */ - @HotSpotIntrinsicCandidate - public static <X extends RuntimeException> - int checkIndex(int index, int length, - BiFunction<String, List<Integer>, X> oobef) { - if (index < 0 || index >= length) - throw outOfBoundsCheckIndex(oobef, index, length); - return index; + return Preconditions.checkIndex(index, length, null); } /** @@ -608,12 +385,6 @@ * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkFromToIndex(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-range * @param toIndex the upper-bound (exclusive) of the sub-range * @param length the upper-bound (exclusive) the range @@ -623,54 +394,7 @@ */ public static int checkFromToIndex(int fromIndex, int toIndex, int length) { - return checkFromToIndex(fromIndex, toIndex, length, null); - } - - /** - * Checks if the sub-range from {@code fromIndex} (inclusive) to - * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} - * (inclusive) to {@code length} (exclusive). - * - * <p>The sub-range is defined to be out-of-bounds if any of the following - * inequalities is true: - * <ul> - * <li>{@code fromIndex < 0}</li> - * <li>{@code fromIndex > toIndex}</li> - * <li>{@code toIndex > length}</li> - * <li>{@code length < 0}, which is implied from the former inequalities</li> - * </ul> - * - * <p>If the sub-range is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkFromToIndex}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. - * - * @param <X> the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param fromIndex the lower-bound (inclusive) of the sub-range - * @param toIndex the upper-bound (exclusive) of the sub-range - * @param length the upper-bound (exclusive) the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code fromIndex} if the sub-range within bounds of the range - * @throws X if the sub-range is out-of-bounds and the exception factory - * function is non-{@code null} - * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and - * the exception factory function is {@code null} - * @since 9 - */ - public static <X extends RuntimeException> - int checkFromToIndex(int fromIndex, int toIndex, int length, - BiFunction<String, List<Integer>, X> oobef) { - if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) - throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); - return fromIndex; + return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null); } /** @@ -687,12 +411,6 @@ * <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * - * <p>This method behaves as if {@link #checkFromIndexSize(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-interval * @param size the size of the sub-range * @param length the upper-bound (exclusive) of the range @@ -702,54 +420,7 @@ */ public static int checkFromIndexSize(int fromIndex, int size, int length) { - return checkFromIndexSize(fromIndex, size, length, null); + return Preconditions.checkFromIndexSize(fromIndex, size, length, null); } - /** - * Checks if the sub-range from {@code fromIndex} (inclusive) to - * {@code fromIndex + size} (exclusive) is within the bounds of range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - * <p>The sub-range is defined to be out-of-bounds if any of the following - * inequalities is true: - * <ul> - * <li>{@code fromIndex < 0}</li> - * <li>{@code size < 0}</li> - * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> - * <li>{@code length < 0}, which is implied from the former inequalities</li> - * </ul> - * - * <p>If the sub-range is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkFromIndexSize}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code fromIndex}, {@code size}, and - * {@code length}. - * - * @param <X> the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param fromIndex the lower-bound (inclusive) of the sub-interval - * @param size the size of the sub-range - * @param length the upper-bound (exclusive) of the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code fromIndex} if the sub-range within bounds of the range - * @throws X if the sub-range is out-of-bounds and the exception factory - * function is non-{@code null} - * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and - * the exception factory function is {@code null} - * @since 9 - */ - public static <X extends RuntimeException> - int checkFromIndexSize(int fromIndex, int size, int length, - BiFunction<String, List<Integer>, X> oobef) { - if ((length | fromIndex | size) < 0 || size > length - fromIndex) - throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); - return fromIndex; - } }
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java Wed May 18 12:04:26 2016 -0700 @@ -462,9 +462,13 @@ private class ZipEntryIterator implements Enumeration<ZipEntry>, Iterator<ZipEntry> { private int i = 0; + private final int entryCount; public ZipEntryIterator() { - ensureOpen(); + synchronized (ZipFile.this) { + ensureOpen(); + this.entryCount = zsrc.total; + } } public boolean hasMoreElements() { @@ -472,10 +476,7 @@ } public boolean hasNext() { - synchronized (ZipFile.this) { - ensureOpen(); - return i < zsrc.total; - } + return i < entryCount; } public ZipEntry nextElement() { @@ -485,7 +486,7 @@ public ZipEntry next() { synchronized (ZipFile.this) { ensureOpen(); - if (i >= zsrc.total) { + if (!hasNext()) { throw new NoSuchElementException(); } // each "entry" has 3 ints in table entries @@ -526,34 +527,34 @@ /* Checks ensureOpen() before invoke this method */ private ZipEntry getZipEntry(String name, int pos) { byte[] cen = zsrc.cen; - ZipEntry e = new ZipEntry(); int nlen = CENNAM(cen, pos); int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); - e.flag = CENFLG(cen, pos); // get the flag first - if (name != null) { - e.name = name; - } else { - if (!zc.isUTF8() && (e.flag & EFS) != 0) { - e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen); + int flag = CENFLG(cen, pos); + if (name == null) { + if (!zc.isUTF8() && (flag & EFS) != 0) { + name = zc.toStringUTF8(cen, pos + CENHDR, nlen); } else { - e.name = zc.toString(cen, pos + CENHDR, nlen); + name = zc.toString(cen, pos + CENHDR, nlen); } } + ZipEntry e = new ZipEntry(name); + e.flag = flag; e.xdostime = CENTIM(cen, pos); e.crc = CENCRC(cen, pos); e.size = CENLEN(cen, pos); e.csize = CENSIZ(cen, pos); e.method = CENHOW(cen, pos); if (elen != 0) { - e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen, - pos + CENHDR + nlen + elen), true); + int start = pos + CENHDR + nlen; + e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true); } if (clen != 0) { - if (!zc.isUTF8() && (e.flag & EFS) != 0) { - e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen); + int start = pos + CENHDR + nlen + elen; + if (!zc.isUTF8() && (flag & EFS) != 0) { + e.comment = zc.toStringUTF8(cen, start, clen); } else { - e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen); + e.comment = zc.toString(cen, start, clen); } } return e; @@ -817,7 +818,7 @@ ); } - /* + /** * Returns an array of strings representing the names of all entries * that begin with "META-INF/" (case ignored). This method is used * in JarFile, via SharedSecrets, as an optimization when looking up @@ -827,14 +828,14 @@ private String[] getMetaInfEntryNames() { synchronized (this) { ensureOpen(); - if (zsrc.metanames.size() == 0) { + if (zsrc.metanames == null) { return null; } - String[] names = new String[zsrc.metanames.size()]; + String[] names = new String[zsrc.metanames.length]; byte[] cen = zsrc.cen; for (int i = 0; i < names.length; i++) { - int pos = zsrc.metanames.get(i); - names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos), + int pos = zsrc.metanames[i]; + names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos), StandardCharsets.UTF_8); } return names; @@ -850,7 +851,7 @@ private long locpos; // position of first LOC header (usually 0) private byte[] comment; // zip file comment // list of meta entries in META-INF dir - private ArrayList<Integer> metanames = new ArrayList<>(); + private int[] metanames; private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true) // A Hashmap for all entries. @@ -1159,7 +1160,7 @@ int next = -1; // list for all meta entries - metanames = new ArrayList<>(); + ArrayList<Integer> metanamesList = null; // Iterate through the entries in the central directory int i = 0; @@ -1194,13 +1195,21 @@ idx = addEntry(idx, hash, next, pos); // Adds name to metanames. if (isMetaName(cen, pos + CENHDR, nlen)) { - metanames.add(pos); + if (metanamesList == null) + metanamesList = new ArrayList<>(4); + metanamesList.add(pos); } // skip ext and comment pos += (CENHDR + nlen + elen + clen); i++; } total = i; + if (metanamesList != null) { + metanames = new int[metanamesList.size()]; + for (int j = 0, len = metanames.length; j < len; j++) { + metanames[j] = metanamesList.get(j); + } + } if (pos + ENDHDR != cen.length) { zerror("invalid CEN header (bad header size)"); } @@ -1265,30 +1274,23 @@ } } - private static byte[] metainf = new byte[] { - 'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/', - }; - - /* - * Returns true if the specified entry's name begins with the string - * "META-INF/" irrespective of case. + /** + * Returns true if the bytes represent a non-directory name + * beginning with "META-INF/", disregarding ASCII case. */ - private static boolean isMetaName(byte[] name, int off, int len) { - if (len < 9 || (name[off] != 'M' && name[off] != 'm')) { // sizeof("META-INF/") - 1 - return false; - } - off++; - for (int i = 1; i < metainf.length; i++) { - byte c = name[off++]; - // Avoid toupper; it's locale-dependent - if (c >= 'a' && c <= 'z') { - c += 'A' - 'a'; - } - if (metainf[i] != c) { - return false; - } - } - return true; + private static boolean isMetaName(byte[] name, int off, int len) { + // Use the "oldest ASCII trick in the book" + return len > 9 // "META-INF/".length() + && name[off + len - 1] != '/' // non-directory + && (name[off++] | 0x20) == 'm' + && (name[off++] | 0x20) == 'e' + && (name[off++] | 0x20) == 't' + && (name[off++] | 0x20) == 'a' + && (name[off++] ) == '-' + && (name[off++] | 0x20) == 'i' + && (name[off++] | 0x20) == 'n' + && (name[off++] | 0x20) == 'f' + && (name[off] ) == '/'; } /*
--- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Wed May 18 12:04:26 2016 -0700 @@ -68,13 +68,14 @@ if (s != null && s.length() > 0) bcp = toURLClassPath(s); - // we have a class path if -cp is specified or -m is not specified + // we have a class path if -cp is specified or -m is not specified. + // If neither is specified then default to -cp <working directory>. URLClassPath ucp = null; String mainMid = System.getProperty("jdk.module.main"); String cp = System.getProperty("java.class.path"); - if (mainMid == null && (cp == null || cp.length() == 0)) - cp = "."; - if (cp != null && cp.length() > 0) + if (mainMid == null && cp == null) + cp = ""; + if (cp != null) ucp = toURLClassPath(cp); @@ -197,7 +198,7 @@ * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch */ void appendToClassPathForInstrumentation(String path) { - appendToUCP(path, ucp); + addClassPathToUCP(path, ucp); } /** @@ -224,7 +225,7 @@ */ private static URLClassPath toURLClassPath(String cp) { URLClassPath ucp = new URLClassPath(new URL[0]); - appendToUCP(cp, ucp); + addClassPathToUCP(cp, ucp); return ucp; } @@ -232,20 +233,28 @@ * Converts the elements in the given class path to file URLs and adds * them to the given URLClassPath. */ - private static void appendToUCP(String cp, URLClassPath ucp) { - String[] elements = cp.split(File.pathSeparator); - if (elements.length == 0) { - // contains path separator(s) only, default to current directory - // to be compatible with long standing behavior - elements = new String[] { "" }; + private static void addClassPathToUCP(String cp, URLClassPath ucp) { + int off = 0; + int next; + while ((next = cp.indexOf(File.pathSeparator, off)) != -1) { + addURLToUCP(cp.substring(off, next), ucp); + off = next + 1; } - for (String s: elements) { - try { - URL url = Paths.get(s).toRealPath().toUri().toURL(); - ucp.addURL(url); - } catch (InvalidPathException | IOException ignore) { - // malformed path string or class path element does not exist - } + + // remaining + addURLToUCP(cp.substring(off), ucp); + } + + /** + * Attempts to convert to the given string to a file URL and adds it + * to the given URLClassPath. + */ + private static void addURLToUCP(String s, URLClassPath ucp) { + try { + URL url = Paths.get(s).toRealPath().toUri().toURL(); + ucp.addURL(url); + } catch (InvalidPathException | IOException ignore) { + // malformed path string or class path element does not exist } }
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed May 18 12:04:26 2016 -0700 @@ -33,6 +33,7 @@ import jdk.internal.misc.VM; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.vm.annotation.ForceInline; /** @@ -209,46 +210,103 @@ /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native byte getByte(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native short getShort(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native char getChar(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native long getLong(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native float getFloat(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native double getDouble(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putDouble(Object o, long offset, double x); + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address may be determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + * @see #getInt(Object, long) + */ + @ForceInline + public long getAddress(Object o, long offset) { + if (ADDRESS_SIZE == 4) { + return Integer.toUnsignedLong(getInt(o, offset)); + } else { + return getLong(o, offset); + } + } + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>The number of bytes actually written at the target address may be + * determined by consulting {@link #addressSize}. + * + * @see #allocateMemory + * @see #putInt(Object, long, int) + */ + @ForceInline + public void putAddress(Object o, long offset, long x) { + if (ADDRESS_SIZE == 4) { + putInt(o, offset, (int)x); + } else { + putLong(o, offset, x); + } + } + // These read VM internal data. /** @@ -287,8 +345,10 @@ * * @see #allocateMemory */ - @HotSpotIntrinsicCandidate - public native byte getByte(long address); + @ForceInline + public byte getByte(long address) { + return getByte(null, address); + } /** * Stores a value into a given memory address. If the address is zero, or @@ -297,75 +357,94 @@ * * @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native void putByte(long address, byte x); + @ForceInline + public void putByte(long address, byte x) { + putByte(null, address, x); + } /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native short getShort(long address); + @ForceInline + public short getShort(long address) { + return getShort(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putShort(long address, short x); + @ForceInline + public void putShort(long address, short x) { + putShort(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native char getChar(long address); + @ForceInline + public char getChar(long address) { + return getChar(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putChar(long address, char x); + @ForceInline + public void putChar(long address, char x) { + putChar(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native int getInt(long address); + @ForceInline + public int getInt(long address) { + return getInt(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putInt(long address, int x); + @ForceInline + public void putInt(long address, int x) { + putInt(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native long getLong(long address); + @ForceInline + public long getLong(long address) { + return getLong(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putLong(long address, long x); + @ForceInline + public void putLong(long address, long x) { + putLong(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native float getFloat(long address); + @ForceInline + public float getFloat(long address) { + return getFloat(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putFloat(long address, float x); + @ForceInline + public void putFloat(long address, float x) { + putFloat(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native double getDouble(long address); + @ForceInline + public double getDouble(long address) { + return getDouble(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putDouble(long address, double x); + @ForceInline + public void putDouble(long address, double x) { + putDouble(null, address, x); + } - /** - * Fetches a native pointer from a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - * <p>If the native pointer is less than 64 bits wide, it is extended as - * an unsigned number to a Java long. The pointer may be indexed by any - * given byte offset, simply by adding that offset (as a simple integer) to - * the long representing the pointer. The number of bytes actually read - * from the target address may be determined by consulting {@link - * #addressSize}. - * - * @see #allocateMemory - */ - @HotSpotIntrinsicCandidate - public native long getAddress(long address); + /** @see #getAddress(Object, long) */ + @ForceInline + public long getAddress(long address) { + return getAddress(null, address); + } - /** - * Stores a native pointer into a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - * <p>The number of bytes actually written at the target address may be - * determined by consulting {@link #addressSize}. - * - * @see #getAddress(long) - */ - @HotSpotIntrinsicCandidate - public native void putAddress(long address, long x); + /** @see #putAddress(Object, long, long) */ + @ForceInline + public void putAddress(long address, long x) { + putAddress(null, address, x); + } @@ -1271,6 +1350,13 @@ return compareAndSwapObject(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectVolatile(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -1325,6 +1411,13 @@ return compareAndSwapInt(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntVolatile(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -1379,6 +1472,13 @@ return compareAndSwapLong(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongVolatile(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + /** * Fetches a reference value from a given Java variable, with volatile * load semantics. Otherwise identical to {@link #getObject(Object, long)}
--- a/src/java.base/share/classes/jdk/internal/misc/VM.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java Wed May 18 12:04:26 2016 -0700 @@ -390,10 +390,25 @@ private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; /* - * Returns the first non-null class loader up the execution stack, - * or null if only code from the null class loader is on the stack. + * Returns the first user-defined class loader up the execution stack, + * or the platform class loader if only code from the platform or + * bootstrap class loader is on the stack. */ - public static native ClassLoader latestUserDefinedLoader(); + public static ClassLoader latestUserDefinedLoader() { + ClassLoader loader = latestUserDefinedLoader0(); + return loader != null ? loader : ClassLoader.getPlatformClassLoader(); + } + + /* + * Returns the first user-defined class loader up the execution stack, + * or null if only code from the platform or bootstrap class loader is + * on the stack. VM does not keep a reference of platform loader and so + * it returns null. + * + * This method should be replaced with StackWalker::walk and then we can + * remove the logic in the VM. + */ + private static native ClassLoader latestUserDefinedLoader0(); /** * Returns {@code true} if we are in a set UID program.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/jdk/internal/util/Preconditions.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 jdk.internal.util; + +import jdk.internal.HotSpotIntrinsicCandidate; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Utility methods to check if state or arguments are correct. + * + */ +public class Preconditions { + + /** + * Maps out-of-bounds values to a runtime exception. + * + * @param checkKind the kind of bounds check, whose name may correspond + * to the name of one of the range check methods, checkIndex, + * checkFromToIndex, checkFromIndexSize + * @param args the out-of-bounds arguments that failed the range check. + * If the checkKind corresponds a the name of a range check method + * then the bounds arguments are those that can be passed in order + * to the method. + * @param oobef the exception formatter that when applied with a checkKind + * and a list out-of-bounds arguments returns a runtime exception. + * If {@code null} then, it is as if an exception formatter was + * supplied that returns {@link IndexOutOfBoundsException} for any + * given arguments. + * @return the runtime exception + */ + private static RuntimeException outOfBounds( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobef, + String checkKind, + Integer... args) { + List<Integer> largs = List.of(args); + RuntimeException e = oobef == null + ? null : oobef.apply(checkKind, largs); + return e == null + ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; + } + + private static RuntimeException outOfBoundsCheckIndex( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int index, int length) { + return outOfBounds(oobe, "checkIndex", index, length); + } + + private static RuntimeException outOfBoundsCheckFromToIndex( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int fromIndex, int toIndex, int length) { + return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); + } + + private static RuntimeException outOfBoundsCheckFromIndexSize( + BiFunction<String, List<Integer>, ? extends RuntimeException> oobe, + int fromIndex, int size, int length) { + return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); + } + + /** + * Returns an out-of-bounds exception formatter from an given exception + * factory. The exception formatter is a function that formats an + * out-of-bounds message from its arguments and applies that message to the + * given exception factory to produce and relay an exception. + * + * <p>The exception formatter accepts two arguments: a {@code String} + * describing the out-of-bounds range check that failed, referred to as the + * <em>check kind</em>; and a {@code List<Integer>} containing the + * out-of-bound integer values that failed the check. The list of + * out-of-bound values is not modified. + * + * <p>Three check kinds are supported {@code checkIndex}, + * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding + * respectively to the specified application of an exception formatter as an + * argument to the out-of-bounds range check methods + * {@link #checkIndex(int, int, BiFunction) checkIndex}, + * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and + * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. + * Thus a supported check kind corresponds to a method name and the + * out-of-bound integer values correspond to method argument values, in + * order, preceding the exception formatter argument (similar in many + * respects to the form of arguments required for a reflective invocation of + * such a range check method). + * + * <p>Formatter arguments conforming to such supported check kinds will + * produce specific exception messages describing failed out-of-bounds + * checks. Otherwise, more generic exception messages will be produced in + * any of the following cases: the check kind is supported but fewer + * or more out-of-bounds values are supplied, the check kind is not + * supported, the check kind is {@code null}, or the list of out-of-bound + * values is {@code null}. + * + * @apiNote + * This method produces an out-of-bounds exception formatter that can be + * passed as an argument to any of the supported out-of-bounds range check + * methods declared by {@code Objects}. For example, a formatter producing + * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a + * {@code static final} field as follows: + * <pre>{@code + * static final + * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF = + * outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new); + * }</pre> + * The formatter instance {@code AIOOBEF} may be passed as an argument to an + * out-of-bounds range check method, such as checking if an {@code index} + * is within the bounds of a {@code limit}: + * <pre>{@code + * checkIndex(index, limit, AIOOBEF); + * }</pre> + * If the bounds check fails then the range check method will throw an + * {@code ArrayIndexOutOfBoundsException} with an appropriate exception + * message that is a produced from {@code AIOOBEF} as follows: + * <pre>{@code + * AIOOBEF.apply("checkIndex", List.of(index, limit)); + * }</pre> + * + * @param f the exception factory, that produces an exception from a message + * where the message is produced and formatted by the returned + * exception formatter. If this factory is stateless and side-effect + * free then so is the returned formatter. + * Exceptions thrown by the factory are relayed to the caller + * of the returned formatter. + * @param <X> the type of runtime exception to be returned by the given + * exception factory and relayed by the exception formatter + * @return the out-of-bounds exception formatter + */ + public static <X extends RuntimeException> + BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) { + // Use anonymous class to avoid bootstrap issues if this method is + // used early in startup + return new BiFunction<String, List<Integer>, X>() { + @Override + public X apply(String checkKind, List<Integer> args) { + return f.apply(outOfBoundsMessage(checkKind, args)); + } + }; + } + + private static String outOfBoundsMessage(String checkKind, List<Integer> args) { + if (checkKind == null && args == null) { + return String.format("Range check failed"); + } else if (checkKind == null) { + return String.format("Range check failed: %s", args); + } else if (args == null) { + return String.format("Range check failed: %s", checkKind); + } + + int argSize = 0; + switch (checkKind) { + case "checkIndex": + argSize = 2; + break; + case "checkFromToIndex": + case "checkFromIndexSize": + argSize = 3; + break; + default: + } + + // Switch to default if fewer or more arguments than required are supplied + switch ((args.size() != argSize) ? "" : checkKind) { + case "checkIndex": + return String.format("Index %d out-of-bounds for length %d", + args.get(0), args.get(1)); + case "checkFromToIndex": + return String.format("Range [%d, %d) out-of-bounds for length %d", + args.get(0), args.get(1), args.get(2)); + case "checkFromIndexSize": + return String.format("Range [%d, %<d + %d) out-of-bounds for length %d", + args.get(0), args.get(1), args.get(2)); + default: + return String.format("Range check failed: %s %s", checkKind, args); + } + } + + /** + * Checks if the {@code index} is within the bounds of the range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The {@code index} is defined to be out-of-bounds if any of the + * following inequalities is true: + * <ul> + * <li>{@code index < 0}</li> + * <li>{@code index >= length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the {@code index} is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code index} and {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param index the index + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code index} if it is within bounds of the range + * @throws X if the {@code index} is out-of-bounds and the exception + * formatter is non-{@code null} + * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds + * and the exception formatter is {@code null} + * @since 9 + * + * @implNote + * This method is made intrinsic in optimizing compilers to guide them to + * perform unsigned comparisons of the index and length when it is known the + * length is a non-negative value (such as that of an array length or from + * the upper bound of a loop) + */ + @HotSpotIntrinsicCandidate + public static <X extends RuntimeException> + int checkIndex(int index, int length, + BiFunction<String, List<Integer>, X> oobef) { + if (index < 0 || index >= length) + throw outOfBoundsCheckIndex(oobef, index, length); + return index; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} + * (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code fromIndex > toIndex}</li> + * <li>{@code toIndex > length}</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromToIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-range + * @param toIndex the upper-bound (exclusive) of the sub-range + * @param length the upper-bound (exclusive) the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static <X extends RuntimeException> + int checkFromToIndex(int fromIndex, int toIndex, int length, + BiFunction<String, List<Integer>, X> oobef) { + if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) + throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); + return fromIndex; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code fromIndex + size} (exclusive) is within the bounds of range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + * <p>The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + * <ul> + * <li>{@code fromIndex < 0}</li> + * <li>{@code size < 0}</li> + * <li>{@code fromIndex + size > length}, taking into account integer overflow</li> + * <li>{@code length < 0}, which is implied from the former inequalities</li> + * </ul> + * + * <p>If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromIndexSize}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code size}, and + * {@code length}. + * + * @param <X> the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-interval + * @param size the size of the sub-range + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static <X extends RuntimeException> + int checkFromIndexSize(int fromIndex, int size, int length, + BiFunction<String, List<Integer>, X> oobef) { + if ((length | fromIndex | size) < 0 || size > length - fromIndex) + throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); + return fromIndex; + } +}
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties Wed May 18 12:04:26 2016 -0700 @@ -100,7 +100,6 @@ \ -Xdiag show additional diagnostic messages\n\ \ -Xdiag:resolver show resolver diagnostic messages\n\ \ -Xnoclassgc disable class garbage collection\n\ -\ -Xincgc enable incremental garbage collection\n\ \ -Xloggc:<file> log GC status to a file with time stamps\n\ \ -Xbatch disable background compilation\n\ \ -Xms<size> set initial Java heap size\n\
--- a/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -441,17 +441,89 @@ (outOfs < 0) || ((out.length - outOfs) < len)) { throw new ArrayIndexOutOfBoundsException(); } - len += outOfs; - while (outOfs < len) { - long i = in[inOfs++]; - out[outOfs++] = (byte)(i >> 56); - out[outOfs++] = (byte)(i >> 48); - out[outOfs++] = (byte)(i >> 40); - out[outOfs++] = (byte)(i >> 32); - out[outOfs++] = (byte)(i >> 24); - out[outOfs++] = (byte)(i >> 16); - out[outOfs++] = (byte)(i >> 8); - out[outOfs++] = (byte)(i ); + if (littleEndianUnaligned) { + outOfs += byteArrayOfs; + len += outOfs; + while (outOfs < len) { + unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++])); + outOfs += 8; + } + } else { + len += outOfs; + while (outOfs < len) { + long i = in[inOfs++]; + out[outOfs++] = (byte)(i >> 56); + out[outOfs++] = (byte)(i >> 48); + out[outOfs++] = (byte)(i >> 40); + out[outOfs++] = (byte)(i >> 32); + out[outOfs++] = (byte)(i >> 24); + out[outOfs++] = (byte)(i >> 16); + out[outOfs++] = (byte)(i >> 8); + out[outOfs++] = (byte)(i ); + } + } + } + + /** + * byte[] to long[] conversion, little endian byte order + */ + static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) { + if ((inOfs < 0) || ((in.length - inOfs) < len) || + ((outOfs < 0) || (out.length - outOfs) < len/8)) { + throw new ArrayIndexOutOfBoundsException(); + } + if (littleEndianUnaligned) { + inOfs += byteArrayOfs; + len += inOfs; + while (inOfs < len) { + out[outOfs++] = unsafe.getLong(in, (long)inOfs); + inOfs += 8; + } + } else { + len += inOfs; + while (inOfs < len) { + out[outOfs++] = ((in[inOfs ] & 0xffL) + | ((in[inOfs + 1] & 0xffL) << 8) + | ((in[inOfs + 2] & 0xffL) << 16) + | ((in[inOfs + 3] & 0xffL) << 24) + | ((in[inOfs + 4] & 0xffL) << 32) + | ((in[inOfs + 5] & 0xffL) << 40) + | ((in[inOfs + 6] & 0xffL) << 48) + | ((in[inOfs + 7] & 0xffL) << 56)); + inOfs += 8; + } + } + } + + + /** + * long[] to byte[] conversion, little endian byte order + */ + static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) { + if ((inOfs < 0) || ((in.length - inOfs) < len/8) || + (outOfs < 0) || ((out.length - outOfs) < len)) { + throw new ArrayIndexOutOfBoundsException(); + } + if (littleEndianUnaligned) { + outOfs += byteArrayOfs; + len += outOfs; + while (outOfs < len) { + unsafe.putLong(out, (long)outOfs, in[inOfs++]); + outOfs += 8; + } + } else { + len += outOfs; + while (outOfs < len) { + long i = in[inOfs++]; + out[outOfs++] = (byte)(i ); + out[outOfs++] = (byte)(i >> 8); + out[outOfs++] = (byte)(i >> 16); + out[outOfs++] = (byte)(i >> 24); + out[outOfs++] = (byte)(i >> 32); + out[outOfs++] = (byte)(i >> 40); + out[outOfs++] = (byte)(i >> 48); + out[outOfs++] = (byte)(i >> 56); + } } } }
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,14 +259,10 @@ private static final Debug debug = Debug.getInstance("policy"); - private static final String NONE = "NONE"; - private static final String P11KEYSTORE = "PKCS11"; - private static final String SELF = "${{self}}"; private static final String X500PRINCIPAL = "javax.security.auth.x500.X500Principal"; private static final String POLICY = "java.security.policy"; - private static final String SECURITY_MANAGER = "java.security.manager"; private static final String POLICY_URL = "policy.url."; private static final String AUTH_POLICY = "java.security.auth.policy"; private static final String AUTH_POLICY_URL = "auth.policy.url."; @@ -288,6 +284,17 @@ private static final Class<?>[] PARAMS2 = { String.class, String.class }; /** + * When a policy file has a syntax error, the exception code may generate + * another permission check and this can cause the policy file to be parsed + * repeatedly, leading to a StackOverflowError or ClassCircularityError. + * To avoid this, this set is populated with policy files that have been + * previously parsed and have syntax errors, so that they can be + * subsequently ignored. + */ + private static AtomicReference<Set<URL>> badPolicyURLs = + new AtomicReference<>(new HashSet<>()); + + /** * Initializes the Policy object and reads the default policy * configuration file(s) into the Policy object. */ @@ -580,6 +587,16 @@ * @param policyFile the policy Reader object. */ private boolean init(URL policy, PolicyInfo newInfo) { + + // skip parsing policy file if it has been previously parsed and + // has syntax errors + if (badPolicyURLs.get().contains(policy)) { + if (debug != null) { + debug.println("skipping bad policy file: " + policy); + } + return false; + } + boolean success = false; PolicyParser pp = new PolicyParser(expandProperties); InputStreamReader isr = null; @@ -622,13 +639,18 @@ addGrantEntry(ge, keyStore, newInfo); } } catch (PolicyParser.ParsingException pe) { + // record bad policy file to avoid later reparsing it + badPolicyURLs.updateAndGet(k -> { + k.add(policy); + return k; + }); MessageFormat form = new MessageFormat(ResourcesMgr.getString (POLICY + ".error.parsing.policy.message")); Object[] source = {policy, pe.getLocalizedMessage()}; System.err.println(form.format(source)); - if (debug != null) + if (debug != null) { pe.printStackTrace(); - + } } catch (Exception e) { if (debug != null) { debug.println("error parsing "+policy);
--- a/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,7 +213,9 @@ new MessageFormat(ResourcesMgr.getString( "duplicate.keystore.domain.name")); Object[] source = {domainName}; - throw new ParsingException(form.format(source)); + String msg = "duplicate keystore domain name: " + + domainName; + throw new ParsingException(msg, form, source); } } } else { @@ -743,7 +745,8 @@ ResourcesMgr.getString ("expected.expect.read.end.of.file.")); Object[] source = {expect}; - throw new ParsingException(form.format(source)); + String msg = "expected [" + expect + "], read [end of file]"; + throw new ParsingException(msg, form, source); case StreamTokenizer.TT_WORD: if (expect.equalsIgnoreCase(st.sval)) { lookahead = st.nextToken(); @@ -1244,7 +1247,8 @@ MessageFormat form = new MessageFormat(ResourcesMgr.getString( "duplicate.keystore.name")); Object[] source = {keystoreName}; - throw new ParsingException(form.format(source)); + String msg = "duplicate keystore name: " + keystoreName; + throw new ParsingException(msg, form, source); } } @@ -1316,6 +1320,8 @@ private static final long serialVersionUID = -4330692689482574072L; private String i18nMessage; + private MessageFormat form; + private Object[] source; /** * Constructs a ParsingException with the specified @@ -1330,26 +1336,34 @@ i18nMessage = msg; } + public ParsingException(String msg, MessageFormat form, + Object[] source) { + super(msg); + this.form = form; + this.source = source; + } + public ParsingException(int line, String msg) { super("line " + line + ": " + msg); - MessageFormat form = new MessageFormat - (ResourcesMgr.getString("line.number.msg")); - Object[] source = {line, msg}; - i18nMessage = form.format(source); + // don't call form.format unless getLocalizedMessage is called + // to avoid unnecessary permission checks + form = new MessageFormat(ResourcesMgr.getString("line.number.msg")); + source = new Object[] {line, msg}; } public ParsingException(int line, String expect, String actual) { super("line " + line + ": expected [" + expect + "], found [" + actual + "]"); - MessageFormat form = new MessageFormat(ResourcesMgr.getString + // don't call form.format unless getLocalizedMessage is called + // to avoid unnecessary permission checks + form = new MessageFormat(ResourcesMgr.getString ("line.number.expected.expect.found.actual.")); - Object[] source = {line, expect, actual}; - i18nMessage = form.format(source); + source = new Object[] {line, expect, actual}; } @Override public String getLocalizedMessage() { - return i18nMessage; + return i18nMessage != null ? i18nMessage : form.format(source); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/provider/SHA3.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.security.provider; + +import static sun.security.provider.ByteArrayAccess.*; +import java.nio.*; +import java.util.*; +import java.security.*; + +/** + * This class implements the Secure Hash Algorithm SHA-3 developed by + * the National Institute of Standards and Technology along with the + * National Security Agency as defined in FIPS PUB 202. + * + * <p>It implements java.security.MessageDigestSpi, and can be used + * through Java Cryptography Architecture (JCA), as a pluggable + * MessageDigest implementation. + * + * @since 9 + * @author Valerie Peng + */ +abstract class SHA3 extends DigestBase { + + private static final int WIDTH = 200; // in bytes, e.g. 1600 bits + private static final int DM = 5; // dimension of lanes + + private static final int NR = 24; // number of rounds + + // precomputed round constants needed by the step mapping Iota + private static final long[] RC_CONSTANTS = { + 0x01L, 0x8082L, 0x800000000000808aL, + 0x8000000080008000L, 0x808bL, 0x80000001L, + 0x8000000080008081L, 0x8000000000008009L, 0x8aL, + 0x88L, 0x80008009L, 0x8000000aL, + 0x8000808bL, 0x800000000000008bL, 0x8000000000008089L, + 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, + 0x800aL, 0x800000008000000aL, 0x8000000080008081L, + 0x8000000000008080L, 0x80000001L, 0x8000000080008008L, + }; + + private byte[] state; + + /** + * Creates a new SHA-3 object. + */ + SHA3(String name, int digestLength) { + super(name, digestLength, (WIDTH - (2 * digestLength))); + implReset(); + } + + /** + * Core compression function. Processes blockSize bytes at a time + * and updates the state of this object. + */ + void implCompress(byte[] b, int ofs) { + for (int i = 0; i < buffer.length; i++) { + state[i] ^= b[ofs++]; + } + state = keccak(state); + } + + /** + * Return the digest. Subclasses do not need to reset() themselves, + * DigestBase calls implReset() when necessary. + */ + void implDigest(byte[] out, int ofs) { + int numOfPadding = + setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length)); + if (numOfPadding < 1) { + throw new ProviderException("Incorrect pad size: " + numOfPadding); + } + for (int i = 0; i < buffer.length; i++) { + state[i] ^= buffer[i]; + } + state = keccak(state); + System.arraycopy(state, 0, out, ofs, engineGetDigestLength()); + } + + /** + * Resets the internal state to start a new hash. + */ + void implReset() { + state = new byte[WIDTH]; + } + + /** + * Utility function for circular shift the specified long + * value to the left for n bits. + */ + private static long circularShiftLeft(long lane, int n) { + return ((lane << n) | (lane >>> (64 - n))); + } + + /** + * Utility function for padding the specified data based on the + * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required + * for SHA-3 hash (section 6.1). + */ + private static int setPaddingBytes(byte[] in, int len) { + if (len != in.length) { + // erase leftover values + Arrays.fill(in, len, in.length, (byte)0); + // directly store the padding bytes into the input + // as the specified buffer is allocated w/ size = rateR + in[len] |= (byte) 0x06; + in[in.length - 1] |= (byte) 0x80; + } + return (in.length - len); + } + + /** + * Utility function for transforming the specified state from + * the byte array format into array of lanes as defined in + * section 3.1.2. + */ + private static long[][] bytes2Lanes(byte[] s) { + if (s.length != WIDTH) { + throw new ProviderException("Error: incorrect input size " + + s.length); + } + // The conversion traverses along x-axis before y-axis. So, y is the + // first dimension and x is the second dimension. + long[][] s2 = new long[DM][DM]; + int sOfs = 0; + for (int y = 0; y < DM; y++, sOfs += 40) { + b2lLittle(s, sOfs, s2[y], 0, 40); + } + return s2; + } + + /** + * Utility function for transforming the specified arrays of + * lanes into a byte array as defined in section 3.1.3. + */ + private static byte[] lanes2Bytes(long[][] m) { + byte[] s = new byte[WIDTH]; + int sOfs = 0; + // The conversion traverses along x-axis before y-axis. So, y is the + // first dimension and x is the second dimension. + for (int y = 0; y < DM; y++, sOfs += 40) { + l2bLittle(m[y], 0, s, sOfs, 40); + } + return s; + } + + /** + * Step mapping Theta as defined in section 3.2.1 . + */ + private static long[][] smTheta(long[][] a) { + long[] c = new long[DM]; + for (int i = 0; i < DM; i++) { + c[i] = a[0][i]^a[1][i]^a[2][i]^a[3][i]^a[4][i]; + } + long[] d = new long[DM]; + for (int i = 0; i < DM; i++) { + long c1 = c[(i + 4) % DM]; + // left shift and wrap the leftmost bit into the rightmost bit + long c2 = circularShiftLeft(c[(i + 1) % DM], 1); + d[i] = c1^c2; + } + for (int y = 0; y < DM; y++) { + for (int x = 0; x < DM; x++) { + a[y][x] ^= d[x]; + } + } + return a; + } + + /** + * Step mapping Rho as defined in section 3.2.2. + */ + private static long[][] smRho(long[][] a) { + long[][] a2 = new long[DM][DM]; + a2[0][0] = a[0][0]; + int xNext, yNext; + for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) { + int numberOfShift = ((t + 1)*(t + 2)/2) % 64; + a2[y][x] = circularShiftLeft(a[y][x], numberOfShift); + xNext = y; + yNext = (2 * x + 3 * y) % DM; + } + return a2; + } + + /** + * Step mapping Pi as defined in section 3.2.3. + */ + private static long[][] smPi(long[][] a) { + long[][] a2 = new long[DM][DM]; + for (int y = 0; y < DM; y++) { + for (int x = 0; x < DM; x++) { + a2[y][x] = a[x][(x + 3 * y) % DM]; + } + } + return a2; + } + + /** + * Step mapping Chi as defined in section 3.2.4. + */ + private static long[][] smChi(long[][] a) { + long[][] a2 = new long[DM][DM]; + for (int y = 0; y < DM; y++) { + for (int x = 0; x < DM; x++) { + a2[y][x] = a[y][x] ^ + ((a[y][(x + 1) % DM] ^ 0xFFFFFFFFFFFFFFFFL) & + a[y][(x + 2) % DM]); + } + } + return a2; + } + + /** + * Step mapping Iota as defined in section 3.2.5. + * + * @return the processed state array + * @param state the state array to be processed + */ + private static long[][] smIota(long[][] a, int rndIndex) { + a[0][0] ^= RC_CONSTANTS[rndIndex]; + return a; + } + + /** + * The function Keccak as defined in section 5.2 with + * rate r = 1600 and capacity c = (digest length x 2). + */ + private static byte[] keccak(byte[] state) { + long[][] lanes = bytes2Lanes(state); + for (int ir = 0; ir < NR; ir++) { + lanes = smIota(smChi(smPi(smRho(smTheta(lanes)))), ir); + } + return lanes2Bytes(lanes); + } + + public Object clone() throws CloneNotSupportedException { + SHA3 copy = (SHA3) super.clone(); + copy.state = copy.state.clone(); + return copy; + } + + /** + * SHA3-224 implementation class. + */ + public static final class SHA224 extends SHA3 { + public SHA224() { + super("SHA3-224", 28); + } + } + + /** + * SHA3-256 implementation class. + */ + public static final class SHA256 extends SHA3 { + public SHA256() { + super("SHA3-256", 32); + } + } + + /** + * SHAs-384 implementation class. + */ + public static final class SHA384 extends SHA3 { + public SHA384() { + super("SHA3-384", 48); + } + } + + /** + * SHA3-512 implementation class. + */ + public static final class SHA512 extends SHA3 { + public SHA512() { + super("SHA3-512", 64); + } + } +}
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java Wed May 18 12:04:26 2016 -0700 @@ -211,6 +211,25 @@ map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6", "SHA-512/256"); + map.put("MessageDigest.SHA3-224", "sun.security.provider.SHA3$SHA224"); + map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.7", "SHA3-224"); + map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.7", + "SHA3-224"); + + map.put("MessageDigest.SHA3-256", "sun.security.provider.SHA3$SHA256"); + map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.8", "SHA3-256"); + map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.8", + "SHA3-256"); + map.put("MessageDigest.SHA3-384", "sun.security.provider.SHA3$SHA384"); + map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.9", "SHA3-384"); + map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.9", + "SHA3-384"); + map.put("MessageDigest.SHA3-512", "sun.security.provider.SHA3$SHA512"); + map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.10", "SHA3-512"); + map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.10", + "SHA3-512"); + + /* * Algorithm Parameter Generator engines */
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,7 +108,7 @@ * a hash for the certificate verify message is required. */ HandshakeHash(boolean needCertificateVerify) { - clonesNeeded = needCertificateVerify ? 3 : 2; + clonesNeeded = needCertificateVerify ? 4 : 3; } void reserve(ByteBuffer input) {
--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed May 18 12:04:26 2016 -0700 @@ -145,11 +145,10 @@ */ public static boolean isBlockOrSF(String s) { // we currently only support DSA and RSA PKCS7 blocks - if (s.endsWith(".SF") || s.endsWith(".DSA") || - s.endsWith(".RSA") || s.endsWith(".EC")) { - return true; - } - return false; + return s.endsWith(".SF") + || s.endsWith(".DSA") + || s.endsWith(".RSA") + || s.endsWith(".EC"); } /**
--- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed May 18 12:04:26 2016 -0700 @@ -552,58 +552,61 @@ return AlgorithmId.sha512WithECDSA_oid; } - // See if any of the installed providers supply a mapping from - // the given algorithm name to an OID string - String oidString; - if (!initOidTable) { - Provider[] provs = Security.getProviders(); - for (int i=0; i<provs.length; i++) { - for (Enumeration<Object> enum_ = provs[i].keys(); - enum_.hasMoreElements(); ) { - String alias = (String)enum_.nextElement(); - String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); - int index; - if (upperCaseAlias.startsWith("ALG.ALIAS") && - (index=upperCaseAlias.indexOf("OID.", 0)) != -1) { - index += "OID.".length(); - if (index == alias.length()) { - // invalid alias entry - break; - } - if (oidTable == null) { - oidTable = new HashMap<>(); - } - oidString = alias.substring(index); - String stdAlgName = provs[i].getProperty(alias); - if (stdAlgName != null) { - stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH); - } - if (stdAlgName != null && - oidTable.get(stdAlgName) == null) { - oidTable.put(stdAlgName, - new ObjectIdentifier(oidString)); - } - } - } - } - - if (oidTable == null) { - oidTable = Collections.<String,ObjectIdentifier>emptyMap(); - } - initOidTable = true; - } - - return oidTable.get(name.toUpperCase(Locale.ENGLISH)); + return oidTable().get(name.toUpperCase(Locale.ENGLISH)); } private static ObjectIdentifier oid(int ... values) { return ObjectIdentifier.newInternal(values); } - private static boolean initOidTable = false; - private static Map<String,ObjectIdentifier> oidTable; + private static volatile Map<String,ObjectIdentifier> oidTable; private static final Map<ObjectIdentifier,String> nameTable; + /** Returns the oidTable, lazily initializing it on first access. */ + private static Map<String,ObjectIdentifier> oidTable() + throws IOException { + // Double checked locking; safe because oidTable is volatile + Map<String,ObjectIdentifier> tab; + if ((tab = oidTable) == null) { + synchronized (AlgorithmId.class) { + if ((tab = oidTable) == null) + oidTable = tab = computeOidTable(); + } + } + return tab; + } + + /** Collects the algorithm names from the installed providers. */ + private static HashMap<String,ObjectIdentifier> computeOidTable() + throws IOException { + HashMap<String,ObjectIdentifier> tab = new HashMap<>(); + for (Provider provider : Security.getProviders()) { + for (Object key : provider.keySet()) { + String alias = (String)key; + String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); + int index; + if (upperCaseAlias.startsWith("ALG.ALIAS") && + (index=upperCaseAlias.indexOf("OID.", 0)) != -1) { + index += "OID.".length(); + if (index == alias.length()) { + // invalid alias entry + break; + } + String oidString = alias.substring(index); + String stdAlgName = provider.getProperty(alias); + if (stdAlgName != null) { + stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH); + } + if (stdAlgName != null && + tab.get(stdAlgName) == null) { + tab.put(stdAlgName, new ObjectIdentifier(oidString)); + } + } + } + } + return tab; + } + /*****************************************************************/ /*
--- a/src/java.base/share/conf/security/java.policy Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/conf/security/java.policy Wed May 18 12:04:26 2016 -0700 @@ -80,6 +80,10 @@ permission java.security.AllPermission; }; +grant codeBase "jrt:/java.scripting" { + permission java.security.AllPermission; +}; + grant codeBase "jrt:/jdk.scripting.nashorn" { permission java.security.AllPermission; };
--- a/src/java.base/share/native/include/jvmti.h Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/native/include/jvmti.h Wed May 18 12:04:26 2016 -0700 @@ -704,7 +704,8 @@ unsigned int can_generate_resource_exhaustion_heap_events : 1; unsigned int can_generate_resource_exhaustion_threads_events : 1; unsigned int can_generate_early_vmstart : 1; - unsigned int : 6; + unsigned int can_generate_early_class_hook_events : 1; + unsigned int : 5; unsigned int : 16; unsigned int : 16; unsigned int : 16;
--- a/src/java.base/share/native/libjava/VM.c Wed May 18 20:40:17 2016 +0300 +++ b/src/java.base/share/native/libjava/VM.c Wed May 18 12:04:26 2016 -0700 @@ -36,7 +36,7 @@ }; JNIEXPORT jobject JNICALL -Java_jdk_internal_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) { +Java_jdk_internal_misc_VM_latestUserDefinedLoader0(JNIEnv *env, jclass cls) { return JVM_LatestUserDefinedLoader(env); }
--- a/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java Wed May 18 12:04:26 2016 -0700 @@ -26,7 +26,6 @@ import java.io.Closeable; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.LinkedList; import java.util.concurrent.ExecutorService; import java.util.function.Consumer; @@ -557,25 +556,37 @@ } static void logParams(SSLParameters p) { - if (!Log.ssl()) + if (!Log.ssl()) { return; + } + Log.logSSL("SSLParameters:"); if (p == null) { Log.logSSL("Null params"); return; } - for (String cipher : p.getCipherSuites()) { - Log.logSSL("cipher: {0}\n", cipher); + + if (p.getCipherSuites() != null) { + for (String cipher : p.getCipherSuites()) { + Log.logSSL("cipher: {0}\n", cipher); + } } + + // SSLParameters.getApplicationProtocols() can't return null for (String approto : p.getApplicationProtocols()) { Log.logSSL("application protocol: {0}\n", approto); } - for (String protocol : p.getProtocols()) { - Log.logSSL("protocol: {0}\n", protocol); + + if (p.getProtocols() != null) { + for (String protocol : p.getProtocols()) { + Log.logSSL("protocol: {0}\n", protocol); + } } - if (p.getServerNames() != null) + + if (p.getServerNames() != null) { for (SNIServerName sname : p.getServerNames()) { Log.logSSL("server name: {0}\n", sname.toString()); + } } }
--- a/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java Wed May 18 12:04:26 2016 -0700 @@ -35,6 +35,7 @@ import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Iterator; @@ -155,6 +156,15 @@ selmgr.register(exchange); } + /** + * Only used from RawChannel to disconnect the channel from + * the selector + */ + void cancelRegistration(SocketChannel s) { + selmgr.cancel(s); + } + + Http2ClientImpl client2() { return client2; } @@ -220,6 +230,13 @@ selector.wakeup(); } + synchronized void cancel(SocketChannel e) { + SelectionKey key = e.keyFor(selector); + if (key != null) + key.cancel(); + selector.wakeup(); + } + void wakeupSelector() { selector.wakeup(); }
--- a/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java Wed May 18 20:40:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 - */ - -package java.net.http; - -public interface HttpHeaders1 extends HttpHeaders { - public void makeUnmodifiable(); -}
--- a/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java Wed May 18 12:04:26 2016 -0700 @@ -176,7 +176,7 @@ * * @return */ - RawChannel rawChannel() { + RawChannel rawChannel() throws IOException { if (rawchan == null) { rawchan = new RawChannel(request.client(), connection); }
--- a/src/java.httpclient/share/classes/java/net/http/Log.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/Log.java Wed May 18 12:04:26 2016 -0700 @@ -88,7 +88,7 @@ logging |= TRACE; break; case "all": - logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE; + logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL; break; } if (val.startsWith("frames")) {
--- a/src/java.httpclient/share/classes/java/net/http/RawChannel.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/RawChannel.java Wed May 18 12:04:26 2016 -0700 @@ -29,6 +29,7 @@ import java.nio.channels.GatheringByteChannel; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; // // Used to implement WebSocket. Each RawChannel corresponds to a TCP connection @@ -56,9 +57,21 @@ interface NonBlockingEvent extends RawEvent { } - RawChannel(HttpClientImpl client, HttpConnection connection) { + RawChannel(HttpClientImpl client, HttpConnection connection) + throws IOException { this.client = client; this.connection = connection; + SocketChannel chan = connection.channel(); + client.cancelRegistration(chan); + chan.configureBlocking(false); + } + + SocketChannel socketChannel() { + return connection.channel(); + } + + ByteBuffer getRemaining() { + return connection.getRemaining(); } private class RawAsyncEvent extends AsyncEvent {
--- a/src/java.httpclient/share/classes/java/net/http/Stream.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/Stream.java Wed May 18 12:04:26 2016 -0700 @@ -32,6 +32,9 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.BiFunction; import java.util.function.LongConsumer; @@ -409,13 +412,20 @@ @Override HttpResponseImpl getResponse() throws IOException { try { - return getResponseAsync(null).join(); - } catch (Throwable e) { + if (request.timeval() > 0) { + return getResponseAsync(null).get( + request.timeval(), TimeUnit.MILLISECONDS); + } else { + return getResponseAsync(null).join(); + } + } catch (TimeoutException e) { + throw new HttpTimeoutException("Response timed out"); + } catch (InterruptedException | ExecutionException e) { Throwable t = e.getCause(); if (t instanceof IOException) { throw (IOException)t; } - throw e; + throw new IOException(e); } }
--- a/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java Wed May 18 12:04:26 2016 -0700 @@ -24,6 +24,8 @@ */ package java.net.http; +import java.io.UncheckedIOException; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -126,6 +128,8 @@ return CompletableFuture.completedFuture(result); } catch (WebSocketHandshakeException e) { return CompletableFuture.failedFuture(e); + } catch (UncheckedIOException ee) { + return CompletableFuture.failedFuture(ee.getCause()); } }); } @@ -149,7 +153,12 @@ checkAccept(response, h); checkExtensions(response, h); String subprotocol = checkAndReturnSubprotocol(response, h); - RawChannel channel = ((HttpResponseImpl) response).rawChannel(); + RawChannel channel = null; + try { + channel = ((HttpResponseImpl) response).rawChannel(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } return new Result(subprotocol, channel); }
--- a/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Wed May 18 20:40:17 2016 +0300 +++ b/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Wed May 18 12:04:26 2016 -0700 @@ -518,18 +518,22 @@ splitPathList(const char* str, int* pathCount, char*** paths) { int count = 0; char** segments = NULL; + char** new_segments; char* c = (char*) str; while (*c != '\0') { while (*c == ' ') c++; /* skip leading spaces */ if (*c == '\0') { break; } - if (segments == NULL) { - segments = (char**)malloc( sizeof(char**) ); - } else { - segments = (char**)realloc( segments, (count+1)*sizeof(char**) ); + new_segments = (char**)realloc(segments, (count+1)*sizeof(char*)); + if (new_segments == NULL) { + jplis_assert(0); + free(segments); + count = 0; + segments = NULL; + break; } - jplis_assert(segments != (char**)NULL); + segments = new_segments; segments[count++] = c; c = strchr(c, ' '); if (c == NULL) {
--- a/src/java.logging/share/classes/java/util/logging/LogManager.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.logging/share/classes/java/util/logging/LogManager.java Wed May 18 12:04:26 2016 -0700 @@ -2506,15 +2506,12 @@ } } - // Management Support - private static LoggingMXBean loggingMXBean = null; /** * String representation of the * {@link javax.management.ObjectName} for the management interface * for the logging facility. * * @see java.lang.management.PlatformLoggingMXBean - * @see java.util.logging.LoggingMXBean * * @since 1.5 */ @@ -2523,24 +2520,21 @@ /** * Returns {@code LoggingMXBean} for managing loggers. - * An alternative way to manage loggers is through the - * {@link java.lang.management.PlatformLoggingMXBean} interface - * that can be obtained by calling: - * <pre> - * PlatformLoggingMXBean logging = {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) - * ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class); - * </pre> * * @return a {@link LoggingMXBean} object. * + * @deprecated {@code java.util.logging.LoggingMXBean} is deprecated and + * replaced with {@code java.lang.management.PlatformLoggingMXBean}. Use + * {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) + * ManagementFactory.getPlatformMXBean}(PlatformLoggingMXBean.class) + * instead. + * * @see java.lang.management.PlatformLoggingMXBean * @since 1.5 */ + @Deprecated(since="9") public static synchronized LoggingMXBean getLoggingMXBean() { - if (loggingMXBean == null) { - loggingMXBean = new Logging(); - } - return loggingMXBean; + return Logging.getInstance(); } /**
--- a/src/java.logging/share/classes/java/util/logging/Logging.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.logging/share/classes/java/util/logging/Logging.java Wed May 18 12:04:26 2016 -0700 @@ -44,16 +44,18 @@ * @see Logger * @see LogManager */ -class Logging implements LoggingMXBean { +@SuppressWarnings("deprecation") // implements LoggingMXBean +final class Logging implements LoggingMXBean { private static LogManager logManager = LogManager.getLogManager(); /** Constructor of Logging which is the implementation class * of LoggingMXBean. */ - Logging() { + private Logging() { } + @Override public List<String> getLoggerNames() { Enumeration<String> loggers = logManager.getLoggerNames(); ArrayList<String> array = new ArrayList<>(); @@ -65,6 +67,7 @@ } private static String EMPTY_STRING = ""; + @Override public String getLoggerLevel(String loggerName) { Logger l = logManager.getLogger(loggerName); if (l == null) { @@ -79,6 +82,7 @@ } } + @Override public void setLoggerLevel(String loggerName, String levelName) { if (loggerName == null) { throw new NullPointerException("loggerName is null"); @@ -102,6 +106,7 @@ logger.setLevel(level); } + @Override public String getParentLoggerName( String loggerName ) { Logger l = logManager.getLogger( loggerName ); if (l == null) { @@ -116,4 +121,11 @@ return p.getName(); } } + + static Logging getInstance() { + return INSTANCE; + } + + private static final Logging INSTANCE = new Logging(); + }
--- a/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.logging/share/classes/java/util/logging/LoggingMXBean.java Wed May 18 12:04:26 2016 -0700 @@ -27,30 +27,23 @@ /** - * The management interface for the logging facility. It is recommended - * to use the {@link java.lang.management.PlatformLoggingMXBean} management - * interface that implements all attributes defined in this - * {@code LoggingMXBean}. The - * {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) - * ManagementFactory.getPlatformMXBean} method can be used to obtain - * the {@code PlatformLoggingMXBean} object representing the management - * interface for logging. + * The management interface for the logging facility. * - * <p>There is a single global instance of the {@code LoggingMXBean}. - * This instance is an {@link javax.management.MXBean MXBean} that - * can be obtained by calling the {@link LogManager#getLoggingMXBean} - * method or from the - * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer + * {@link java.lang.management.PlatformLoggingMXBean + * java.lang.management.PlatformLoggingMXBean} is the management interface + * for logging facility registered in the {@link + * java.lang.management.ManagementFactory#getPlatformMBeanServer() * platform MBeanServer}. - * <p> - * The {@link javax.management.ObjectName ObjectName} that uniquely identifies - * the management interface for logging within the {@code MBeanServer} is: - * <pre> - * {@link LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging} - * </pre> - * <p> - * The instance registered in the platform {@code MBeanServer} - * is also a {@link java.lang.management.PlatformLoggingMXBean}. + * It is recommended to use the {@code PlatformLoggingMXBean} obtained via + * the {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class) + * ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} method. + * + * @deprecated {@code LoggingMXBean} is no longer a {@link + * java.lang.management.PlatformManagedObject platform MXBean} and is replaced + * with {@link java.lang.management.PlatformLoggingMXBean}. + * It will not register in the platform {@code MBeanServer}. + * Use {@code ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} + * instead. * * @author Ron Mann * @author Mandy Chung @@ -58,6 +51,7 @@ * * @see java.lang.management.PlatformLoggingMXBean */ +@Deprecated(since="9") public interface LoggingMXBean { /**
--- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java Wed May 18 12:04:26 2016 -0700 @@ -598,9 +598,8 @@ try { final ObjectName objName = new ObjectName(mxbeanName); - // skip the isInstanceOf check for LoggingMXBean String intfName = mxbeanInterface.getName(); - if (!connection.isInstanceOf(objName, intfName)) { + if (!isInstanceOf(connection, objName, intfName)) { throw new IllegalArgumentException(mxbeanName + " is not an instance of " + mxbeanInterface); } @@ -616,6 +615,33 @@ } } + // This makes it possible to obtain an instance of LoggingMXBean + // using newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class) + // even though the underlying MXBean no longer implements + // java.util.logging.LoggingMXBean. + // Altough java.util.logging.LoggingMXBean is deprecated, an application + // that uses newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class) will + // continue to work. + // + private static boolean isInstanceOf(MBeanServerConnection connection, + ObjectName objName, String intfName) + throws InstanceNotFoundException, IOException + { + // special case for java.util.logging.LoggingMXBean. + // java.util.logging.LoggingMXBean is deprecated and + // replaced with java.lang.management.PlatformLoggingMXBean, + // so we will consider that any MBean implementing + // java.lang.management.PlatformLoggingMXBean also implements + // java.util.logging.LoggingMXBean. + if ("java.util.logging.LoggingMXBean".equals(intfName)) { + if (connection.isInstanceOf(objName, + PlatformLoggingMXBean.class.getName())) { + return true; + } + } + return connection.isInstanceOf(objName, intfName); + } + /** * Returns the platform MXBean implementing * the given {@code mxbeanInterface} which is specified
--- a/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.management/share/classes/java/lang/management/PlatformLoggingMXBean.java Wed May 18 12:04:26 2016 -0700 @@ -44,10 +44,6 @@ * {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging} * </pre> * - * <p>The instance registered in the platform {@code MBeanServer} with - * this {@code ObjectName} implements all attributes defined by - * {@link java.util.logging.LoggingMXBean}. - * * @since 1.7 */ public interface PlatformLoggingMXBean extends PlatformManagedObject {
--- a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Wed May 18 12:04:26 2016 -0700 @@ -26,6 +26,8 @@ package sun.management; import java.lang.management.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; @@ -43,9 +45,13 @@ import java.util.ArrayList; import java.util.List; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Module; +import java.lang.reflect.UndeclaredThrowableException; import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; /** * ManagementFactoryHelper provides static factory methods to create @@ -66,6 +72,7 @@ return jvm; } + static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; private static ClassLoadingImpl classMBean = null; private static MemoryImpl memoryMBean = null; private static ThreadImpl threadMBean = null; @@ -145,74 +152,138 @@ } public static PlatformLoggingMXBean getPlatformLoggingMXBean() { - if (LoggingMXBeanSupport.isAvailable()) { - return PlatformLoggingImpl.instance; + if (LoggingMXBeanAccess.isAvailable()) { + return PlatformLoggingImpl.MBEAN; } else { return null; } } public static boolean isPlatformLoggingMXBeanAvailable() { - return LoggingMXBeanSupport.isAvailable(); + return LoggingMXBeanAccess.isAvailable(); } - /** - * The logging MXBean object is an instance of - * PlatformLoggingMXBean and java.util.logging.LoggingMXBean - * but it can't directly implement two MXBean interfaces - * as a compliant MXBean implements exactly one MXBean interface, - * or if it implements one interface that is a subinterface of - * all the others; otherwise, it is a non-compliant MXBean - * and MBeanServer will throw NotCompliantMBeanException. - * See the Definition of an MXBean section in javax.management.MXBean spec. - * - * To create a compliant logging MXBean, define a LoggingMXBean interface - * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean - */ - public interface LoggingMXBean - extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean { - } - - // This is a trick: if java.util.logging is not present then - // attempting to access something that implements - // java.util.logging.LoggingMXBean will trigger a CNFE. - // So we cannot directly call any static method or access any static field - // on PlatformLoggingImpl, as we would risk raising a CNFE. - // Instead we use this intermediate LoggingMXBeanSupport class to determine + // The LoggingMXBeanAccess class uses reflection to determine // whether java.util.logging is present, and load the actual LoggingMXBean // implementation. // - static final class LoggingMXBeanSupport { - final static Object loggingImpl = - AccessController.doPrivileged(new PrivilegedAction<Object>() { - @Override - public Object run() { - try { - // create a LoggingProxyImpl instance when - // java.util.logging classes exist - Class<?> c = Class.forName("java.util.logging.Logging", true, null); - Constructor<?> cons = c.getDeclaredConstructor(); - cons.setAccessible(true); - return cons.newInstance(); - } catch (ClassNotFoundException cnf) { - return null; - } catch (NoSuchMethodException | InstantiationException - | IllegalAccessException | InvocationTargetException e) { - throw new AssertionError(e); - } - }}); + static final class LoggingMXBeanAccess { + + final static String LOG_MANAGER_CLASS_NAME = "java.util.logging.LogManager"; + final static String LOGGING_MXBEAN_CLASS_NAME = "java.util.logging.LoggingMXBean"; + final static Class<?> LOG_MANAGER_CLASS = loadLoggingClass(LOG_MANAGER_CLASS_NAME); static boolean isAvailable() { - return loggingImpl != null; + return LOG_MANAGER_CLASS != null; } + + private static Class<?> loadLoggingClass(String className) { + return AccessController.doPrivileged(new PrivilegedAction<>() { + @Override + public Class<?> run() { + Optional<Module> logging = java.lang.reflect.Layer.boot() + .findModule("java.logging"); + if (logging.isPresent()) { + return Class.forName(logging.get(), className); + } + return null; + } + }); + } + + private Map<String, Method> initMethodMap(Object impl) { + if (impl == null) { + return Collections.emptyMap(); + } + Class<?> intfClass = loadLoggingClass(LOGGING_MXBEAN_CLASS_NAME); + final Map<String, Method> methodsMap = new HashMap<>(); + for (Method m : intfClass.getMethods()) { + try { + // Sanity checking: all public methods present in + // java.util.logging.LoggingMXBean should + // also be in PlatformLoggingMXBean + Method specMethod = PlatformLoggingMXBean.class + .getMethod(m.getName(), m.getParameterTypes()); + if (specMethod.getReturnType().isAssignableFrom(m.getReturnType())) { + if (methodsMap.putIfAbsent(m.getName(), m) != null) { + throw new RuntimeException("unexpected polymorphic method: " + + m.getName()); + } + } + } catch (NoSuchMethodException x) { + // All methods in java.util.logging.LoggingMXBean should + // also be in PlatformLoggingMXBean + throw new InternalError(x); + } + } + return Collections.unmodifiableMap(methodsMap); + } + + private static Object getMXBeanImplementation() { + if (!isAvailable()) { + // should not happen + throw new NoClassDefFoundError(LOG_MANAGER_CLASS_NAME); + } + try { + final Method m = LOG_MANAGER_CLASS.getMethod("getLoggingMXBean"); + return m.invoke(null); + } catch (NoSuchMethodException + | IllegalAccessException + | InvocationTargetException x) { + throw new ExceptionInInitializerError(x); + } + } + + // The implementation object, which will be invoked through + // reflection. The implementation does not need to implement + // PlatformLoggingMXBean, but must declare the same methods + // with same signatures, and they must be public, with one + // exception: + // getObjectName will not be called on the implementation object, + // so the implementation object does not need to declare such + // a method. + final Object impl = getMXBeanImplementation(); + final Map<String, Method> methods = initMethodMap(impl); + + LoggingMXBeanAccess() { + } + + <T> T invoke(String methodName, Object... args) { + Method m = methods.get(methodName); + if (m == null) { + throw new UnsupportedOperationException(methodName); + } + try { + @SuppressWarnings("unchecked") + T result = (T) m.invoke(impl, args); + return result; + } catch (IllegalAccessException ex) { + throw new UnsupportedOperationException(ex); + } catch (InvocationTargetException ex) { + throw unwrap(ex); + } + } + + private static RuntimeException unwrap(InvocationTargetException x) { + Throwable t = x.getCause(); + if (t instanceof RuntimeException) { + return (RuntimeException)t; + } + if (t instanceof Error) { + throw (Error)t; + } + return new UndeclaredThrowableException(t == null ? x : t); + } + + } - static class PlatformLoggingImpl implements LoggingMXBean - { - final static java.util.logging.LoggingMXBean impl = - (java.util.logging.LoggingMXBean) LoggingMXBeanSupport.loggingImpl; - final static PlatformLoggingMXBean instance = new PlatformLoggingImpl(); - final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; + static final class PlatformLoggingImpl implements PlatformLoggingMXBean { + + private final LoggingMXBeanAccess loggingAccess; + private PlatformLoggingImpl(LoggingMXBeanAccess loggingAccess) { + this.loggingAccess = loggingAccess; + } private volatile ObjectName objname; // created lazily @Override @@ -232,23 +303,29 @@ @Override public java.util.List<String> getLoggerNames() { - return impl.getLoggerNames(); + return loggingAccess.invoke("getLoggerNames"); } @Override public String getLoggerLevel(String loggerName) { - return impl.getLoggerLevel(loggerName); + return loggingAccess.invoke("getLoggerLevel", loggerName); } @Override public void setLoggerLevel(String loggerName, String levelName) { - impl.setLoggerLevel(loggerName, levelName); + loggingAccess.invoke("setLoggerLevel", loggerName, levelName); } @Override public String getParentLoggerName(String loggerName) { - return impl.getParentLoggerName(loggerName); + return loggingAccess.invoke("getParentLoggerName", loggerName); } + + private static PlatformLoggingImpl getInstance() { + return new PlatformLoggingImpl(new LoggingMXBeanAccess()); + } + + static final PlatformLoggingMXBean MBEAN = getInstance(); } private static List<BufferPoolMXBean> bufferPools = null;
--- a/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java Wed May 18 20:40:17 2016 +0300 +++ b/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java Wed May 18 12:04:26 2016 -0700 @@ -194,7 +194,7 @@ /* * Unless we were told to skip this consideration, choose the * "default loader" to simulate the default ObjectInputStream - * resolveClass mechanism (that is, choose the first non-null + * resolveClass mechanism (that is, choose the first non-platform * loader on the execution stack) to maximize the likelihood of * type compatibility with calling code. (This consideration * is skipped during server parameter unmarshalling using the 1.2 @@ -268,8 +268,9 @@ } /* - * Returns the first non-null class loader up the execution stack, or null - * if only code from the null class loader is on the stack. + * Returns the first non-platform class loader up the execution stack, + * or platform class loader if only code from the platform class loader or null + * is on the stack. */ private static ClassLoader latestUserDefinedLoader() { return jdk.internal.misc.VM.latestUserDefinedLoader();
--- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Wed May 18 12:04:26 2016 -0700 @@ -258,7 +258,7 @@ /* * Convenience method for simple commands */ - private InputStream executeCommand(String cmd, Object ... args) throws IOException { + public InputStream executeCommand(String cmd, Object ... args) throws IOException { try { return execute(cmd, args); } catch (AgentLoadException x) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.oracle.security.ucrypto; + +/** + * Enum for representing the ucrypto mechanisms. + * + * @since 9 + */ +public enum LibMDMech { + + MD5(new ServiceDesc[] + { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5") + }), + SHA_1(new ServiceDesc[] + { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1", + "SHA-1", "SHA1") + }), + SHA_256(new ServiceDesc[] + { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256", + "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1") + }), + SHA_384(new ServiceDesc[] + { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384", + "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2") + }), + SHA_512(new ServiceDesc[] + { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512", + "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3") + }); + + ServiceDesc[] serviceDescs; + + private static ServiceDesc sd(String type, String algo, String cn, String... aliases) { + return new ServiceDesc(type, algo, cn, aliases); + } + + LibMDMech(ServiceDesc[] serviceDescs) { + this.serviceDescs = serviceDescs; + } + + public ServiceDesc[] getServiceDescriptions() { return serviceDescs; } +}
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,23 +33,67 @@ import java.security.*; /** - * MessageDigest implementation class. This class currently supports - * MD5, SHA1, SHA256, SHA384, and SHA512 + * MessageDigest implementation class using native Ucrypto API. + * This class currently supports: MD5, SHA-2 (224, 256, 384, 512) + * and SHA-3 (224, 256, 384, 512) digests * * @since 9 */ -public abstract class NativeDigest extends MessageDigestSpi - implements Cloneable { +abstract class NativeDigest extends MessageDigestSpi { - private static final int MECH_MD5 = 1; - private static final int MECH_SHA1 = 2; - private static final int MECH_SHA256 = 3; - private static final int MECH_SHA224 = 4; - private static final int MECH_SHA384 = 5; - private static final int MECH_SHA512 = 6; + public static final class MD5 extends NativeDigest { + public MD5() { + super(UcryptoMech.CRYPTO_MD5, 16); + } + } + public static final class SHA1 extends NativeDigest { + public SHA1() { + super(UcryptoMech.CRYPTO_SHA1, 20); + } + } + public static final class SHA224 extends NativeDigest { + public SHA224() { + super(UcryptoMech.CRYPTO_SHA224, 28); + } + } + public static final class SHA256 extends NativeDigest { + public SHA256() { + super(UcryptoMech.CRYPTO_SHA256, 32); + } + } + public static final class SHA384 extends NativeDigest { + public SHA384() { + super(UcryptoMech.CRYPTO_SHA384, 48); + } + } + public static final class SHA512 extends NativeDigest { + public SHA512() { + super(UcryptoMech.CRYPTO_SHA512, 64); + } + } + public static final class SHA3_224 extends NativeDigest { + public SHA3_224() { + super(UcryptoMech.CRYPTO_SHA3_224, 28); + } + } + public static final class SHA3_256 extends NativeDigest { + public SHA3_256() { + super(UcryptoMech.CRYPTO_SHA3_256, 32); + } + } + public static final class SHA3_384 extends NativeDigest { + public SHA3_384() { + super(UcryptoMech.CRYPTO_SHA3_384, 48); + } + } + public static final class SHA3_512 extends NativeDigest { + public SHA3_512() { + super(UcryptoMech.CRYPTO_SHA3_512, 64); + } + } private final int digestLen; - private final int mech; + private final UcryptoMech mech; // field for ensuring native memory is freed private DigestContextRef pCtxt = null; @@ -64,10 +108,9 @@ // referents are GC'ed so we can do post-mortem processing private static Set<DigestContextRef> refList = new ConcurrentSkipListSet<DigestContextRef>(); - // Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>()); private final long id; - private final int mech; + private final UcryptoMech mech; private static void drainRefQueueBounded() { while (true) { @@ -77,7 +120,7 @@ } } - DigestContextRef(NativeDigest nc, long id, int mech) { + DigestContextRef(NativeDigest nc, long id, UcryptoMech mech) { super(nc, refQueue); this.id = id; this.mech = mech; @@ -98,18 +141,22 @@ refList.remove(this); try { if (needFree) { - UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id); - NativeDigest.nativeFree(mech, id); - } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id); + UcryptoProvider.debug("Resource: free Digest Ctxt " + + this.id); + NativeDigest.nativeFree(mech.value(), id); + } else { + UcryptoProvider.debug("Resource: discard Digest Ctxt " + + this.id); + } } finally { this.clear(); } } } - NativeDigest(int mech, int digestLen) { + NativeDigest(UcryptoMech mech, int digestLen) { + this.mech = mech; this.digestLen = digestLen; - this.mech = mech; } // see JCA spec @@ -153,10 +200,10 @@ } if (pCtxt == null) { - pCtxt = new DigestContextRef(this, nativeInit(mech), mech); + pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech); } try { - int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen); + int status = nativeDigest(mech.value(), pCtxt.id, out, ofs, digestLen); if (status != 0) { throw new DigestException("Internal error: " + status); } @@ -183,64 +230,24 @@ + len + ". in.length: " + in.length); } if (pCtxt == null) { - pCtxt = new DigestContextRef(this, nativeInit(mech), mech); + pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech); } - nativeUpdate(mech, pCtxt.id, in, ofs, len); + nativeUpdate(mech.value(), pCtxt.id, in, ofs, len); } /** * Clone this digest. */ public synchronized Object clone() throws CloneNotSupportedException { - NativeDigest copy = (NativeDigest) super.clone(); - // re-work the fields that cannot be copied over - if (pCtxt != null) { - copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech); - } - return copy; + throw new CloneNotSupportedException("Clone is not supported"); } // return pointer to the context - protected static native long nativeInit(int mech); + protected static final native long nativeInit(int mech); // return status code; always 0 - protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen); + protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen); // return status code; always 0 - protected static native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen); - // return pointer to the duplicated context - protected static native long nativeClone(int mech, long pCtxt); + protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen); // free the specified context - private native static void nativeFree(int mech, long id); - - - public static final class MD5 extends NativeDigest { - public MD5() { - super(MECH_MD5, 16); - } - } - - public static final class SHA1 extends NativeDigest { - public SHA1() { - super(MECH_SHA1, 20); - } - } - - public static final class SHA256 extends NativeDigest { - public SHA256() { - super(MECH_SHA256, 32); - } - } - - - public static final class SHA384 extends NativeDigest { - public SHA384() { - super(MECH_SHA384, 48); - } - } - - - public static final class SHA512 extends NativeDigest { - public SHA512() { - super(MECH_SHA512, 64); - } - } + private static final native void nativeFree(int mech, long id); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigestMD.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.oracle.security.ucrypto; + +import java.lang.ref.*; + +import java.io.ByteArrayOutputStream; +import java.util.*; +import java.util.concurrent.ConcurrentSkipListSet; +import java.security.*; + +/** + * MessageDigest implementation class for libMD API. This class currently supports + * MD5, SHA1, SHA256, SHA384, and SHA512 + * + * @since 9 + */ +public abstract class NativeDigestMD extends MessageDigestSpi + implements Cloneable { + + private static final int MECH_MD5 = 1; + private static final int MECH_SHA1 = 2; + private static final int MECH_SHA256 = 3; + private static final int MECH_SHA224 = 4; + private static final int MECH_SHA384 = 5; + private static final int MECH_SHA512 = 6; + + private final int digestLen; + private final int mech; + + // field for ensuring native memory is freed + private DigestContextRef pCtxt = null; + + private static class DigestContextRef extends PhantomReference<NativeDigestMD> + implements Comparable<DigestContextRef> { + + private static ReferenceQueue<NativeDigestMD> refQueue = + new ReferenceQueue<NativeDigestMD>(); + + // Needed to keep these references from being GC'ed until when their + // referents are GC'ed so we can do post-mortem processing + private static Set<DigestContextRef> refList = + new ConcurrentSkipListSet<DigestContextRef>(); + // Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>()); + + private final long id; + private final int mech; + + private static void drainRefQueueBounded() { + while (true) { + DigestContextRef next = (DigestContextRef) refQueue.poll(); + if (next == null) break; + next.dispose(true); + } + } + + DigestContextRef(NativeDigestMD nc, long id, int mech) { + super(nc, refQueue); + this.id = id; + this.mech = mech; + refList.add(this); + UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id); + drainRefQueueBounded(); + } + + public int compareTo(DigestContextRef other) { + if (this.id == other.id) { + return 0; + } else { + return (this.id < other.id) ? -1 : 1; + } + } + + void dispose(boolean needFree) { + refList.remove(this); + try { + if (needFree) { + UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id); + NativeDigestMD.nativeFree(mech, id); + } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id); + } finally { + this.clear(); + } + } + } + + NativeDigestMD(int mech, int digestLen) { + this.digestLen = digestLen; + this.mech = mech; + } + + // see JCA spec + protected int engineGetDigestLength() { + return digestLen; + } + + // see JCA spec + protected synchronized void engineReset() { + if (pCtxt != null) { + pCtxt.dispose(true); + pCtxt = null; + } + } + + // see JCA spec + protected synchronized byte[] engineDigest() { + byte[] digest = new byte[digestLen]; + try { + int len = engineDigest(digest, 0, digestLen); + if (len != digestLen) { + throw new UcryptoException("Digest length mismatch." + + " Len: " + len + ". digestLen: " + digestLen); + } + return digest; + } catch (DigestException de) { + throw new UcryptoException("Internal error", de); + } + } + + // see JCA spec + protected synchronized int engineDigest(byte[] out, int ofs, int len) + throws DigestException { + if (len < digestLen) { + throw new DigestException("Output buffer must be at least " + + digestLen + " bytes long. Got: " + len); + } + if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) { + throw new DigestException("Buffer too short to store digest. " + + "ofs: " + ofs + ". len: " + len + ". out.length: " + out.length); + } + + if (pCtxt == null) { + pCtxt = new DigestContextRef(this, nativeInit(mech), mech); + } + try { + int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen); + if (status != 0) { + throw new DigestException("Internal error: " + status); + } + } finally { + pCtxt.dispose(false); + pCtxt = null; + } + return digestLen; + } + + // see JCA spec + protected synchronized void engineUpdate(byte in) { + byte[] temp = { in }; + engineUpdate(temp, 0, 1); + } + + // see JCA spec + protected synchronized void engineUpdate(byte[] in, int ofs, int len) { + if (len == 0) { + return; + } + if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) { + throw new ArrayIndexOutOfBoundsException("ofs: " + ofs + ". len: " + + len + ". in.length: " + in.length); + } + if (pCtxt == null) { + pCtxt = new DigestContextRef(this, nativeInit(mech), mech); + } + nativeUpdate(mech, pCtxt.id, in, ofs, len); + } + + /** + * Clone this digest. + */ + public synchronized Object clone() throws CloneNotSupportedException { + NativeDigestMD copy = (NativeDigestMD) super.clone(); + // re-work the fields that cannot be copied over + if (pCtxt != null) { + copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech); + } + return copy; + } + + // return pointer to the context + protected static final native long nativeInit(int mech); + // return status code; always 0 + protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen); + // return status code; always 0 + protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen); + // return pointer to the duplicated context + protected static final native long nativeClone(int mech, long pCtxt); + // free the specified context + private static final native void nativeFree(int mech, long id); + + + public static final class MD5 extends NativeDigestMD { + public MD5() { + super(MECH_MD5, 16); + } + } + + public static final class SHA1 extends NativeDigestMD { + public SHA1() { + super(MECH_SHA1, 20); + } + } + + public static final class SHA256 extends NativeDigestMD { + public SHA256() { + super(MECH_SHA256, 32); + } + } + + + public static final class SHA384 extends NativeDigestMD { + public SHA384() { + super(MECH_SHA384, 48); + } + } + + + public static final class SHA512 extends NativeDigestMD { + public SHA512() { + super(MECH_SHA512, 64); + } + } +}
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package com.oracle.security.ucrypto; -import java.util.HashMap; - /** * Enum for representing the ucrypto mechanisms. * @@ -35,78 +33,126 @@ // Check /usr/include/libsoftcrypto.h for updates public enum UcryptoMech { - CRYPTO_AES_ECB(1, new ServiceDesc[] + CRYPTO_AES_ECB(new ServiceDesc[] { sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"), sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5", "AES"), - sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding", + sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", "2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"), - sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding", + sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", "2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"), - sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding", + sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", "2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41") }), - CRYPTO_AES_CBC(2, new ServiceDesc[] + CRYPTO_AES_CBC(new ServiceDesc[] { sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"), sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"), - sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding", + sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", "2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"), - sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding", + sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", "2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"), - sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding", + sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", "2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42") }), - CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet - CRYPTO_AES_CTR(4, new ServiceDesc[] +// CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug + CRYPTO_AES_CTR(new ServiceDesc[] { sd("Cipher", "AES/CTR/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding") }), - CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS - CRYPTO_AES_GCM(6, new ServiceDesc[] +// CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS + CRYPTO_AES_GCM(new ServiceDesc[] { sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"), - sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding", + sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", "2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"), - sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding", + sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", "2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"), - sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding", + sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", "2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46") }), - CRYPTO_AES_GMAC(7, null), // No support from Solaris yet - CRYPTO_AES_CFB128(8, new ServiceDesc[] +// CRYPTO_AES_GMAC(null), // No support from Solaris + CRYPTO_AES_CFB128(new ServiceDesc[] { sd("Cipher", "AES/CFB128/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding"), - sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") }), - CRYPTO_RSA_PKCS(31, new ServiceDesc[] + sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") + }), + + CRYPTO_RSA_PKCS(new ServiceDesc[] { sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding", - "RSA") }), - CRYPTO_RSA_X_509(32, new ServiceDesc[] + "RSA") + }), + CRYPTO_RSA_X_509(new ServiceDesc[] { sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }), - CRYPTO_MD5_RSA_PKCS(33, new ServiceDesc[] + CRYPTO_MD5_RSA_PKCS(new ServiceDesc[] { sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5", - "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") }), - CRYPTO_SHA1_RSA_PKCS(34, new ServiceDesc[] + "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") + }), + CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[] { sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1", "1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5", - "1.3.14.3.2.29") }), - CRYPTO_SHA256_RSA_PKCS(35, new ServiceDesc[] + "1.3.14.3.2.29") + }), + CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[] { sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256", - "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") }), - CRYPTO_SHA384_RSA_PKCS(36, new ServiceDesc[] + "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") + }), + CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[] { sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384", - "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") }), - CRYPTO_SHA512_RSA_PKCS(37, new ServiceDesc[] + "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") + }), + CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[] { sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512", - "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") }); + "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") + }), - private final int mech; + CRYPTO_MD5(new ServiceDesc[] + { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }), + CRYPTO_SHA1(new ServiceDesc[] + { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }), + CRYPTO_SHA224(new ServiceDesc[] + { sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224", + "2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4") + }), + CRYPTO_SHA256(new ServiceDesc[] + { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256", + "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1") + }), + CRYPTO_SHA384(new ServiceDesc[] + { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384", + "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2") + }), + CRYPTO_SHA512(new ServiceDesc[] + { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512", + "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3") + }), + CRYPTO_SHA3_224(new ServiceDesc[] + { sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224", + "2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7") + }), + CRYPTO_SHA3_256(new ServiceDesc[] + { sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256", + "2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8") + }), + CRYPTO_SHA3_384(new ServiceDesc[] + { sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384", + "2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9") + }), + CRYPTO_SHA3_512(new ServiceDesc[] + { sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512", + "2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10") + }); + + private int mech = 0; private final ServiceDesc[] serviceDescs; private static ServiceDesc sd(String type, String algo, String cn, String... aliases) { return new ServiceDesc(type, algo, cn, aliases); } - UcryptoMech(int mech, ServiceDesc[] serviceDescs) { - this.mech = mech; + UcryptoMech(ServiceDesc[] serviceDescs) { this.serviceDescs = serviceDescs; } + public void setValue(int nativeMechValue) { + this.mech = nativeMechValue; + } + public int value() { return mech; } public ServiceDesc[] getServiceDescriptions() { return serviceDescs; } }
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.File; +import java.lang.reflect.Constructor; import java.util.*; import java.security.*; @@ -74,48 +75,52 @@ if (provProp != null) { boolean[] result = loadLibraries(); if (result.length == 2) { - if (result[0]) { // successfully loaded libmd - provProp.put("MessageDigest.MD5", - sd("MessageDigest", "MD5", - "com.oracle.security.ucrypto.NativeDigest$MD5")); - provProp.put("MessageDigest.SHA", - sd("MessageDigest", "SHA", - "com.oracle.security.ucrypto.NativeDigest$SHA1", - "SHA-1", "SHA1")); - provProp.put("MessageDigest.SHA-256", - sd("MessageDigest", "SHA-256", - "com.oracle.security.ucrypto.NativeDigest$SHA256", - "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")); - - provProp.put("MessageDigest.SHA-384", - sd("MessageDigest", "SHA-384", - "com.oracle.security.ucrypto.NativeDigest$SHA384", - "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")); - - provProp.put("MessageDigest.SHA-512", - sd("MessageDigest", "SHA-512", - "com.oracle.security.ucrypto.NativeDigest$SHA512", - "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")); - }; - if (result[1]) { // successfully loaded libsoftcrypto + // true when libsoftcrypto or libucrypto(S12) has been successfully loaded + if (result[1]) { String supportedMechs = getMechList(); debug("Prov: supported mechs = " + supportedMechs); - for (UcryptoMech m : UcryptoMech.values()) { - if (supportedMechs.indexOf(m.name() + ",") != -1) { + StringTokenizer st = new StringTokenizer(supportedMechs, ":,;"); + // format: numOfSupportedMechs:[mechName,mechValue;]+ + // skip the first one which is numberOfSupportedMechs + st.nextToken(); + while (st.hasMoreTokens()) { + String mechName = st.nextToken(); + int nativeMechVal = Integer.parseInt(st.nextToken()); + try { + UcryptoMech m = Enum.valueOf(UcryptoMech.class, mechName); + m.setValue(nativeMechVal); ServiceDesc[] services = m.getServiceDescriptions(); - // skip unsupported UcryptoMech - if (services == null || services.length == 0) continue; + // defined in UcryptoMech as unsupported + if (services == null || services.length == 0) { + debug("Skip Unsupported Algorithm: " + mechName); + continue; + } for (int p = 0; p < services.length; p++) { ServiceDesc entry = services[p]; provProp.put(entry.getType() + "." + entry.getAlgorithm(), entry); } + } catch (IllegalArgumentException iae) { + // not defined in UcryptoMech + debug("Skip Unrecognized Algorithm: " + mechName); } } // NOTE: GCM support is only available since jdk 7 provProp.put("AlgorithmParameters.GCM", - sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters")); + sd("AlgorithmParameters", "GCM", + "com.oracle.security.ucrypto.GCMParameters")); } + // true when libmd is needed and has been successfully loaded + if (result[0]) { + for (LibMDMech m : LibMDMech.values()) { + ServiceDesc[] services = m.getServiceDescriptions(); + for (ServiceDesc entry : services) { + String sKey = entry.getType() + "." + entry.getAlgorithm(); + // only register if none has been registered + provProp.putIfAbsent(sKey, entry); + } + } + }; } else { debug("Prov: unexpected ucrypto library loading error, got " + result.length); } @@ -138,6 +143,7 @@ sd.getAliases(), null); } + @SuppressWarnings("deprecation") @Override public Object newInstance(Object ctrParamObj) throws NoSuchAlgorithmException { @@ -152,53 +158,19 @@ int keySize = -1; if (algo.charAt(3) == '_') { keySize = Integer.parseInt(algo.substring(4, 7))/8; - algo = algo.substring(0, 3) + algo.substring(7); } - if (algo.equals("AES/ECB/NoPadding")) { - return new NativeCipher.AesEcbNoPadding(keySize); - } else if (algo.equals("AES/ECB/PKCS5Padding")) { - return new NativeCipherWithJavaPadding.AesEcbPKCS5(); - } else if (algo.equals("AES/CBC/NoPadding")) { - return new NativeCipher.AesCbcNoPadding(keySize); - } else if (algo.equals("AES/CBC/PKCS5Padding")) { - return new NativeCipherWithJavaPadding.AesCbcPKCS5(); - } else if (algo.equals("AES/CTR/NoPadding")) { - return new NativeCipher.AesCtrNoPadding(); - } else if (algo.equals("AES/GCM/NoPadding")) { - return new NativeGCMCipher.AesGcmNoPadding(keySize); - } else if (algo.equals("AES/CFB128/NoPadding")) { - return new NativeCipher.AesCfb128NoPadding(); - } else if (algo.equals("AES/CFB128/PKCS5Padding")) { - return new NativeCipherWithJavaPadding.AesCfb128PKCS5(); - } else if (algo.equals("RSA/ECB/NoPadding")) { - return new NativeRSACipher.NoPadding(); - } else if (algo.equals("RSA/ECB/PKCS1Padding")) { - return new NativeRSACipher.PKCS1Padding(); + String implClass = getClassName(); + Class<?> clz = Class.forName(implClass); + if (keySize != -1) { + Constructor<?> ctr = clz.getConstructor(int.class); + return ctr.newInstance(keySize); + } else { + return clz.newInstance(); } - } else if (type.equals("Signature")) { - if (algo.equals("SHA1withRSA")) { - return new NativeRSASignature.SHA1(); - } else if (algo.equals("SHA256withRSA")) { - return new NativeRSASignature.SHA256(); - } else if (algo.equals("SHA384withRSA")) { - return new NativeRSASignature.SHA384(); - } else if (algo.equals("SHA512withRSA")) { - return new NativeRSASignature.SHA512(); - } else if (algo.equals("MD5withRSA")) { - return new NativeRSASignature.MD5(); - } - } else if (type.equals("MessageDigest")) { - if (algo.equals("SHA")) { - return new NativeDigest.SHA1(); - } else if (algo.equals("SHA-256")) { - return new NativeDigest.SHA256(); - } else if (algo.equals("SHA-384")) { - return new NativeDigest.SHA384(); - } else if (algo.equals("SHA-512")) { - return new NativeDigest.SHA512(); - } else if (algo.equals("MD5")) { - return new NativeDigest.MD5(); - } + } else if (type.equals("Signature") || type.equals("MessageDigest")) { + String implClass = getClassName(); + Class<?> clz = Class.forName(implClass); + return clz.newInstance(); } else if (type.equals("AlgorithmParameters")) { if (algo.equals("GCM")) { return new GCMParameters();
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/libsoftcrypto.h Wed May 18 20:40:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* - * 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. 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. - */ - -#ifndef _LIBSOFTCRYPTO_H -#define _LIBSOFTCRYPTO_H - -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <strings.h> - -typedef enum ucrypto_mech { - CRYPTO_AES_ECB = 1, - CRYPTO_AES_CBC, - CRYPTO_AES_CBC_PAD, - CRYPTO_AES_CTR, - CRYPTO_AES_CCM, - CRYPTO_AES_GCM, - CRYPTO_AES_GMAC, - CRYPTO_AES_CFB128, - CRYPTO_RSA_PKCS = 31, - CRYPTO_RSA_X_509, - CRYPTO_MD5_RSA_PKCS, - CRYPTO_SHA1_RSA_PKCS, - CRYPTO_SHA256_RSA_PKCS, - CRYPTO_SHA384_RSA_PKCS, - CRYPTO_SHA512_RSA_PKCS -} ucrypto_mech_t; - -typedef struct crypto_ctx { - void *cc_provider; - uint_t cc_session; - void *cc_provider_private; /* owned by provider */ - void *cc_framework_private; /* owned by framework */ - uint32_t cc_flags; /* flags */ - void *cc_opstate; /* state */ -} crypto_ctx_t; - -extern int ucrypto_encrypt_init(crypto_ctx_t *context, - ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, - void *iv, size_t iv_len); - -extern int ucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in, - size_t in_len, uchar_t *out, size_t *out_len); - -extern int ucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out, - size_t *out_len); - -/* Encrypt atomic */ -extern int ucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str, - size_t key_len, void *iv, size_t iv_len, uchar_t *in, - size_t in_len, uchar_t *out, size_t *out_len); - -/* Decrypt multi-part */ -extern int ucrypto_decrypt_init(crypto_ctx_t *context, - ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, - void *iv, size_t iv_len); - -extern int ucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in, - size_t in_len, uchar_t *out, size_t *out_len); - -extern int ucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out, - size_t *out_len); - -/* Decrypt atomic */ -extern int ucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str, - size_t key_len, void *iv, size_t iv_len, uchar_t *in, - size_t in_len, uchar_t *out, size_t *out_len); - -/* Sign multi-part */ -extern int ucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type, - uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - -extern int ucrypto_sign_update(crypto_ctx_t *context, - uchar_t *data_str, size_t data_len); - -extern int ucrypto_sign_final(crypto_ctx_t *context, - uchar_t *sig_str, size_t *sig_len); - -/* Sign atomic */ -extern int ucrypto_sign(ucrypto_mech_t mech_type, - uchar_t *key_str, size_t key_len, void *iv, size_t iv_len, - uchar_t *data_str, size_t data_len, uchar_t *sig_str, size_t *sig_len); - -/* Verify multi-part */ -extern int ucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type, - uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - -extern int ucrypto_verify_update(crypto_ctx_t *context, - uchar_t *data_str, size_t data_len); - -extern int ucrypto_verify_final(crypto_ctx_t *context, - uchar_t *sig_str, size_t *sig_len); - -/* Verify atomic */ -extern int ucrypto_verify(ucrypto_mech_t mech_type, - uchar_t *key_str, size_t key_len, void *iv, size_t iv_len, - uchar_t *data_str, size_t data_len, uchar_t *sig, size_t *sig_len); - -extern int ucrypto_get_mechlist(char *str); - -extern const char *ucrypto_id2mech(ucrypto_mech_t mech_type); - -extern ucrypto_mech_t ucrypto_mech2id(const char *str); - -extern int ucrypto_version(); - -typedef struct CK_AES_CTR_PARAMS { - ulong_t ulCounterBits; - uint8_t cb[16]; -} CK_AES_CTR_PARAMS; - -typedef struct CK_AES_GCM_PARAMS { - uchar_t *pIv; - ulong_t ulIvLen; - ulong_t ulIvBits; - uchar_t *pAAD; - ulong_t ulAADLen; - ulong_t ulTagBits; -} CK_AES_GCM_PARAMS; - -typedef struct crypto_object_attribute { - uint64_t oa_type; /* attribute type */ - caddr_t oa_value; /* attribute value */ - ssize_t oa_value_len; /* length of attribute value */ -} crypto_object_attribute_t; - -/* Attribute types to use for passing a RSA public key or a private key. */ -#define SUN_CKA_MODULUS 0x00000120 -#define SUN_CKA_MODULUS_BITS 0x00000121 -#define SUN_CKA_PUBLIC_EXPONENT 0x00000122 -#define SUN_CKA_PRIVATE_EXPONENT 0x00000123 -#define SUN_CKA_PRIME_1 0x00000124 -#define SUN_CKA_PRIME_2 0x00000125 -#define SUN_CKA_EXPONENT_1 0x00000126 -#define SUN_CKA_EXPONENT_2 0x00000127 -#define SUN_CKA_COEFFICIENT 0x00000128 -#define SUN_CKA_PRIME 0x00000130 -#define SUN_CKA_SUBPRIME 0x00000131 -#define SUN_CKA_BASE 0x00000132 - -#define CKK_EC 0x00000003 -#define CKK_GENERIC_SECRET 0x00000010 -#define CKK_RC4 0x00000012 -#define CKK_AES 0x0000001F -#define CKK_DES 0x00000013 -#define CKK_DES2 0x00000014 -#define CKK_DES3 0x00000015 - -#define CKO_PUBLIC_KEY 0x00000002 -#define CKO_PRIVATE_KEY 0x00000003 -#define CKA_CLASS 0x00000000 -#define CKA_VALUE 0x00000011 -#define CKA_KEY_TYPE 0x00000100 -#define CKA_VALUE_LEN 0x00000161 -#define CKA_EC_PARAMS 0x00000180 -#define CKA_EC_POINT 0x00000181 - -#endif /* _LIBSOFTCRYPTO_H */
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,22 @@ /* * Dumps out byte array in hex with and name and length info */ +void printError(char* header, int mech, int rv) { + if (mech != -1) { + printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv); + } else { + printf("%s, rv = 0x%0x\n", header, rv); + } + if (*ftab->ucryptoStrerror != NULL) { + char * reason = (*ftab->ucryptoStrerror)(rv); + printf("\tcause = %s\n", reason); + free(reason); + } +} + +/* + * Dumps out byte array in hex with and name and length info + */ void printBytes(char* header, unsigned char* bytes, int len) { int i; @@ -60,6 +76,16 @@ (*env)->DeleteLocalRef(env, jExClass); } +/* + * De-allocates all memory associated with crypto_ctx_t + */ +void freeContext(crypto_ctx_t *context) { + if (ftab->ucryptoFreeContext != NULL) { + (*ftab->ucryptoFreeContext)(context); + } + free(context); +} + JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_4; } @@ -203,10 +229,10 @@ } if (encrypt) { rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen); - if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv); + if (rv != 0 && DEBUG) printError("ucryptoEncryptInit", mech, rv); } else { rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen); - if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv); + if (rv != 0 && DEBUG) printError("ucryptoDecryptInit", mech, rv); } if (iv != jIv) { @@ -234,15 +260,15 @@ } if (encrypt) { rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength); - if (rv != 0) { - if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv); + if (rv) { + if (DEBUG) printError("ucryptoEncryptUpdate", -1, rv); } else { *outLen = (int)outLength; } } else { rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength); - if (rv != 0) { - if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv); + if (rv) { + if (DEBUG) printError("ucryptoDecryptUpdate", -1, rv); } else { if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength); *outLen = (int)outLength; @@ -263,16 +289,16 @@ if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen); if (encrypt) { rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength); - if (rv != 0) { - if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv); + if (rv) { + if (DEBUG) printError("ucryptoDecryptFinal", -1, rv); } else { if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength); *outLen = (int)outLength; } } else { rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength); - if (rv != 0) { - if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv); + if (rv) { + if (DEBUG) printError("ucryptoDecryptFinal", -1, rv); } else { if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength); *outLen = (int)outLength; @@ -285,102 +311,61 @@ // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION //////////////////////////////////////////////////////// jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) { - void *pContext = NULL; + crypto_ctx_t *context = NULL; + int rv; - switch (mech) { - case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1: - pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX)); - if (pContext != NULL) { - (*ftab->sha1Init)((SHA1_CTX *)pContext); + context = malloc(sizeof(crypto_ctx_t)); + if (context != NULL) { + rv = (*ftab->ucryptoDigestInit)(context, (ucrypto_mech_t) mech, NULL, 0); + if (rv) { + freeContext(context); + if (DEBUG) printError("ucryptoDigestInit", mech, rv); + return 0L; } - break; - case com_oracle_security_ucrypto_NativeDigest_MECH_MD5: - pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX)); - if (pContext != NULL) { - (*ftab->md5Init)((MD5_CTX *)pContext); - } - break; - case com_oracle_security_ucrypto_NativeDigest_MECH_SHA256: - pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX)); - if (pContext != NULL) { - (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext); - } - break; - case com_oracle_security_ucrypto_NativeDigest_MECH_SHA384: - pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX)); - if (pContext != NULL) { - (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext); - } - break; - case com_oracle_security_ucrypto_NativeDigest_MECH_SHA512: - pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX)); - if (pContext != NULL) { - (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext); - } - break; - default: - if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech); } - return (jlong) pContext; + return (jlong) context; } jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) { - if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) { - (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len); - } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) { - (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len); - } else { // SHA-2 family - (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len); + crypto_ctx_t *context; + jint rv = 0; + + context = (crypto_ctx_t *) pContext; + rv = (*ftab->ucryptoDigestUpdate)(context, (const unsigned char*)(in + ofs), + (size_t) len); + + if (rv) { + freeContext(context); + if (DEBUG) printError("ucryptoDigestUpdate", mech, rv); } - return 0; + + return -rv; // use negative value to indicate error } -// Do digest and free the context immediately jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) { + crypto_ctx_t *context; + jint rv = 0; + size_t digest_len = digestLen; - if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) { - (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext); - free((SHA1_CTX *)pContext); - } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) { - (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext); - free((MD5_CTX *)pContext); - } else { // SHA-2 family - (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext); - free((SHA2_CTX *)pContext); + context = (crypto_ctx_t *) pContext; + rv = (*ftab->ucryptoDigestFinal)(context, (unsigned char*)(out + ofs), + &digest_len); + if (rv) { + freeContext(context); + if (DEBUG) printError("ucryptoDigestFinal", mech, rv); } - return 0; -} -jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone - (jint mech, jlong pContext) { - void *copy = NULL; - size_t len = 0; - - if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) { - len = sizeof(SHA1_CTX); - } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) { - len = sizeof(MD5_CTX); - } else { // SHA-2 family - len = sizeof(SHA2_CTX); - } - copy = (void*) malloc(len); - if (copy != NULL) { - bcopy((void *)pContext, copy, len); - } - return (jlong) copy; + return -rv; // use negative value to indicate error } void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree (jint mech, jlong pContext) { - if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) { - free((SHA1_CTX*) pContext); - } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) { - free((MD5_CTX*) pContext); - } else { // SHA-2 family - free((SHA2_CTX*) pContext); - } + crypto_ctx_t *context; + + context = (crypto_ctx_t *) pContext; + freeContext(context); } // AES @@ -395,7 +380,7 @@ rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen, bufIv, ivLen, tagLen, bufAad, aadLen); if (rv) { - free(context); + freeContext(context); return 0L; } } @@ -417,8 +402,7 @@ context = (crypto_ctx_t *) pContext; rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen); if (rv) { - free(context); - context = 0; + freeContext(context); return -rv; // use negative value to indicate error! } @@ -443,7 +427,7 @@ outLen = 0; } rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen); - free(context); + freeContext(context); if (rv) { return -rv; // use negative value to indicate error! } @@ -451,8 +435,6 @@ return outLen; } - - /* * Class: com_oracle_security_ucrypto_NativeDigest * Method: nativeInit @@ -475,13 +457,15 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) { unsigned char *bufIn; + jint rv = 0; + bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen); if (!(*env)->ExceptionCheck(env)) { - JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen); + rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen); free(bufIn); } - return 0; + return rv; } /* @@ -492,6 +476,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) { unsigned char *bufOut; + jint rv = 0; bufOut = (unsigned char *) malloc(digestLen); if (bufOut == NULL) { @@ -499,21 +484,12 @@ return 0; } - JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen); - - (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut); + rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen); + if (rv == 0) { + (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut); + } free(bufOut); - return 0; -} - -/* - * Class: com_oracle_security_ucrypto_NativeDigest - * Method: nativeClone - * Signature: (IJ)J - */ -JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone - (JNIEnv *env, jclass jcls, jint mech, jlong pContext) { - return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext); + return rv; } /* @@ -582,7 +558,7 @@ cleanup: if ((result == 0L) && (context != NULL)) { - free(context); + freeContext(context); } if (bufKey != NULL) { (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0); @@ -626,7 +602,7 @@ rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen); if (rv) { - free(context); + freeContext(context); free(bufIn); free(bufOut); return -rv; @@ -683,6 +659,7 @@ return rc; } + /* * Class: com_oracle_security_ucrypto_NativeKey * Method: nativeFree @@ -984,9 +961,9 @@ } if (DEBUG) { - printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey); - printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen); - printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen); + printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey); + printBytes("\tmod: ", (unsigned char*) mod, modLen); + printBytes("\tpubExp: ", (unsigned char*) pub, pubLen); } pKey[0].oa_type = SUN_CKA_MODULUS; @@ -1062,7 +1039,7 @@ if (DEBUG) { printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n", context, mech, sign, pKey, keyLength); - printf("SignatureInit, ret => 0x%x\n", rv); + printError("SignatureInit", mech, rv); } return rv; } @@ -1083,7 +1060,7 @@ pKey = (uchar_t *) jKey; rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength); if (rv) { - free(context); + freeContext(context); return 0L; } } @@ -1105,7 +1082,7 @@ pKey = (uchar_t *) jKey; rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength); if (rv) { - free(context); + freeContext(context); throwUCExceptionUsingRV(env, rv); return 0L; } @@ -1125,7 +1102,7 @@ context = (crypto_ctx_t *) pCtxt; if (DEBUG) { - printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n", + printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n", context, sign, jIn, jInOfs, jInLen); } if (sign) { @@ -1133,9 +1110,9 @@ } else { rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen); } - if (DEBUG) printf("Signature update, ret => 0x%x\n", rv); if (rv) { - free(context); + freeContext(context); + if (DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv); return -rv; // use negative value to indicate error! } @@ -1194,9 +1171,9 @@ context = (crypto_ctx_t *) pCtxt; if (DEBUG) { - printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n", + printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n", context, sign, bufSig, sigOfs, jSigLen); - printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen); + printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen); } if (sign) { rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength); @@ -1204,18 +1181,17 @@ rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength); } - if (DEBUG) { - printf("Signature nativeFinal, ret => 0x%x\n", rv); - if (sigLength != jSigLen) { - printf("SIG actual output len=%d\n", sigLength); + freeContext(context); + if (rv) { + if (DEBUG) { + printError("NativeRSASignature.nativeFinal", -1, rv); + if (sigLength != jSigLen) { + printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength); + } + if (sign) { + printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen); + } } - if (sign) { - printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen); - } - } - - free(context); - if (rv) { return -rv; } else return 0; } @@ -1273,10 +1249,10 @@ pKey = (uchar_t *) keyValue; if (DEBUG) { - printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n", + printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n", mech, encrypt, pKey, keyLength); - printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen); - printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen); + printBytes("Before: in = ", (unsigned char*) bufIn, jInLen); + printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen); } if (encrypt) { @@ -1289,11 +1265,11 @@ (uchar_t *)(bufOut + jOutOfs), &outLength); } if (DEBUG) { - printf("Cipher nativeAtomic, ret => 0x%x\n", rv); + printError("NativeRSACipher.nativeAtomic", mech, rv); if (outLength != jOutLen) { - printf("CIP actual output len=%d\n", outLength); + printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength); } - printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength); + printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength); } if (rv) {
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,18 +29,18 @@ extern "C" { #endif -#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5 -#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L -#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 -#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L -#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 -#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L -#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 -#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L -#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 -#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L -#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 -#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 1L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 2L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 3L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 4L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 5L +#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 +#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 6L #define DEBUG 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <jni.h> +#include "jni_util.h" +#include <libsoftcrypto.h> +#include "nativeCrypto.h" +#include "nativeFunc.h" + + +extern void throwOutOfMemoryError(JNIEnv *env, const char *msg); +extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len); + +/////////////////////////////////////////////////////// +// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION +//////////////////////////////////////////////////////// +jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) { + void *pContext = NULL; + + switch (mech) { + case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1: + pContext = malloc(sizeof(SHA1_CTX)); + if (pContext != NULL) { + (*ftab->sha1Init)((SHA1_CTX *)pContext); + } + break; + case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5: + pContext = malloc(sizeof(MD5_CTX)); + if (pContext != NULL) { + (*ftab->md5Init)((MD5_CTX *)pContext); + } + break; + case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256: + pContext = malloc(sizeof(SHA2_CTX)); + if (pContext != NULL) { + (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext); + } + break; + case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384: + pContext = malloc(sizeof(SHA2_CTX)); + if (pContext != NULL) { + (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext); + } + break; + case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512: + pContext = malloc(sizeof(SHA2_CTX)); + if (pContext != NULL) { + (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext); + } + break; + default: + if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech); + } + return (jlong) pContext; +} + +jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate + (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) { + if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) { + (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len); + } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) { + (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len); + } else { // SHA-2 family + (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len); + } + return 0; +} + +// Do digest and free the context immediately +jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest + (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) { + + if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) { + (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext); + free((SHA1_CTX *)pContext); + } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) { + (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext); + free((MD5_CTX *)pContext); + } else { // SHA-2 family + (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext); + free((SHA2_CTX *)pContext); + } + return 0; +} + +jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone + (jint mech, jlong pContext) { + void *copy = NULL; + size_t len = 0; + + if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) { + len = sizeof(SHA1_CTX); + } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) { + len = sizeof(MD5_CTX); + } else { // SHA-2 family + len = sizeof(SHA2_CTX); + } + copy = malloc(len); + if (copy != NULL) { + bcopy((void *)pContext, copy, len); + } + return (jlong) copy; +} + +void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree + (jint mech, jlong pContext) { + if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) { + free((SHA1_CTX*) pContext); + } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) { + free((MD5_CTX*) pContext); + } else { // SHA-2 family + free((SHA2_CTX*) pContext); + } +} + + +/* + * Class: com_oracle_security_ucrypto_NativeDigestMD + * Method: nativeInit + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit + (JNIEnv *env, jclass jcls, jint mech) { + jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech); + if (result == NULL) { + throwOutOfMemoryError(env, NULL); + } + return result; +} + +/* + * Class: com_oracle_security_ucrypto_NativeDigestMD + * Method: nativeUpdate + * Signature: (IJ[BII)I + */ +JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate + (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) { + unsigned char *bufIn; + + bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen); + if (!(*env)->ExceptionCheck(env)) { + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen); + free(bufIn); + } + return 0; +} + +/* + * Class: com_oracle_security_ucrypto_NativeDigestMD + * Method: nativeDigest + * Signature: (IJ[BII)I + */ +JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest + (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) { + unsigned char *bufOut; + + bufOut = (unsigned char *) malloc(digestLen); + if (bufOut == NULL) { + throwOutOfMemoryError(env, NULL); + return 0; + } + + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen); + + (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut); + free(bufOut); + return 0; +} + +/* + * Class: com_oracle_security_ucrypto_NativeDigestMD + * Method: nativeClone + * Signature: (IJ)J + */ +JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone + (JNIEnv *env, jclass jcls, jint mech, jlong pContext) { + return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext); +} + +/* + * Class: com_oracle_security_ucrypto_NativeDigestMD + * Method: nativeFree + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree + (JNIEnv *env, jclass jcls, jint mech, jlong pContext) { + JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext); +} +
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,21 +42,33 @@ static const char SHA2_FINAL[] = "SHA2Final"; static const char UCRYPTO_VERSION[] = "ucrypto_version"; static const char UCRYPTO_GET_MECHLIST[] = "ucrypto_get_mechlist"; + static const char UCRYPTO_ENCRYPT_INIT[] = "ucrypto_encrypt_init"; static const char UCRYPTO_ENCRYPT_UPDATE[] = "ucrypto_encrypt_update"; static const char UCRYPTO_ENCRYPT_FINAL[] = "ucrypto_encrypt_final"; static const char UCRYPTO_ENCRYPT[] = "ucrypto_encrypt"; + static const char UCRYPTO_DECRYPT_INIT[] = "ucrypto_decrypt_init"; static const char UCRYPTO_DECRYPT_UPDATE[] = "ucrypto_decrypt_update"; static const char UCRYPTO_DECRYPT_FINAL[] = "ucrypto_decrypt_final"; static const char UCRYPTO_DECRYPT[] = "ucrypto_decrypt"; + static const char UCRYPTO_SIGN_INIT[] = "ucrypto_sign_init"; static const char UCRYPTO_SIGN_UPDATE[] = "ucrypto_sign_update"; static const char UCRYPTO_SIGN_FINAL[] = "ucrypto_sign_final"; + static const char UCRYPTO_VERIFY_INIT[] = "ucrypto_verify_init"; static const char UCRYPTO_VERIFY_UPDATE[] = "ucrypto_verify_update"; static const char UCRYPTO_VERIFY_FINAL[] = "ucrypto_verify_final"; +static const char UCRYPTO_DIGEST_INIT[] = "ucrypto_digest_init"; +static const char UCRYPTO_DIGEST_UPDATE[] = "ucrypto_digest_update"; +static const char UCRYPTO_DIGEST_FINAL[] = "ucrypto_digest_final"; + +static const char UCRYPTO_FREE_CONTEXT[] = "ucrypto_free_context"; + +static const char UCRYPTO_STRERROR[] = "ucrypto_strerror"; + /** * Initialize native T4 crypto function pointers */ @@ -73,28 +85,6 @@ return NULL; } - lib = dlopen("libmd.so", RTLD_NOW); - if (lib != NULL) { - ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT); - ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE); - ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL); - ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT); - ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE); - ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL); - ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT); - ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE); - ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL); - if (ftab->md5Init != NULL && ftab->md5Update != NULL && - ftab->md5Final != NULL && ftab->sha1Init != NULL && - ftab->sha1Update != NULL && ftab->sha1Final != NULL && - ftab->sha2Init != NULL && ftab->sha2Update != NULL && - ftab->sha2Final != NULL) { - buf[0] = JNI_TRUE; - } else { - dlclose(lib); - } - } - lib = dlopen("libsoftcrypto.so", RTLD_NOW); if (lib != NULL) { // These APIs aren't available for v0 lib on Solaris 10 @@ -102,7 +92,6 @@ dlsym(lib, UCRYPTO_VERSION); ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR) dlsym(lib, UCRYPTO_GET_MECHLIST); - //?? ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR) dlsym(lib, UCRYPTO_SIGN_INIT); ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR) @@ -116,6 +105,21 @@ ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR) dlsym(lib, UCRYPTO_VERIFY_FINAL); + // These APS are added starting S12 + ftab->ucryptoDigestInit = (UCRYPTO_DIGEST_INIT_FN_PTR) + dlsym(lib, UCRYPTO_DIGEST_INIT); + ftab->ucryptoDigestUpdate = (UCRYPTO_DIGEST_UPDATE_FN_PTR) + dlsym(lib, UCRYPTO_DIGEST_UPDATE); + ftab->ucryptoDigestFinal = (UCRYPTO_DIGEST_FINAL_FN_PTR) + dlsym(lib, UCRYPTO_DIGEST_FINAL); + + ftab->ucryptoFreeContext = (UCRYPTO_FREE_CONTEXT_FN_PTR) + dlsym(lib, UCRYPTO_FREE_CONTEXT); + + ftab->ucryptoStrerror = (UCRYPTO_STRERROR_FN_PTR) + dlsym(lib, UCRYPTO_STRERROR); + + // These should be avilable for all libsoftcrypto libs ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR) dlsym(lib, UCRYPTO_ENCRYPT_INIT); @@ -147,6 +151,34 @@ } else { dlclose(lib); } + + // proceed with libmd when libucrypto does not support digest operations + if (ftab->ucryptoDigestInit == NULL || + ftab->ucryptoDigestUpdate == NULL || + ftab->ucryptoDigestFinal == NULL) { + + lib = dlopen("libmd.so", RTLD_NOW); + if (lib != NULL) { + ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT); + ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE); + ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL); + ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT); + ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE); + ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL); + ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT); + ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE); + ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL); + if (ftab->md5Init != NULL && ftab->md5Update != NULL && + ftab->md5Final != NULL && ftab->sha1Init != NULL && + ftab->sha1Update != NULL && ftab->sha1Final != NULL && + ftab->sha2Init != NULL && ftab->sha2Update != NULL && + ftab->sha2Final != NULL) { + buf[0] = JNI_TRUE; + } else { + dlclose(lib); + } + } + } } return buf;
--- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,15 +69,12 @@ (crypto_ctx_t *context, ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR) (crypto_ctx_t *context, uchar_t *in, size_t in_len, uchar_t *out, size_t *out_len); - typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR) (crypto_ctx_t *context, uchar_t *out, size_t *out_len); - typedef int (*UCRYPTO_ENCRYPT_FN_PTR) (ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len, uchar_t *in, @@ -87,15 +84,12 @@ (crypto_ctx_t *context, ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR) (crypto_ctx_t *context, uchar_t *in, size_t in_len, uchar_t *out, size_t *out_len); - typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR) (crypto_ctx_t *context, uchar_t *out, size_t *out_len); - typedef int (*UCRYPTO_DECRYPT_FN_PTR) (ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len, uchar_t *in, @@ -105,10 +99,8 @@ (crypto_ctx_t *context, ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR) (crypto_ctx_t *context, uchar_t *data_str, size_t data_len); - typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR) (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len); @@ -116,13 +108,24 @@ (crypto_ctx_t *context, ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len, void *iv, size_t iv_len); - typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR) (crypto_ctx_t *context, uchar_t *data_str, size_t data_len); - typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR) (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len); +typedef int (*UCRYPTO_DIGEST_INIT_FN_PTR) + (crypto_ctx_t *context, ucrypto_mech_t mech_type, + void *param, size_t param_len); +typedef int (*UCRYPTO_DIGEST_UPDATE_FN_PTR) + (crypto_ctx_t *context, const uchar_t *data, size_t data_len); +typedef int (*UCRYPTO_DIGEST_FINAL_FN_PTR) + (crypto_ctx_t *context, uchar_t *digest, size_t *digest_len); + +typedef void (*UCRYPTO_FREE_CONTEXT_FN_PTR) + (crypto_ctx_t *context); + +typedef char* (*UCRYPTO_STRERROR_FN_PTR)(int rv); + /* dynamically resolved functions from libmd, and libsoftcrypto @@ -153,6 +156,11 @@ UCRYPTO_VERIFY_INIT_FN_PTR ucryptoVerifyInit; UCRYPTO_VERIFY_UPDATE_FN_PTR ucryptoVerifyUpdate; UCRYPTO_VERIFY_FINAL_FN_PTR ucryptoVerifyFinal; + UCRYPTO_DIGEST_INIT_FN_PTR ucryptoDigestInit; + UCRYPTO_DIGEST_UPDATE_FN_PTR ucryptoDigestUpdate; + UCRYPTO_DIGEST_FINAL_FN_PTR ucryptoDigestFinal; + UCRYPTO_FREE_CONTEXT_FN_PTR ucryptoFreeContext; + UCRYPTO_STRERROR_FN_PTR ucryptoStrerror; } T4CRYPTO_FUNCTION_TABLE; typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;
--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java Wed May 18 12:04:26 2016 -0700 @@ -2498,6 +2498,12 @@ //ignore } + if (o instanceof Runnable) { + ((Runnable) o).run(); + sb.setLength(0); + continue; + } + // Search mode. // // Note that we have to do this first, because if there is a command
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 jdk.internal.jline.extra; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.function.Supplier; + +import jdk.internal.jline.console.ConsoleReader; +import jdk.internal.jline.console.KeyMap; +import jdk.internal.jline.console.history.History; +import jdk.internal.jline.console.history.History.Entry; +import jdk.internal.jline.console.history.MemoryHistory; + +/*Public for tests (HistoryTest). + */ +public abstract class EditingHistory implements History { + + private final History fullHistory; + private History currentDelegate; + + protected EditingHistory(ConsoleReader in, Iterable<? extends String> originalHistory) { + this.fullHistory = new MemoryHistory(); + this.currentDelegate = fullHistory; + bind(in, CTRL_UP, + (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::previousSnippet)); + bind(in, CTRL_DOWN, + (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::nextSnippet)); + load(originalHistory); + } + + private void moveHistoryToSnippet(ConsoleReader in, Supplier<Boolean> action) { + if (!action.get()) { + try { + in.beep(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } else { + try { + //could use: + //in.resetPromptLine(in.getPrompt(), in.getHistory().current().toString(), -1); + //but that would mean more re-writing on the screen, (and prints an additional + //empty line), so using setBuffer directly: + Method setBuffer = in.getClass().getDeclaredMethod("setBuffer", String.class); + + setBuffer.setAccessible(true); + setBuffer.invoke(in, in.getHistory().current().toString()); + in.flush(); + } catch (ReflectiveOperationException | IOException ex) { + throw new IllegalStateException(ex); + } + } + } + + private void bind(ConsoleReader in, String shortcut, Object action) { + KeyMap km = in.getKeys(); + for (int i = 0; i < shortcut.length(); i++) { + Object value = km.getBound(Character.toString(shortcut.charAt(i))); + if (value instanceof KeyMap) { + km = (KeyMap) value; + } else { + km.bind(shortcut.substring(i), action); + } + } + } + + private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP + private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN + + @Override + public int size() { + return currentDelegate.size(); + } + + @Override + public boolean isEmpty() { + return currentDelegate.isEmpty(); + } + + @Override + public int index() { + return currentDelegate.index(); + } + + @Override + public void clear() { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + currentDelegate.clear(); + } + + @Override + public CharSequence get(int index) { + return currentDelegate.get(index); + } + + @Override + public void add(CharSequence line) { + NarrowingHistoryLine currentLine = null; + int origIndex = fullHistory.index(); + int fullSize; + try { + fullHistory.moveToEnd(); + fullSize = fullHistory.index(); + if (currentDelegate == fullHistory) { + if (origIndex < fullHistory.index()) { + for (Entry entry : fullHistory) { + if (!(entry.value() instanceof NarrowingHistoryLine)) + continue; + int[] cluster = ((NarrowingHistoryLine) entry.value()).span; + if (cluster[0] == origIndex && cluster[1] > cluster[0]) { + currentDelegate = new MemoryHistory(); + for (int i = cluster[0]; i <= cluster[1]; i++) { + currentDelegate.add(fullHistory.get(i)); + } + } + } + } + } + fullHistory.moveToEnd(); + while (fullHistory.previous()) { + CharSequence c = fullHistory.current(); + if (c instanceof NarrowingHistoryLine) { + currentLine = (NarrowingHistoryLine) c; + break; + } + } + } finally { + fullHistory.moveTo(origIndex); + } + if (currentLine == null || currentLine.span[1] != (-1)) { + line = currentLine = new NarrowingHistoryLine(line, fullSize); + } + StringBuilder complete = new StringBuilder(); + for (int i = currentLine.span[0]; i < fullSize; i++) { + complete.append(fullHistory.get(i)); + } + complete.append(line); + if (isComplete(complete)) { + currentLine.span[1] = fullSize; //TODO: +1? + currentDelegate = fullHistory; + } + fullHistory.add(line); + } + + protected abstract boolean isComplete(CharSequence input); + + @Override + public void set(int index, CharSequence item) { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + currentDelegate.set(index, item); + } + + @Override + public CharSequence remove(int i) { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + return currentDelegate.remove(i); + } + + @Override + public CharSequence removeFirst() { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + return currentDelegate.removeFirst(); + } + + @Override + public CharSequence removeLast() { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + return currentDelegate.removeLast(); + } + + @Override + public void replace(CharSequence item) { + if (currentDelegate != fullHistory) + throw new IllegalStateException("narrowed"); + currentDelegate.replace(item); + } + + @Override + public ListIterator<Entry> entries(int index) { + return currentDelegate.entries(index); + } + + @Override + public ListIterator<Entry> entries() { + return currentDelegate.entries(); + } + + @Override + public Iterator<Entry> iterator() { + return currentDelegate.iterator(); + } + + @Override + public CharSequence current() { + return currentDelegate.current(); + } + + @Override + public boolean previous() { + return currentDelegate.previous(); + } + + @Override + public boolean next() { + return currentDelegate.next(); + } + + @Override + public boolean moveToFirst() { + return currentDelegate.moveToFirst(); + } + + @Override + public boolean moveToLast() { + return currentDelegate.moveToLast(); + } + + @Override + public boolean moveTo(int index) { + return currentDelegate.moveTo(index); + } + + @Override + public void moveToEnd() { + currentDelegate.moveToEnd(); + } + + public boolean previousSnippet() { + for (int i = index() - 1; i >= 0; i--) { + if (get(i) instanceof NarrowingHistoryLine) { + moveTo(i); + return true; + } + } + + return false; + } + + public boolean nextSnippet() { + for (int i = index() + 1; i < size(); i++) { + if (get(i) instanceof NarrowingHistoryLine) { + moveTo(i); + return true; + } + } + + if (index() < size()) { + moveToEnd(); + return true; + } + + return false; + } + + public final void load(Iterable<? extends String> originalHistory) { + NarrowingHistoryLine currentHistoryLine = null; + boolean start = true; + int currentLine = 0; + for (String historyItem : originalHistory) { + StringBuilder line = new StringBuilder(historyItem); + int trailingBackSlashes = countTrailintBackslashes(line); + boolean continuation = trailingBackSlashes % 2 != 0; + line.delete(line.length() - trailingBackSlashes / 2 - (continuation ? 1 : 0), line.length()); + if (start) { + class PersistentNarrowingHistoryLine extends NarrowingHistoryLine implements PersistentEntryMarker { + public PersistentNarrowingHistoryLine(CharSequence delegate, int start) { + super(delegate, start); + } + } + fullHistory.add(currentHistoryLine = new PersistentNarrowingHistoryLine(line, currentLine)); + } else { + class PersistentLine implements CharSequence, PersistentEntryMarker { + private final CharSequence delegate; + public PersistentLine(CharSequence delegate) { + this.delegate = delegate; + } + @Override public int length() { + return delegate.length(); + } + @Override public char charAt(int index) { + return delegate.charAt(index); + } + @Override public CharSequence subSequence(int start, int end) { + return delegate.subSequence(start, end); + } + @Override public String toString() { + return delegate.toString(); + } + } + fullHistory.add(new PersistentLine(line)); + } + start = !continuation; + currentHistoryLine.span[1] = currentLine; + currentLine++; + } + } + + public Collection<? extends String> save() { + Collection<String> result = new ArrayList<>(); + Iterator<Entry> entries = fullHistory.iterator(); + + if (entries.hasNext()) { + Entry entry = entries.next(); + while (entry != null) { + StringBuilder historyLine = new StringBuilder(entry.value()); + int trailingBackSlashes = countTrailintBackslashes(historyLine); + for (int i = 0; i < trailingBackSlashes; i++) { + historyLine.append("\\"); + } + entry = entries.hasNext() ? entries.next() : null; + if (entry != null && !(entry.value() instanceof NarrowingHistoryLine)) { + historyLine.append("\\"); + } + result.add(historyLine.toString()); + } + } + + return result; + } + + private int countTrailintBackslashes(CharSequence text) { + int count = 0; + + for (int i = text.length() - 1; i >= 0; i--) { + if (text.charAt(i) == '\\') { + count++; + } else { + break; + } + } + + return count; + } + + public List<String> currentSessionEntries() { + List<String> result = new ArrayList<>(); + + for (Entry e : fullHistory) { + if (!(e.value() instanceof PersistentEntryMarker)) { + result.add(e.value().toString()); + } + } + + return result; + } + + public void fullHistoryReplace(String source) { + fullHistory.replace(source); + } + + private class NarrowingHistoryLine implements CharSequence { + private final CharSequence delegate; + private final int[] span; + + public NarrowingHistoryLine(CharSequence delegate, int start) { + this.delegate = delegate; + this.span = new int[] {start, -1}; + } + + @Override + public int length() { + return delegate.length(); + } + + @Override + public char charAt(int index) { + return delegate.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return delegate.subSequence(start, end); + } + + @Override + public String toString() { + return delegate.toString(); + } + + } + + private interface PersistentEntryMarker {} +} +
--- a/src/jdk.internal.le/share/classes/module-info.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.internal.le/share/classes/module-info.java Wed May 18 12:04:26 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,9 @@ exports jdk.internal.jline.console.history to jdk.scripting.nashorn.shell, jdk.jshell; + exports jdk.internal.jline.extra to + jdk.scripting.nashorn.shell, + jdk.jshell; exports jdk.internal.jline.internal to jdk.scripting.nashorn.shell, jdk.jshell;
--- a/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java Wed May 18 20:40:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 jdk.internal.vm.agent.spi; - -/** - * Service interface for jdk.hotspot.agent to provide the tools that - * jstack, jmap, jinfo will invoke, if present. - */ -public interface ToolProvider { - /** - * Returns the name of the tool provider - */ - String getName(); - - /** - * Invoke the tool provider with the given arguments - */ - void run(String... arguments); -}
--- a/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java Wed May 18 20:40:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 jdk.internal.vm.agent.spi; - -import java.lang.reflect.Layer; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; - -public final class ToolProviderFinder { - private static final Map<String, ToolProvider> providers = init(); - - public static ToolProvider find(String name) { - return providers.get(name); - } - - private static Map<String, ToolProvider> init() { - Map<String, ToolProvider> providers = new HashMap<>(); - ServiceLoader.load(Layer.boot(), ToolProvider.class) - .forEach(p -> providers.putIfAbsent(p.getName(), p)); - return providers; - } -}
--- a/src/jdk.jcmd/share/classes/module-info.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/module-info.java Wed May 18 12:04:26 2016 -0700 @@ -26,9 +26,4 @@ module jdk.jcmd { requires jdk.attach; requires jdk.jvmstat; - - exports jdk.internal.vm.agent.spi to jdk.hotspot.agent; - - uses jdk.internal.vm.agent.spi.ToolProvider; } -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java Wed May 18 12:04:26 2016 -0700 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.common; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.attach.VirtualMachineDescriptor; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.MonitoredVmUtil; +import sun.jvmstat.monitor.VmIdentifier; + +/** + * Class for finding process matching a process argument, + * excluding tool it self and returning a list containing + * the process identifiers. + */ +public class ProcessArgumentMatcher { + private String excludeCls; + private String matchClass = null; + private String singlePid = null; + private boolean matchAll = false; + + public ProcessArgumentMatcher(String pidArg, Class<?> excludeClass) { + excludeCls = excludeClass.getName(); + if (pidArg == null || pidArg.isEmpty()) { + throw new IllegalArgumentException("Pid string is invalid"); + } + if (pidArg.charAt(0) == '-') { + throw new IllegalArgumentException("Unrecognized " + pidArg); + } + try { + long pid = Long.parseLong(pidArg); + if (pid == 0) { + matchAll = true; + } else { + singlePid = String.valueOf(pid); + } + } catch (NumberFormatException nfe) { + matchClass = pidArg; + } + } + + private boolean check(VirtualMachineDescriptor vmd) { + String mainClass = null; + try { + VmIdentifier vmId = new VmIdentifier(vmd.id()); + MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); + MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); + mainClass = MonitoredVmUtil.mainClass(monitoredVm, true); + monitoredHost.detach(monitoredVm); + } catch (NullPointerException npe) { + // There is a potential race, where a running java app is being + // queried, unfortunately the java app has shutdown after this + // method is started but before getMonitoredVM is called. + // If this is the case, then the /tmp/hsperfdata_xxx/pid file + // will have disappeared and we will get a NullPointerException. + // Handle this gracefully.... + return false; + } catch (MonitorException | URISyntaxException e) { + if (e.getMessage() != null) { + System.err.println(e.getMessage()); + } else { + Throwable cause = e.getCause(); + if ((cause != null) && (cause.getMessage() != null)) { + System.err.println(cause.getMessage()); + } else { + e.printStackTrace(); + } + } + return false; + } + + if (mainClass.equals(excludeCls)) { + return false; + } + + if (matchAll || mainClass.indexOf(matchClass) != -1) { + return true; + } + + return false; + } + + public Collection<String> getPids() { + Collection<String> pids = new ArrayList<>(); + if (singlePid != null) { + pids.add(singlePid); + return pids; + } + List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); + for (VirtualMachineDescriptor vmd : vmds) { + if (check(vmd)) { + pids.add(vmd.id()); + } + } + return pids; + } +}
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java Wed May 18 12:04:26 2016 -0700 @@ -33,16 +33,14 @@ private boolean listProcesses = false; private boolean listCounters = false; private boolean showUsage = false; - private int pid = -1; private String command = null; - private String processSubstring; + private String processString = null; public boolean isListProcesses() { return listProcesses; } public boolean isListCounters() { return listCounters; } public boolean isShowUsage() { return showUsage; } - public int getPid() { return pid; } public String getCommand() { return command; } - public String getProcessSubstring() { return processSubstring; } + public String getProcessString() { return processString; } public Arguments(String[] args) { if (args.length == 0 || args[0].equals("-l")) { @@ -55,15 +53,7 @@ return; } - try { - pid = Integer.parseInt(args[0]); - } catch (NumberFormatException ex) { - // use as a partial class-name instead - if (args[0].charAt(0) != '-') { - // unless it starts with a '-' - processSubstring = args[0]; - } - } + processString = args[0]; StringBuilder sb = new StringBuilder(); for (int i = 1; i < args.length; i++) {
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java Wed May 18 12:04:26 2016 -0700 @@ -29,22 +29,22 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; -import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.net.URISyntaxException; import com.sun.tools.attach.AttachOperationFailedException; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; -import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import sun.tools.attach.HotSpotVirtualMachine; +import sun.tools.common.ProcessArgumentMatcher; import sun.tools.jstat.JStatLogger; import sun.jvmstat.monitor.Monitor; import sun.jvmstat.monitor.MonitoredHost; import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.MonitoredVmUtil; import sun.jvmstat.monitor.MonitorException; import sun.jvmstat.monitor.VmIdentifier; @@ -73,52 +73,18 @@ System.exit(0); } - List<String> pids = new ArrayList<String>(); - if (arg.getPid() == 0) { - // find all VMs - List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); - for (VirtualMachineDescriptor vmd : vmds) { - if (!isJCmdProcess(vmd)) { - pids.add(vmd.id()); - } - } - } else if (arg.getProcessSubstring() != null) { - // use the partial class-name match - List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); - for (VirtualMachineDescriptor vmd : vmds) { - if (isJCmdProcess(vmd)) { - continue; - } - try { - String mainClass = getMainClass(vmd); - if (mainClass != null - && mainClass.indexOf(arg.getProcessSubstring()) != -1) { - pids.add(vmd.id()); - } - } catch (MonitorException|URISyntaxException e) { - if (e.getMessage() != null) { - System.err.println(e.getMessage()); - } else { - Throwable cause = e.getCause(); - if ((cause != null) && (cause.getMessage() != null)) { - System.err.println(cause.getMessage()); - } else { - e.printStackTrace(); - } - } - } - } - if (pids.isEmpty()) { - System.err.println("Could not find any processes matching : '" - + arg.getProcessSubstring() + "'"); - System.exit(1); - } - } else if (arg.getPid() == -1) { + Collection<String> pids = Collections.emptyList(); + try { + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(arg.getProcessString(), JCmd.class); + pids = ap.getPids(); + } catch (IllegalArgumentException iae) { System.err.println("Invalid pid specified"); System.exit(1); - } else { - // Use the found pid - pids.add(arg.getPid() + ""); + } + if (pids.isEmpty()) { + System.err.println("Could not find any processes matching : '" + + arg.getProcessString() + "'"); + System.exit(1); } boolean success = true; @@ -199,36 +165,6 @@ } } - private static boolean isJCmdProcess(VirtualMachineDescriptor vmd) { - try { - String mainClass = getMainClass(vmd); - return mainClass != null && mainClass.equals(JCmd.class.getName()); - } catch (URISyntaxException|MonitorException ex) { - return false; - } - } - - private static String getMainClass(VirtualMachineDescriptor vmd) - throws URISyntaxException, MonitorException { - try { - String mainClass = null; - VmIdentifier vmId = new VmIdentifier(vmd.id()); - MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); - MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); - mainClass = MonitoredVmUtil.mainClass(monitoredVm, true); - monitoredHost.detach(monitoredVm); - return mainClass; - } catch(NullPointerException e) { - // There is a potential race, where a running java app is being - // queried, unfortunately the java app has shutdown after this - // method is started but before getMonitoredVM is called. - // If this is the case, then the /tmp/hsperfdata_xxx/pid file - // will have disappeared and we will get a NullPointerException. - // Handle this gracefully.... - return null; - } - } - /** * Class to compare two Monitor objects by name in ascending order. * (from jstat)
--- a/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java Wed May 18 12:04:26 2016 -0700 @@ -25,15 +25,14 @@ package sun.tools.jinfo; -import java.util.Arrays; import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import com.sun.tools.attach.VirtualMachine; import sun.tools.attach.HotSpotVirtualMachine; -import jdk.internal.vm.agent.spi.ToolProvider; -import jdk.internal.vm.agent.spi.ToolProviderFinder; +import sun.tools.common.ProcessArgumentMatcher; /* * This class is the main class for the JInfo utility. It parses its arguments @@ -41,157 +40,96 @@ * or an SA tool. */ final public class JInfo { - private static final String SA_JINFO_TOOL_NAME = "jinfo"; - private boolean useSA = false; - private String[] args = null; - private JInfo(String[] args) throws IllegalArgumentException { + public static void main(String[] args) throws Exception { if (args.length == 0) { - throw new IllegalArgumentException(); + usage(1); // no arguments + } + checkForUnsupportedOptions(args); + + boolean doFlag = false; + boolean doFlags = false; + boolean doSysprops = false; + + // Parse the options (arguments starting with "-" ) + int optionCount = 0; + while (optionCount < args.length) { + String arg = args[optionCount]; + if (!arg.startsWith("-")) { + break; + } + + optionCount++; + + if (arg.equals("-help") || arg.equals("-h")) { + usage(0); + } + + if (arg.equals("-flag")) { + doFlag = true; + continue; + } + + if (arg.equals("-flags")) { + doFlags = true; + continue; + } + + if (arg.equals("-sysprops")) { + doSysprops = true; + continue; + } } - int argCopyIndex = 0; - // First determine if we should launch SA or not - if (args[0].equals("-F")) { - // delete the -F - argCopyIndex = 1; - useSA = true; - } else if (args[0].equals("-flags") - || args[0].equals("-sysprops")) - { - if (args.length == 2) { - if (!isPid(args[1])) { - // If args[1] doesn't parse to a number then - // it must be the SA debug server - // (otherwise it is the pid) - useSA = true; - } - } else if (args.length == 3) { - // arguments include an executable and a core file - useSA = true; - } else { - throw new IllegalArgumentException(); - } - } else if (!args[0].startsWith("-")) { - if (args.length == 2) { - // the only arguments are an executable and a core file - useSA = true; - } else if (args.length == 1) { - if (!isPid(args[0])) { - // The only argument is not a PID; it must be SA debug - // server - useSA = true; - } - } else { - throw new IllegalArgumentException(); - } - } else if (args[0].equals("-h") || args[0].equals("-help")) { - if (args.length > 1) { - throw new IllegalArgumentException(); - } - } else if (args[0].equals("-flag")) { - if (args.length == 3) { - if (!isPid(args[2])) { - throw new IllegalArgumentException(); - } - } else { - throw new IllegalArgumentException(); - } - } else { - throw new IllegalArgumentException(); + // Next we check the parameter count. -flag allows extra parameters + int paramCount = args.length - optionCount; + if ((doFlag && paramCount != 2) || ((!doFlag && paramCount != 1))) { + usage(1); } - this.args = Arrays.copyOfRange(args, argCopyIndex, args.length); - } - - @SuppressWarnings("fallthrough") - private void execute() throws Exception { - if (args[0].equals("-h") - || args[0].equals("-help")) { - usage(0); + if (!doFlag && !doFlags && !doSysprops) { + // Print flags and sysporps if no options given + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class); + Collection<String> pids = ap.getPids(); + for (String pid : pids) { + if (pids.size() > 1) { + System.out.println("Pid:" + pid); + } + sysprops(pid); + System.out.println(); + flags(pid); + System.out.println(); + commandLine(pid); + } } - if (useSA) { - // SA only supports -flags or -sysprops - if (args[0].startsWith("-")) { - if (!(args[0].equals("-flags") || args[0].equals("-sysprops"))) { - usage(1); + if (doFlag) { + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount+1], JInfo.class); + Collection<String> pids = ap.getPids(); + for (String pid : pids) { + if (pids.size() > 1) { + System.out.println("Pid:" + pid); + } + flag(pid, args[optionCount]); + } + } + else if (doFlags || doSysprops) { + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(args[optionCount], JInfo.class); + Collection<String> pids = ap.getPids(); + for (String pid : pids) { + if (pids.size() > 1) { + System.out.println("Pid:" + pid); + } + if (doFlags) { + flags(pid); + } + else if (doSysprops) { + sysprops(pid); } } - - // invoke SA which does it's own argument parsing - runTool(); - - } else { - // Now we can parse arguments for the non-SA case - String pid = null; - - switch(args[0]) { - case "-flag": - if (args.length != 3) { - usage(1); - } - String option = args[1]; - pid = args[2]; - flag(pid, option); - break; - case "-flags": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - flags(pid); - break; - case "-sysprops": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - sysprops(pid); - break; - case "-help": - case "-h": - usage(0); - // Fall through - default: - if (args.length == 1) { - // no flags specified, we do -sysprops and -flags - pid = args[0]; - sysprops(pid); - System.out.println(); - flags(pid); - System.out.println(); - commandLine(pid); - } else { - usage(1); - } - } } } - public static void main(String[] args) throws Exception { - JInfo jinfo = null; - try { - jinfo = new JInfo(args); - jinfo.execute(); - } catch (IllegalArgumentException e) { - usage(1); - } - } - - private static boolean isPid(String arg) { - return arg.matches("[0-9]+"); - } - - // Invoke SA tool with the given arguments - private void runTool() throws Exception { - ToolProvider tool = ToolProviderFinder.find(SA_JINFO_TOOL_NAME); - if (tool == null) { - usage(1); - } - tool.run(args); - } - private static void flag(String pid, String option) throws IOException { HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid); String flag; @@ -274,46 +212,49 @@ vm.detach(); } + private static void checkForUnsupportedOptions(String[] args) { + // Check arguments for -F, and non-numeric value + // and warn the user that SA is not supported anymore + int maxCount = 1; + int paramCount = 0; - // print usage message - private static void usage(int exit) { - boolean usageSA = ToolProviderFinder.find(SA_JINFO_TOOL_NAME) != null; - - System.err.println("Usage:"); - if (usageSA) { - System.err.println(" jinfo [option] <pid>"); - System.err.println(" (to connect to a running process)"); - System.err.println(" jinfo -F [option] <pid>"); - System.err.println(" (to connect to a hung process)"); - System.err.println(" jinfo [option] <executable> <core>"); - System.err.println(" (to connect to a core file)"); - System.err.println(" jinfo [option] [server_id@]<remote server IP or hostname>"); - System.err.println(" (to connect to remote debug server)"); - System.err.println(""); - System.err.println("where <option> is one of:"); - System.err.println(" for running processes:"); - System.err.println(" -flag <name> to print the value of the named VM flag"); - System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); - System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); - System.err.println(" for running or hung processes and core files:"); - System.err.println(" -flags to print VM flags"); - System.err.println(" -sysprops to print Java system properties"); - System.err.println(" <no option> to print both VM flags and system properties"); - System.err.println(" -h | -help to print this help message"); - } else { - System.err.println(" jinfo <option> <pid>"); - System.err.println(" (to connect to a running process)"); - System.err.println(""); - System.err.println("where <option> is one of:"); - System.err.println(" -flag <name> to print the value of the named VM flag"); - System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); - System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); - System.err.println(" -flags to print VM flags"); - System.err.println(" -sysprops to print Java system properties"); - System.err.println(" <no option> to print both VM flags and system properties"); - System.err.println(" -h | -help to print this help message"); + for (String s : args) { + if (s.equals("-F")) { + SAOptionError("-F option used"); + } + if (s.equals("-flag")) { + maxCount = 2; + } + if (! s.startsWith("-")) { + paramCount += 1; + } } + if (paramCount > maxCount) { + SAOptionError("More than " + maxCount + " non-option argument"); + } + } + + private static void SAOptionError(String msg) { + System.err.println("Error: " + msg); + System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jinfo instead"); + System.exit(1); + } + + // print usage message + private static void usage(int exit) { + System.err.println("Usage:"); + System.err.println(" jinfo <option> <pid>"); + System.err.println(" (to connect to a running process)"); + System.err.println(""); + System.err.println("where <option> is one of:"); + System.err.println(" -flag <name> to print the value of the named VM flag"); + System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); + System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); + System.err.println(" -flags to print VM flags"); + System.err.println(" -sysprops to print Java system properties"); + System.err.println(" <no option> to print both VM flags and system properties"); + System.err.println(" -h | -help to print this help message"); System.exit(exit); } }
--- a/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java Wed May 18 12:04:26 2016 -0700 @@ -28,12 +28,13 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Collection; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.AttachNotSupportedException; import sun.tools.attach.HotSpotVirtualMachine; -import jdk.internal.vm.agent.spi.ToolProvider; -import jdk.internal.vm.agent.spi.ToolProviderFinder; +import sun.tools.common.ProcessArgumentMatcher; /* * This class is the main class for the JMap utility. It parses its arguments @@ -44,34 +45,18 @@ */ public class JMap { - // Options handled by the attach mechanism - private static String HISTO_OPTION = "-histo"; - private static String LIVE_HISTO_OPTION = "-histo:live"; - private static String DUMP_OPTION_PREFIX = "-dump:"; - - // These options imply the use of a SA tool - private static String SA_TOOL_OPTIONS = - "-heap|-heap:format=b|-clstats|-finalizerinfo"; - - // The -F (force) option is currently not passed through to SA - private static String FORCE_SA_OPTION = "-F"; - - // Default option (if nothing provided) - private static String DEFAULT_OPTION = "-pmap"; - public static void main(String[] args) throws Exception { if (args.length == 0) { usage(1); // no arguments } - // used to indicate if we should use SA - boolean useSA = false; + checkForUnsupportedOptions(args); - // the chosen option (-heap, -dump:*, ... ) + // the chosen option String option = null; // First iterate over the options (arguments starting with -). There should be - // one (but maybe two if -F is also used). + // one. int optionCount = 0; while (optionCount < args.length) { String arg = args[optionCount]; @@ -80,8 +65,6 @@ } if (arg.equals("-help") || arg.equals("-h")) { usage(0); - } else if (arg.equals(FORCE_SA_OPTION)) { - useSA = true; } else { if (option != null) { usage(1); // option already specified @@ -93,123 +76,102 @@ // if no option provided then use default. if (option == null) { - option = DEFAULT_OPTION; - } - if (option.matches(SA_TOOL_OPTIONS)) { - useSA = true; + usage(0); } - // Next we check the parameter count. For the SA tools there are - // one or two parameters. For the built-in -dump option there is - // only one parameter (the process-id) + // Next we check the parameter count. int paramCount = args.length - optionCount; - if (paramCount == 0 || paramCount > 2) { + if (paramCount != 1) { usage(1); } - if (optionCount == 0 || paramCount != 1) { - useSA = true; - } else { - // the parameter for the -dump option is a process-id. - // If it doesn't parse to a number then it must be SA - // debug server - if (!args[optionCount].matches("[0-9]+")) { - useSA = true; + String pidArg = args[1]; + // Here we handle the built-in options + // As more options are added we should create an abstract tool class and + // have a table to map the options + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JMap.class); + Collection<String> pids = ap.getPids(); + for (String pid : pids) { + if (pids.size() > 1) { + System.out.println("Pid:" + pid); } - } - - - // at this point we know if we are executing an SA tool or a built-in - // option. - - if (useSA) { - // parameters (<pid> or <exe> <core>) - String params[] = new String[paramCount]; - for (int i=optionCount; i<args.length; i++ ){ - params[i-optionCount] = args[i]; - } - runTool(option, params); - - } else { - String pid = args[1]; - // Here we handle the built-in options - // As more options are added we should create an abstract tool class and - // have a table to map the options - if (option.equals(HISTO_OPTION)) { - histo(pid, false); - } else if (option.equals(LIVE_HISTO_OPTION)) { - histo(pid, true); - } else if (option.startsWith(DUMP_OPTION_PREFIX)) { - dump(pid, option); + if (option.equals("-histo")) { + histo(pid, ""); + } else if (option.startsWith("-histo:")) { + histo(pid, option.substring("-histo:".length())); + } else if (option.startsWith("-dump:")) { + dump(pid, option.substring("-dump:".length())); + } else if (option.equals("-finalizerinfo")) { + executeCommandForPid(pid, "jcmd", "GC.finalizer_info"); + } else if (option.equals("-clstats")) { + executeCommandForPid(pid, "jcmd", "GC.class_stats"); } else { - usage(1); + usage(1); } } } - // Invoke SA tool with the given arguments - private static void runTool(String option, String args[]) throws Exception { - String[][] tools = { - { "-pmap", "pmap" }, - { "-heap", "heapSummary" }, - { "-heap:format=b", "heapDumper" }, - { "-histo", "objectHistogram" }, - { "-clstats", "classLoaderStats" }, - { "-finalizerinfo", "finalizerInfo" }, - }; + private static void executeCommandForPid(String pid, String command, Object ... args) + throws AttachNotSupportedException, IOException, + UnsupportedEncodingException { + VirtualMachine vm = VirtualMachine.attach(pid); - String name = null; + // Cast to HotSpotVirtualMachine as this is an + // implementation specific method. + HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm; + try (InputStream in = hvm.executeCommand(command, args)) { + // read to EOF and just print output + byte b[] = new byte[256]; + int n; + do { + n = in.read(b); + if (n > 0) { + String s = new String(b, 0, n, "UTF-8"); + System.out.print(s); + } + } while (n > 0); + } + vm.detach(); + } - // -dump option needs to be handled in a special way - if (option.startsWith(DUMP_OPTION_PREFIX)) { - // first check that the option can be parsed - String fn = parseDumpOptions(option); - if (fn == null) { - usage(1); - } - - // tool for heap dumping - name = "heapDumper"; - - // HeapDumper -f <file> - args = prepend(fn, args); - args = prepend("-f", args); - } else { - int i=0; - while (i < tools.length) { - if (option.equals(tools[i][0])) { - name = tools[i][1]; - break; - } - i++; - } + private static void histo(String pid, String options) + throws AttachNotSupportedException, IOException, + UnsupportedEncodingException { + String liveopt = "-all"; + if (options.equals("") || options.equals("all")) { + // pass } - if (name == null) { - usage(1); // no mapping to tool + else if (options.equals("live")) { + liveopt = "-live"; } - - // Tool not available on this platform. - ToolProvider tool = ToolProviderFinder.find(name); - if (tool == null) { + else { usage(1); } - // invoke the main method with the arguments - tool.run(args); + // inspectHeap is not the same as jcmd GC.class_histogram + executeCommandForPid(pid, "inspectheap", liveopt); } - private static final String LIVE_OBJECTS_OPTION = "-live"; - private static final String ALL_OBJECTS_OPTION = "-all"; - private static void histo(String pid, boolean live) throws IOException { - VirtualMachine vm = attach(pid); - InputStream in = ((HotSpotVirtualMachine)vm). - heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION); - drain(vm, in); - } + private static void dump(String pid, String options) + throws AttachNotSupportedException, IOException, + UnsupportedEncodingException { - private static void dump(String pid, String options) throws IOException { - // parse the options to get the dump filename - String filename = parseDumpOptions(options); + String subopts[] = options.split(","); + String filename = null; + String liveopt = "-all"; + + for (int i = 0; i < subopts.length; i++) { + String subopt = subopts[i]; + if (subopt.equals("live")) { + liveopt = "-live"; + } else if (subopt.startsWith("file=")) { + // file=<file> - check that <file> is specified + if (subopt.length() > 5) { + filename = subopt.substring(5); + } + } + } + if (filename == null) { usage(1); // invalid options or no filename } @@ -219,156 +181,73 @@ // working directory rather than the directory where jmap // is executed. filename = new File(filename).getCanonicalPath(); - - // dump live objects only or not - boolean live = isDumpLiveObjects(options); - - VirtualMachine vm = attach(pid); - System.out.println("Dumping heap to " + filename + " ..."); - InputStream in = ((HotSpotVirtualMachine)vm). - dumpHeap((Object)filename, - (live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION)); - drain(vm, in); + // dumpHeap is not the same as jcmd GC.heap_dump + executeCommandForPid(pid, "dumpheap", filename, liveopt); } - // Parse the options to the -dump option. Valid options are format=b and - // file=<file>. Returns <file> if provided. Returns null if <file> not - // provided, or invalid option. - private static String parseDumpOptions(String arg) { - assert arg.startsWith(DUMP_OPTION_PREFIX); + private static void checkForUnsupportedOptions(String[] args) { + // Check arguments for -F, -m, and non-numeric value + // and warn the user that SA is not supported anymore - String filename = null; + int paramCount = 0; - // options are separated by comma (,) - String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(","); + for (String s : args) { + if (s.equals("-F")) { + SAOptionError("-F option used"); + } - for (int i=0; i<options.length; i++) { - String option = options[i]; + if (s.equals("-heap")) { + SAOptionError("-heap option used"); + } - if (option.equals("format=b")) { - // ignore format (not needed at this time) - } else if (option.equals("live")) { - // a valid suboption - } else { + /* Reimplemented using jcmd, output format is different + from original one - // file=<file> - check that <file> is specified - if (option.startsWith("file=")) { - filename = option.substring(5); - if (filename.length() == 0) { - return null; - } - } else { - return null; // option not recognized - } + if (s.equals("-clstats")) { + warnSA("-clstats option used"); + } + + if (s.equals("-finalizerinfo")) { + warnSA("-finalizerinfo option used"); + } + */ + + if (! s.startsWith("-")) { + paramCount += 1; } } - return filename; - } - private static boolean isDumpLiveObjects(String arg) { - // options are separated by comma (,) - String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(","); - for (String suboption : options) { - if (suboption.equals("live")) { - return true; - } - } - return false; - } - - // Attach to <pid>, existing if we fail to attach - private static VirtualMachine attach(String pid) { - try { - return VirtualMachine.attach(pid); - } catch (Exception x) { - String msg = x.getMessage(); - if (msg != null) { - System.err.println(pid + ": " + msg); - } else { - x.printStackTrace(); - } - if ((x instanceof AttachNotSupportedException) && haveSA()) { - System.err.println("The -F option can be used when the " + - "target process is not responding"); - } - System.exit(1); - return null; // keep compiler happy + if (paramCount > 1) { + SAOptionError("More than one non-option argument"); } } - // Read the stream from the target VM until EOF, then detach - private static void drain(VirtualMachine vm, InputStream in) throws IOException { - // read to EOF and just print output - byte b[] = new byte[256]; - int n; - do { - n = in.read(b); - if (n > 0) { - String s = new String(b, 0, n, "UTF-8"); - System.out.print(s); - } - } while (n > 0); - in.close(); - vm.detach(); - } - - // return a new string array with arg as the first element - private static String[] prepend(String arg, String args[]) { - String[] newargs = new String[args.length+1]; - newargs[0] = arg; - System.arraycopy(args, 0, newargs, 1, args.length); - return newargs; - } - - // returns true if SA is available - private static boolean haveSA() { - return ToolProviderFinder.find("heapSummary") != null; + private static void SAOptionError(String msg) { + System.err.println("Error: " + msg); + System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jmap instead"); + System.exit(1); } // print usage message private static void usage(int exit) { System.err.println("Usage:"); - if (haveSA()) { - System.err.println(" jmap [option] <pid>"); - System.err.println(" (to connect to running process)"); - System.err.println(" jmap [option] <executable <core>"); - System.err.println(" (to connect to a core file)"); - System.err.println(" jmap [option] [server_id@]<remote server IP or hostname>"); - System.err.println(" (to connect to remote debug server)"); - System.err.println(""); - System.err.println("where <option> is one of:"); - System.err.println(" <none> to print same info as Solaris pmap"); - System.err.println(" -heap to print java heap summary"); - System.err.println(" -histo[:live] to print histogram of java object heap; if the \"live\""); - System.err.println(" suboption is specified, only count live objects"); - System.err.println(" -clstats to print class loader statistics"); - System.err.println(" -finalizerinfo to print information on objects awaiting finalization"); - System.err.println(" -dump:<dump-options> to dump java heap in hprof binary format"); - System.err.println(" dump-options:"); - System.err.println(" live dump only live objects; if not specified,"); - System.err.println(" all objects in the heap are dumped."); - System.err.println(" format=b binary format"); - System.err.println(" file=<file> dump heap to <file>"); - System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>"); - System.err.println(" -F force. Use with -dump:<dump-options> <pid> or -histo"); - System.err.println(" to force a heap dump or histogram when <pid> does not"); - System.err.println(" respond. The \"live\" suboption is not supported"); - System.err.println(" in this mode."); - System.err.println(" -h | -help to print this help message"); - System.err.println(" -J<flag> to pass <flag> directly to the runtime system"); - } else { - System.err.println(" jmap -histo <pid>"); - System.err.println(" (to connect to running process and print histogram of java object heap"); - System.err.println(" jmap -dump:<dump-options> <pid>"); - System.err.println(" (to connect to running process and dump java heap)"); - System.err.println(""); - System.err.println(" dump-options:"); - System.err.println(" format=b binary default"); - System.err.println(" file=<file> dump heap to <file>"); - System.err.println(""); - System.err.println(" Example: jmap -dump:format=b,file=heap.bin <pid>"); - } - + System.err.println(" jmap -clstats <pid>"); + System.err.println(" to connect to running process and print class loader statistics"); + System.err.println(" jmap -finalizerinfo <pid>"); + System.err.println(" to connect to running process and print information on objects awaiting finalization"); + System.err.println(" jmap -histo[:live] <pid>"); + System.err.println(" to connect to running process and print histogram of java object heap"); + System.err.println(" if the \"live\" suboption is specified, only count live objects"); + System.err.println(" jmap -dump:<dump-options> <pid>"); + System.err.println(" to connect to running process and dump java heap"); + System.err.println(""); + System.err.println(" dump-options:"); + System.err.println(" live dump only live objects; if not specified,"); + System.err.println(" all objects in the heap are dumped."); + System.err.println(" format=b binary format"); + System.err.println(" file=<file> dump heap to <file>"); + System.err.println(""); + System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>"); System.exit(exit); } }
--- a/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java Wed May 18 20:40:17 2016 +0300 +++ b/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java Wed May 18 12:04:26 2016 -0700 @@ -26,12 +26,11 @@ package sun.tools.jstack; import java.io.InputStream; +import java.util.Collection; import com.sun.tools.attach.VirtualMachine; -import com.sun.tools.attach.AttachNotSupportedException; import sun.tools.attach.HotSpotVirtualMachine; -import jdk.internal.vm.agent.spi.ToolProvider; -import jdk.internal.vm.agent.spi.ToolProviderFinder; +import sun.tools.common.ProcessArgumentMatcher; /* * This class is the main class for the JStack utility. It parses its arguments @@ -39,15 +38,14 @@ * obtained the thread dump from a target process using the VM attach mechanism */ public class JStack { - private static final String SA_JSTACK_TOOL_NAME = "jstack"; public static void main(String[] args) throws Exception { if (args.length == 0) { usage(1); // no arguments } - boolean useSA = false; - boolean mixed = false; + checkForUnsupportedOptions(args); + boolean locks = false; // Parse the options (arguments starting with "-" ) @@ -60,87 +58,40 @@ if (arg.equals("-help") || arg.equals("-h")) { usage(0); } - else if (arg.equals("-F")) { - useSA = true; - } else { - if (arg.equals("-m")) { - mixed = true; + if (arg.equals("-l")) { + locks = true; } else { - if (arg.equals("-l")) { - locks = true; - } else { - usage(1); - } + usage(1); } } optionCount++; } - // mixed stack implies SA tool - if (mixed) { - useSA = true; + // Next we check the parameter count. + int paramCount = args.length - optionCount; + if (paramCount != 1) { + usage(1); } - // Next we check the parameter count. If there are two parameters - // we assume core file and executable so we use SA. - int paramCount = args.length - optionCount; - if (paramCount == 0 || paramCount > 2) { - usage(1); + // pass -l to thread dump operation to get extra lock info + String pidArg = args[optionCount]; + String params[]; + if (locks) { + params = new String[] { "-l" }; + } else { + params = new String[0]; } - if (paramCount == 2) { - useSA = true; - } else { - // If we can't parse it as a pid then it must be debug server - if (!args[optionCount].matches("[0-9]+")) { - useSA = true; - } - } - - // now execute using the SA JStack tool or the built-in thread dumper - if (useSA) { - // parameters (<pid> or <exe> <core> - String params[] = new String[paramCount]; - for (int i=optionCount; i<args.length; i++ ){ - params[i-optionCount] = args[i]; - } - runJStackTool(mixed, locks, params); - } else { - // pass -l to thread dump operation to get extra lock info - String pid = args[optionCount]; - String params[]; - if (locks) { - params = new String[] { "-l" }; - } else { - params = new String[0]; + ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg, JStack.class); + Collection<String> pids = ap.getPids(); + for (String pid : pids) { + if (pids.size() > 1) { + System.out.println("Pid:" + pid); } runThreadDump(pid, params); } } - // SA JStack tool - private static boolean isAgentToolPresent() { - return ToolProviderFinder.find(SA_JSTACK_TOOL_NAME) != null; - } - - private static void runJStackTool(boolean mixed, boolean locks, String args[]) throws Exception { - ToolProvider tool = ToolProviderFinder.find(SA_JSTACK_TOOL_NAME); - if (tool == null) { - usage(1); // SA not available - } - - // JStack tool also takes -m and -l arguments - if (mixed) { - args = prepend("-m", args); - } - if (locks) { - args = prepend("-l", args); - } - - tool.run(args); - } - - // Attach to pid and perform a thread dump private static void runThreadDump(String pid, String args[]) throws Exception { VirtualMachine vm = null; @@ -153,10 +104,6 @@ } else { x.printStackTrace(); } - if ((x instanceof AttachNotSupportedException) && isAgentToolPresent()) { - System.err.println("The -F option can be used when the target " + - "process is not responding"); - } System.exit(1); } @@ -178,12 +125,35 @@ vm.detach(); } - // return a new string array with arg as the first element - private static String[] prepend(String arg, String args[]) { - String[] newargs = new String[args.length+1]; - newargs[0] = arg; - System.arraycopy(args, 0, newargs, 1, args.length); - return newargs; + private static void checkForUnsupportedOptions(String[] args) { + // Check arguments for -F, -m, and non-numeric value + // and warn the user that SA is not supported anymore + + int paramCount = 0; + + for (String s : args) { + if (s.equals("-F")) { + SAOptionError("-F option used"); + } + + if (s.equals("-m")) { + SAOptionError("-m option used"); + } + + if (! s.startsWith("-")) { + paramCount += 1; + } + } + + if (paramCount > 1) { + SAOptionError("More than one non-option argument"); + } + } + + private static void SAOptionError(String msg) { + System.err.println("Error: " + msg); + System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jstack instead"); + System.exit(1); } // print usage message @@ -191,25 +161,8 @@ System.err.println("Usage:"); System.err.println(" jstack [-l] <pid>"); System.err.println(" (to connect to running process)"); - - if (isAgentToolPresent()) { - System.err.println(" jstack -F [-m] [-l] <pid>"); - System.err.println(" (to connect to a hung process)"); - System.err.println(" jstack [-m] [-l] <executable> <core>"); - System.err.println(" (to connect to a core file)"); - System.err.println(" jstack [-m] [-l] [server_id@]<remote server IP or hostname>"); - System.err.println(" (to connect to a remote debug server)"); - } - System.err.println(""); System.err.println("Options:"); - - if (isAgentToolPresent()) { - System.err.print