# HG changeset patch # User shade # Date 1528793529 -7200 # Node ID 25d779d6bafc4f730647b2b450c8b99a36307671 # Parent f21420b61fd2ef3d7ed8bd015a09046d61676184# Parent 7f166e010af44f790b56c7d75b44e72ee77d5216 Merge diff -r f21420b61fd2 -r 25d779d6bafc make/autoconf/spec.gmk.in --- a/make/autoconf/spec.gmk.in Tue Jun 12 08:02:39 2018 +0200 +++ b/make/autoconf/spec.gmk.in Tue Jun 12 10:52:09 2018 +0200 @@ -858,7 +858,12 @@ else ifneq ($(DEBUG_LEVEL), release) DEBUG_PART := -$(DEBUG_LEVEL) endif -JDK_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART).tar.gz +ifeq ($(OPENJDK_TARGET_OS), windows) + JDK_BUNDLE_EXTENSION := zip +else + JDK_BUNDLE_EXTENSION := tar.gz +endif +JDK_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART).$(JDK_BUNDLE_EXTENSION) JDK_SYMBOLS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART)-symbols.tar.gz TEST_DEMOS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-tests-demos$(DEBUG_PART).tar.gz TEST_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-tests$(DEBUG_PART).tar.gz diff -r f21420b61fd2 -r 25d779d6bafc make/conf/jib-profiles.js --- a/make/conf/jib-profiles.js Tue Jun 12 08:02:39 2018 +0200 +++ b/make/conf/jib-profiles.js Tue Jun 12 10:52:09 2018 +0200 @@ -272,13 +272,14 @@ */ common.main_profile_artifacts = function (o) { var jdk_subdir = (o.jdk_subdir != null ? o.jdk_subdir : "jdk-" + data.version); + var jdk_suffix = (o.jdk_suffix != null ? o.jdk_suffix : "tar.gz"); var pf = o.platform return { artifacts: { jdk: { - local: "bundles/\\(jdk.*bin.tar.gz\\)", + local: "bundles/\\(jdk.*bin." + jdk_suffix + "\\)", remote: [ - "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin.tar.gz", + "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin." + jdk_suffix, "bundles/" + pf + "/\\1" ], subdir: jdk_subdir, @@ -320,13 +321,14 @@ */ common.debug_profile_artifacts = function (o) { var jdk_subdir = "jdk-" + data.version + "/fastdebug"; + var jdk_suffix = (o.jdk_suffix != null ? o.jdk_suffix : "tar.gz"); var pf = o.platform return { artifacts: { jdk: { - local: "bundles/\\(jdk.*bin-debug.tar.gz\\)", + local: "bundles/\\(jdk.*bin-debug." + jdk_suffix + "\\)", remote: [ - "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin-debug.tar.gz", + "bundles/" + pf + "/jdk-" + data.version + "_" + pf + "_bin-debug." + jdk_suffix, "bundles/" + pf + "/\\1" ], subdir: jdk_subdir, @@ -590,9 +592,11 @@ }, "windows-x64": { platform: "windows-x64", + jdk_suffix: "zip", }, "windows-x86": { platform: "windows-x86", + jdk_suffix: "zip", }, "linux-aarch64": { platform: "linux-aarch64", diff -r f21420b61fd2 -r 25d779d6bafc src/hotspot/share/gc/shared/oopStorage.cpp --- a/src/hotspot/share/gc/shared/oopStorage.cpp Tue Jun 12 08:02:39 2018 +0200 +++ b/src/hotspot/share/gc/shared/oopStorage.cpp Tue Jun 12 10:52:09 2018 +0200 @@ -52,9 +52,7 @@ assert(_next == NULL, "deleting attached block"); } -OopStorage::AllocateList::AllocateList(const AllocateEntry& (*get_entry)(const Block& block)) : - _head(NULL), _tail(NULL), _get_entry(get_entry) -{} +OopStorage::AllocateList::AllocateList() : _head(NULL), _tail(NULL) {} OopStorage::AllocateList::~AllocateList() { // ~OopStorage() empties its lists before destroying them. @@ -68,8 +66,8 @@ assert(_tail == NULL, "invariant"); _head = _tail = █ } else { - _get_entry(block)._next = old; - _get_entry(*old)._prev = █ + block.allocate_entry()._next = old; + old->allocate_entry()._prev = █ _head = █ } } @@ -80,14 +78,14 @@ assert(_head == NULL, "invariant"); _head = _tail = █ } else { - _get_entry(*old)._next = █ - _get_entry(block)._prev = old; + old->allocate_entry()._next = █ + block.allocate_entry()._prev = old; _tail = █ } } void OopStorage::AllocateList::unlink(const Block& block) { - const AllocateEntry& block_entry = _get_entry(block); + const AllocateEntry& block_entry = block.allocate_entry(); const Block* prev_blk = block_entry._prev; const Block* next_blk = block_entry._next; block_entry._prev = NULL; @@ -98,15 +96,15 @@ _head = _tail = NULL; } else if (prev_blk == NULL) { assert(_head == &block, "invariant"); - _get_entry(*next_blk)._prev = NULL; + next_blk->allocate_entry()._prev = NULL; _head = next_blk; } else if (next_blk == NULL) { assert(_tail == &block, "invariant"); - _get_entry(*prev_blk)._next = NULL; + prev_blk->allocate_entry()._next = NULL; _tail = prev_blk; } else { - _get_entry(*next_blk)._prev = prev_blk; - _get_entry(*prev_blk)._next = next_blk; + next_blk->allocate_entry()._prev = prev_blk; + prev_blk->allocate_entry()._next = next_blk; } } @@ -232,10 +230,6 @@ const_cast(_owner) = NULL; } -const OopStorage::AllocateEntry& OopStorage::Block::get_allocate_entry(const Block& block) { - return block._allocate_entry; -} - size_t OopStorage::Block::allocation_size() { // _data must be first member, so aligning Block aligns _data. STATIC_ASSERT(_data_pos == 0); @@ -769,7 +763,7 @@ Mutex* active_mutex) : _name(dup_name(name)), _active_array(ActiveArray::create(initial_active_array_size)), - _allocate_list(&Block::get_allocate_entry), + _allocate_list(), _deferred_updates(NULL), _allocate_mutex(allocate_mutex), _active_mutex(active_mutex), diff -r f21420b61fd2 -r 25d779d6bafc src/hotspot/share/gc/shared/oopStorage.hpp --- a/src/hotspot/share/gc/shared/oopStorage.hpp Tue Jun 12 08:02:39 2018 +0200 +++ b/src/hotspot/share/gc/shared/oopStorage.hpp Tue Jun 12 10:52:09 2018 +0200 @@ -178,14 +178,13 @@ class AllocateList { const Block* _head; const Block* _tail; - const AllocateEntry& (*_get_entry)(const Block& block); // Noncopyable. AllocateList(const AllocateList&); AllocateList& operator=(const AllocateList&); public: - AllocateList(const AllocateEntry& (*get_entry)(const Block& block)); + AllocateList(); ~AllocateList(); Block* head(); diff -r f21420b61fd2 -r 25d779d6bafc src/hotspot/share/gc/shared/oopStorage.inline.hpp --- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp Tue Jun 12 08:02:39 2018 +0200 +++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp Tue Jun 12 10:52:09 2018 +0200 @@ -158,7 +158,7 @@ Block& operator=(const Block&); public: - static const AllocateEntry& get_allocate_entry(const Block& block); + const AllocateEntry& allocate_entry() const; static size_t allocation_size(); static size_t allocation_alignment_shift(); @@ -214,19 +214,19 @@ } inline OopStorage::Block* OopStorage::AllocateList::prev(Block& block) { - return const_cast(_get_entry(block)._prev); + return const_cast(block.allocate_entry()._prev); } inline OopStorage::Block* OopStorage::AllocateList::next(Block& block) { - return const_cast(_get_entry(block)._next); + return const_cast(block.allocate_entry()._next); } inline const OopStorage::Block* OopStorage::AllocateList::prev(const Block& block) const { - return _get_entry(block)._prev; + return block.allocate_entry()._prev; } inline const OopStorage::Block* OopStorage::AllocateList::next(const Block& block) const { - return _get_entry(block)._next; + return block.allocate_entry()._next; } template @@ -296,7 +296,11 @@ return SkipNullFn(f); } -// Inline Block accesses for use in iteration inner loop. +// Inline Block accesses for use in iteration loops. + +inline const OopStorage::AllocateEntry& OopStorage::Block::allocate_entry() const { + return _allocate_entry; +} inline void OopStorage::Block::check_index(unsigned index) const { assert(index < ARRAY_SIZE(_data), "Index out of bounds: %u", index); diff -r f21420b61fd2 -r 25d779d6bafc src/java.base/share/classes/javax/crypto/CipherSpi.java --- a/src/java.base/share/classes/javax/crypto/CipherSpi.java Tue Jun 12 08:02:39 2018 +0200 +++ b/src/java.base/share/classes/javax/crypto/CipherSpi.java Tue Jun 12 10:52:09 2018 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -755,6 +755,7 @@ return 0; } int outLenNeeded = engineGetOutputSize(inLen); + if (output.remaining() < outLenNeeded) { throw new ShortBufferException("Need at least " + outLenNeeded + " bytes of space in output buffer"); @@ -762,98 +763,77 @@ boolean a1 = input.hasArray(); boolean a2 = output.hasArray(); - - if (a1 && a2) { - byte[] inArray = input.array(); - int inOfs = input.arrayOffset() + inPos; - byte[] outArray = output.array(); + int total = 0; + byte[] inArray, outArray; + if (a2) { // output has an accessible byte[] + outArray = output.array(); int outPos = output.position(); int outOfs = output.arrayOffset() + outPos; - int n; - if (isUpdate) { - n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs); - } else { - n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs); - } - input.position(inLimit); - output.position(outPos + n); - return n; - } else if (!a1 && a2) { - int outPos = output.position(); - byte[] outArray = output.array(); - int outOfs = output.arrayOffset() + outPos; - byte[] inArray = new byte[getTempArraySize(inLen)]; - int total = 0; - do { - int chunk = Math.min(inLen, inArray.length); - if (chunk > 0) { - input.get(inArray, 0, chunk); + + if (a1) { // input also has an accessible byte[] + inArray = input.array(); + int inOfs = input.arrayOffset() + inPos; + if (isUpdate) { + total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs); + } else { + total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs); } - int n; - if (isUpdate || (inLen != chunk)) { - n = engineUpdate(inArray, 0, chunk, outArray, outOfs); - } else { - n = engineDoFinal(inArray, 0, chunk, outArray, outOfs); - } - total += n; - outOfs += n; - inLen -= chunk; - } while (inLen > 0); - output.position(outPos + total); - return total; - } else { // output is not backed by an accessible byte[] - byte[] inArray; - int inOfs; - if (a1) { - inArray = input.array(); - inOfs = input.arrayOffset() + inPos; - } else { + input.position(inLimit); + } else { // input does not have accessible byte[] inArray = new byte[getTempArraySize(inLen)]; - inOfs = 0; + do { + int chunk = Math.min(inLen, inArray.length); + if (chunk > 0) { + input.get(inArray, 0, chunk); + } + int n; + if (isUpdate || (inLen > chunk)) { + n = engineUpdate(inArray, 0, chunk, outArray, outOfs); + } else { + n = engineDoFinal(inArray, 0, chunk, outArray, outOfs); + } + total += n; + outOfs += n; + inLen -= chunk; + } while (inLen > 0); } - byte[] outArray = new byte[getTempArraySize(outLenNeeded)]; - int outSize = outArray.length; - int total = 0; - boolean resized = false; - do { - int chunk = - Math.min(inLen, (outSize == 0? inArray.length : outSize)); - if (!a1 && !resized && chunk > 0) { - input.get(inArray, 0, chunk); - inOfs = 0; + output.position(outPos + total); + } else { // output does not have an accessible byte[] + if (a1) { // but input has an accessible byte[] + inArray = input.array(); + int inOfs = input.arrayOffset() + inPos; + if (isUpdate) { + outArray = engineUpdate(inArray, inOfs, inLen); + } else { + outArray = engineDoFinal(inArray, inOfs, inLen); + } + input.position(inLimit); + if (outArray != null && outArray.length != 0) { + output.put(outArray); + total = outArray.length; } - try { + } else { // input also does not have an accessible byte[] + inArray = new byte[getTempArraySize(inLen)]; + do { + int chunk = Math.min(inLen, inArray.length); + if (chunk > 0) { + input.get(inArray, 0, chunk); + } int n; - if (isUpdate || (inLen != chunk)) { - n = engineUpdate(inArray, inOfs, chunk, outArray, 0); + if (isUpdate || (inLen > chunk)) { + outArray = engineUpdate(inArray, 0, chunk); } else { - n = engineDoFinal(inArray, inOfs, chunk, outArray, 0); + outArray = engineDoFinal(inArray, 0, chunk); } - resized = false; - inOfs += chunk; + if (outArray != null && outArray.length != 0) { + output.put(outArray); + total += outArray.length; + } inLen -= chunk; - if (n > 0) { - output.put(outArray, 0, n); - total += n; - } - } catch (ShortBufferException e) { - if (resized) { - // we just resized the output buffer, but it still - // did not work. Bug in the provider, abort - throw (ProviderException)new ProviderException - ("Could not determine buffer size").initCause(e); - } - // output buffer is too small, realloc and try again - resized = true; - outSize = engineGetOutputSize(chunk); - outArray = new byte[outSize]; - } - } while (inLen > 0); - if (a1) { - input.position(inLimit); + } while (inLen > 0); } - return total; } + return total; } /** diff -r f21420b61fd2 -r 25d779d6bafc src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Tue Jun 12 08:02:39 2018 +0200 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Tue Jun 12 10:52:09 2018 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, 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 @@ -53,8 +53,8 @@ "sun.security.jgss.wrapper.NativeGSSFactory"; private static final String LIB_PROP = "sun.security.jgss.lib"; private static final String DEBUG_PROP = "sun.security.nativegss.debug"; - private static HashMap MECH_MAP; - static final Provider INSTANCE = new SunNativeProvider(); + private static final HashMap MECH_MAP; + static final Provider INSTANCE; static boolean DEBUG; static void debug(String message) { if (DEBUG) { @@ -117,6 +117,8 @@ return null; } }); + // initialize INSTANCE after MECH_MAP is constructed + INSTANCE = new SunNativeProvider(); } public SunNativeProvider() { diff -r f21420b61fd2 -r 25d779d6bafc test/hotspot/gtest/gc/shared/test_oopStorage.cpp --- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Tue Jun 12 08:02:39 2018 +0200 +++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Tue Jun 12 10:52:09 2018 +0200 @@ -1203,7 +1203,7 @@ class OopStorageAllocateListTest : public OopStorageBlockCollectionTest {}; TEST_F(OopStorageAllocateListTest, empty_list) { - AllocateList list(&OopBlock::get_allocate_entry); + AllocateList list; EXPECT_TRUE(is_list_empty(list)); EXPECT_EQ(NULL_BLOCK, list.head()); @@ -1212,7 +1212,7 @@ } TEST_F(OopStorageAllocateListTest, push_back) { - AllocateList list(&OopBlock::get_allocate_entry); + AllocateList list; for (size_t i = 0; i < nvalues; ++i) { list.push_back(*values[i]); @@ -1242,7 +1242,7 @@ } TEST_F(OopStorageAllocateListTest, push_front) { - AllocateList list(&OopBlock::get_allocate_entry); + AllocateList list; for (size_t i = 0; i < nvalues; ++i) { list.push_front(*values[i]); @@ -1273,7 +1273,7 @@ class OopStorageAllocateListTestWithList : public OopStorageAllocateListTest { public: - OopStorageAllocateListTestWithList() : list(&OopBlock::get_allocate_entry) { + OopStorageAllocateListTestWithList() : list() { for (size_t i = 0; i < nvalues; ++i) { list.push_back(*values[i]); } @@ -1345,7 +1345,7 @@ } TEST_F(OopStorageAllocateListTest, single) { - AllocateList list(&OopBlock::get_allocate_entry); + AllocateList list; list.push_back(*values[0]); EXPECT_EQ(NULL_BLOCK, list.next(*values[0])); diff -r f21420b61fd2 -r 25d779d6bafc test/hotspot/jtreg/ProblemList-graal.txt --- a/test/hotspot/jtreg/ProblemList-graal.txt Tue Jun 12 08:02:39 2018 +0200 +++ b/test/hotspot/jtreg/ProblemList-graal.txt Tue Jun 12 10:52:09 2018 +0200 @@ -143,3 +143,9 @@ vmTestbase/nsk/jvmti/AttachOnDemand/attach024/TestDescription.java 8195630 generic-all vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/TestDescription.java 8202342 generic-all + +vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t002/TestDescription.java 8204506 macosx-all + +compiler/stable/TestStableShort.java 8204346 generic-all +compiler/stable/TestStableUShort.java 8204346 generic-all +compiler/stable/TestStableUByte.java 8204346 generic-all diff -r f21420b61fd2 -r 25d779d6bafc test/jdk/java/lang/Package/PackageFromManifest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/lang/Package/PackageFromManifest.java Tue Jun 12 10:52:09 2018 +0200 @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8201528 + * @summary The test will create JAR file(s) with the manifest file + * that customized package versioning information (different info for + * same package if multiple jars). Then verify package versioning info + * @library /lib/testlibrary + * @library /test/lib + * @run main PackageFromManifest setup test + * @run main PackageFromManifest runJar test1.jar + * @run main PackageFromManifest runJar test1.jar test2.jar foo.Foo1 + * @run main PackageFromManifest runJar test1.jar test2.jar foo.Foo2 + * @run main/othervm PackageFromManifest runUrlLoader test1.jar + * @run main/othervm PackageFromManifest runUrlLoader test1.jar test2.jar foo.Foo1 + * @run main/othervm PackageFromManifest runUrlLoader test1.jar test2.jar foo.Foo2 + */ + +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.jar.Manifest; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * This test accept at least two input parameters, first one is run type like + * 'setup', 'runJar', 'runTest', 'runUrlLoader', the rest parameters are options + * to each run type. 'setup' run type should be placed at first since it will + * create necessary jars for the rest tests. 'runTest' will be called in test + * logic only, it should not be used in @run + * + * #1 test will do setup only to generate required jars before other tests run + * PackageFromManifest setup test + * + * #2 test will run against single jar file to verify package versioning + * PackageFromManifest runJar test1.jar + * + * #4 test will run against two jar files, load class foo.Foo1 first, then + * verify package versioning + * PackageFromManifest runJar test1.jar test2.jar foo.Foo1 + * + * #5 test will run against two jar files, load class foo.Foo2 first, then + * verify package versioning + * PackageFromManifest runJar test1.jar test2.jar foo.Foo2 + * + * #3 test will use URLCLassLoader to load single jar file, then verify + * package versioning + * PackageFromManifest runUrlLoader test1.jar + * + * #6 test will use URLCLassLoader to load two jars, load class foo.Foo1 first, + * then verify package versioning + * PackageFromManifest runUrlLoader test1.jar test2.jar foo.Foo1 + * + * #7 test will use URLCLassLoader to load two jars, load class foo.Foo2 first, + * then verify package versioning + * PackageFromManifest runUrlLoader test1.jar test2.jar foo.Foo2 + */ +public class PackageFromManifest { + + private static final String PACKAGE_NAME = "foo"; + private static final String TEST_JAR_FILE1 = "test1.jar"; + private static final String TEST_JAR_FILE2 = "test2.jar"; + private static final String TEST_SUFFIX1 = "1"; + private static final String TEST_SUFFIX2 = "2"; + private static final String TEST_CLASS_PREFIX = "Foo"; + private static final String TEST_CLASS_NAME1 = + TEST_CLASS_PREFIX + TEST_SUFFIX1; + private static final String TEST_CLASS_NAME2 = + TEST_CLASS_PREFIX + TEST_SUFFIX2; + private static final String MANIFEST_FILE = "test.mf"; + private static final String SPEC_TITLE = "testSpecTitle"; + private static final String SPEC_VENDOR = "testSpecVendor"; + private static final String IMPL_TITLE = "testImplTitle"; + private static final String IMPL_VENDOR = "testImplVendor"; + private static final Path WORKING_PATH = Paths.get("."); + + public static void main(String[] args) throws Exception { + if (args != null && args.length > 1) { + String runType = args[0]; + String[] options = Arrays.copyOfRange(args, 1, args.length); + switch (runType) { + case "setup": + setup(); + break; + case "runTest": + runTest(options); + break; + case "runJar": + runJar(options); + break; + case "runUrlLoader": + testUrlLoader(options); + break; + default: + throw new RuntimeException("Invalid run type : " + runType); + } + } else { + throw new RuntimeException("Invalid input arguments"); + } + } + + private static void createTestClass(String name) throws IOException { + List content = new ArrayList<>(); + content.add("package " + PACKAGE_NAME + ";"); + content.add("public class " + name + " {"); + content.add("}"); + + Path javaFile = WORKING_PATH.resolve(name + ".java"); + + Files.write(javaFile, content); + + CompilerUtils.compile(WORKING_PATH, WORKING_PATH); + + // clean up created java file + Files.delete(javaFile); + } + + private static void createManifest(String suffix) throws IOException { + List content = new ArrayList<>(); + content.add("Manifest-version: 1.1"); + content.add("Name: " + PACKAGE_NAME + "/"); + content.add("Specification-Title: " + SPEC_TITLE + suffix); + content.add("Specification-Version: " + suffix); + content.add("Specification-Vendor: " + SPEC_VENDOR + suffix); + content.add("Implementation-Title: " + IMPL_TITLE + suffix); + content.add("Implementation-Version: " + suffix); + content.add("Implementation-Vendor: " + IMPL_VENDOR + suffix); + + Files.write(WORKING_PATH.resolve(MANIFEST_FILE), content); + } + + private static void buildJar(String jarFileName, boolean isIncludeSelf) + throws IOException { + try (InputStream is = Files.newInputStream(Paths.get(MANIFEST_FILE))) { + if (isIncludeSelf) { + Path selfPath = WORKING_PATH + .resolve("PackageFromManifest.class"); + if (!Files.exists(selfPath)) { + Files.copy(Paths.get(System.getProperty("test.classes")) + .resolve("PackageFromManifest.class"), selfPath); + } + JarUtils.createJarFile(Paths.get(jarFileName), new Manifest(is), + WORKING_PATH, selfPath, + WORKING_PATH.resolve(PACKAGE_NAME)); + } else { + JarUtils.createJarFile(Paths.get(jarFileName), new Manifest(is), + WORKING_PATH, WORKING_PATH.resolve(PACKAGE_NAME)); + } + } + + // clean up build files + FileUtils.deleteFileTreeWithRetry(WORKING_PATH.resolve(PACKAGE_NAME)); + Files.delete(WORKING_PATH.resolve(MANIFEST_FILE)); + } + + private static void runJar(String[] options) throws Exception { + String[] cmds; + String classPath = Stream.of(options).takeWhile(s -> s.endsWith(".jar")) + .collect(Collectors.joining(File.pathSeparator)); + if (options.length == 1) { + cmds = new String[] { "-cp", classPath, "PackageFromManifest", + "runTest", "single" }; + } else { + cmds = new String[] { "-cp", classPath, "PackageFromManifest", + "runTest", options[options.length - 1] }; + } + + ProcessTools.executeTestJava(cmds).outputTo(System.out) + .errorTo(System.err).shouldHaveExitValue(0); + } + + private static void runTest(String[] options) + throws ClassNotFoundException { + String option = options[0]; + if (option.equalsIgnoreCase("single")) { + runTest(Class.forName(PACKAGE_NAME + "." + TEST_CLASS_NAME1) + .getPackage(), TEST_SUFFIX1); + } else { + // Load one specified class first + System.out.println("Load " + Class.forName(option) + " first"); + + String suffix = option.endsWith(TEST_SUFFIX1) ? + TEST_SUFFIX1 : + TEST_SUFFIX2; + + runTest(Class.forName(PACKAGE_NAME + "." + TEST_CLASS_NAME1) + .getPackage(), suffix); + runTest(Class.forName(PACKAGE_NAME + "." + TEST_CLASS_NAME2) + .getPackage(), suffix); + } + } + + private static void runTest(Package testPackage, String suffix) { + checkValue("Package Name", PACKAGE_NAME, testPackage.getName()); + checkValue("Spec Title", SPEC_TITLE + suffix, + testPackage.getSpecificationTitle()); + checkValue("Spec Vendor", SPEC_VENDOR + suffix, + testPackage.getSpecificationVendor()); + checkValue("Spec Version", suffix, + testPackage.getSpecificationVersion()); + checkValue("Impl Title", IMPL_TITLE + suffix, + testPackage.getImplementationTitle()); + checkValue("Impl Vendor", IMPL_VENDOR + suffix, + testPackage.getImplementationVendor()); + checkValue("Impl Version", suffix, + testPackage.getImplementationVersion()); + } + + private static void checkValue(String name, String expect, String actual) { + if (!expect.equals(actual)) { + throw new RuntimeException( + "Failed, unexpected value for " + name + ", expect: " + + expect + ", actual: " + actual); + } else { + System.out.println(name + " : " + actual); + } + } + + private static void setup() throws IOException { + if (!Files.exists(WORKING_PATH.resolve(TEST_JAR_FILE1))) { + createTestClass(TEST_CLASS_NAME1); + createManifest(TEST_SUFFIX1); + buildJar(TEST_JAR_FILE1, true); + } + + if (!Files.exists(WORKING_PATH.resolve(TEST_JAR_FILE2))) { + createTestClass(TEST_CLASS_NAME2); + createManifest(TEST_SUFFIX2); + buildJar(TEST_JAR_FILE2, false); + } + } + + private static void testUrlLoader(String[] options) + throws ClassNotFoundException { + URLClassLoader cl = new URLClassLoader( + Stream.of(options).takeWhile(s -> s.endsWith(".jar")).map(s -> { + try { + return WORKING_PATH.resolve(s).toUri().toURL(); + } catch (MalformedURLException e) { + return null; + } + }).toArray(URL[]::new)); + if (options.length == 1) { + runTest(Class + .forName(PACKAGE_NAME + "." + TEST_CLASS_NAME1, true, cl) + .getPackage(), TEST_SUFFIX1); + } else { + // Load one specified class first + System.out.println("Load " + Class + .forName(options[options.length - 1], true, cl) + " first"); + + String suffix = options[options.length - 1].endsWith(TEST_SUFFIX1) ? + TEST_SUFFIX1 : + TEST_SUFFIX2; + + runTest(Class + .forName(PACKAGE_NAME + "." + TEST_CLASS_NAME1, true, cl) + .getPackage(), suffix); + runTest(Class + .forName(PACKAGE_NAME + "." + TEST_CLASS_NAME2, true, cl) + .getPackage(), suffix); + } + } +} diff -r f21420b61fd2 -r 25d779d6bafc test/jdk/javax/crypto/CipherSpi/TestGCMWithByteBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/javax/crypto/CipherSpi/TestGCMWithByteBuffer.java Tue Jun 12 10:52:09 2018 +0200 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8178374 + * @summary Test GCM decryption with various types of input/output + * ByteBuffer objects + * @key randomness + */ + +import java.nio.ByteBuffer; +import java.security.*; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.AEADBadTagException; +import javax.crypto.spec.*; + +public class TestGCMWithByteBuffer { + + private static Random random = new SecureRandom(); + private static int dataSize = 4096; // see javax.crypto.CipherSpi + private static int multiples = 3; + + public static void main(String args[]) throws Exception { + Provider[] provs = Security.getProviders(); + for (Provider p : provs) { + try { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", p); + test(cipher); + } catch (NoSuchAlgorithmException nsae) { + // skip testing due to no support + continue; + } + } + } + + private static void test(Cipher cipher) throws Exception { + System.out.println("Testing " + cipher.getProvider()); + + boolean failedOnce = false; + Exception failedReason = null; + + int tagLen = 96; // in bits + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + byte[] dataChunk = new byte[dataSize]; + random.nextBytes(dataChunk); + + SecretKey key = new SecretKeySpec(keyBytes, "AES"); + // re-use key bytes as IV as the real test is buffer calculation + GCMParameterSpec s = new GCMParameterSpec(tagLen, keyBytes); + + /* + * Iterate through various sizes to make sure that the code works with + * internal temp buffer size 4096. + */ + for (int t = 1; t <= multiples; t++) { + int size = t * dataSize; + + System.out.println("\nTesting data size: " + size); + + try { + decrypt(cipher, key, s, dataChunk, t, + ByteBuffer.allocate(dataSize), + ByteBuffer.allocate(size), + ByteBuffer.allocateDirect(dataSize), + ByteBuffer.allocateDirect(size)); + } catch (Exception e) { + System.out.println("\tFailed with data size " + size); + failedOnce = true; + failedReason = e; + } + } + if (failedOnce) { + throw failedReason; + } + System.out.println("\n=> Passed..."); + } + + private enum TestVariant { + HEAP_HEAP, HEAP_DIRECT, DIRECT_HEAP, DIRECT_DIRECT + }; + + private static void decrypt(Cipher cipher, SecretKey key, + GCMParameterSpec s, byte[] dataChunk, int multiples, + ByteBuffer heapIn, ByteBuffer heapOut, ByteBuffer directIn, + ByteBuffer directOut) throws Exception { + + ByteBuffer inBB = null; + ByteBuffer outBB = null; + + // try various combinations of input/output + for (TestVariant tv : TestVariant.values()) { + System.out.println(" " + tv); + + switch (tv) { + case HEAP_HEAP: + inBB = heapIn; + outBB = heapOut; + break; + case HEAP_DIRECT: + inBB = heapIn; + outBB = directOut; + break; + case DIRECT_HEAP: + inBB = directIn; + outBB = heapOut; + break; + case DIRECT_DIRECT: + inBB = directIn; + outBB = directOut; + break; + } + + // prepare input and output buffers + inBB.clear(); + inBB.put(dataChunk); + + outBB.clear(); + + try { + // Always re-init the Cipher object so cipher is in + // a good state for future testing + cipher.init(Cipher.DECRYPT_MODE, key, s); + + for (int i = 0; i < multiples; i++) { + inBB.flip(); + cipher.update(inBB, outBB); + if (inBB.hasRemaining()) { + throw new Exception("buffer not empty"); + } + } + // finish decryption and process all data buffered + cipher.doFinal(inBB, outBB); + throw new RuntimeException("Error: doFinal completed without exception"); + } catch (AEADBadTagException ex) { + System.out.println("Expected AEADBadTagException thrown"); + continue; + } + } + } +}