8216426: Usage of array placement new may lead to memory corruption

Reviewed-by: rehn, kbarrett, rkennke, eosterlund
diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp
index f4e47ca..b5a9c9e 100644
--- a/src/hotspot/share/utilities/concurrentHashTable.hpp
+++ b/src/hotspot/share/utilities/concurrentHashTable.hpp
@@ -68,7 +68,7 @@
     void print_value_on(outputStream* st) const {};
   };
 
-  // Only constructed with placement new[] from an array allocated with MEMFLAGS
+  // Only constructed with placement new from an array allocated with MEMFLAGS
   // of InternalTable.
   class Bucket {
    private:
diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
index 720097a..72d16a3 100644
--- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
+++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
@@ -193,8 +193,12 @@
 {
   assert(_log2_size >= SIZE_SMALL_LOG2 && _log2_size <= SIZE_BIG_LOG2,
          "Bad size");
-  void* memory = NEW_C_HEAP_ARRAY(Bucket, _size, F);
-  _buckets = new (memory) Bucket[_size];
+  _buckets = NEW_C_HEAP_ARRAY(Bucket, _size, F);
+  // Use placement new for each element instead of new[] which could use more
+  // memory than allocated.
+  for (size_t i = 0; i < _size; ++i) {
+    new (_buckets + i) Bucket();
+  }
 }
 
 template <typename VALUE, typename CONFIG, MEMFLAGS F>