Merge epsilon-gc-branch
authorshade
Tue, 12 Jun 2018 10:52:09 +0200
branchepsilon-gc-branch
changeset 56742 25d779d6bafc
parent 56741 f21420b61fd2 (current diff)
parent 50513 7f166e010af4 (diff)
child 56743 774caae3a3ce
Merge
--- 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
--- 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",
--- 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<OopStorage* volatile&>(_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),
--- 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();
--- 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<Block*>(_get_entry(block)._prev);
+  return const_cast<Block*>(block.allocate_entry()._prev);
 }
 
 inline OopStorage::Block* OopStorage::AllocateList::next(Block& block) {
-  return const_cast<Block*>(_get_entry(block)._next);
+  return const_cast<Block*>(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<typename Closure>
@@ -296,7 +296,11 @@
   return SkipNullFn<F>(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);
--- 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;
     }
 
     /**
--- 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<String, String> MECH_MAP;
-    static final Provider INSTANCE = new SunNativeProvider();
+    private static final HashMap<String, String> 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() {
--- 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]));
--- 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
--- /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<String> 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<String> 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);
+        }
+    }
+}
--- /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;
+            }
+        }
+    }
+}