Skip to content

Commit

Permalink
8338064: Give better error for ConcurrentHashTable corruption
Browse files Browse the repository at this point in the history
Reviewed-by: dholmes, shade
  • Loading branch information
coleenp committed Aug 9, 2024
1 parent 2b5aec2 commit 069e0ea
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/hotspot/share/utilities/concurrentHashTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ConcurrentHashTable : public CHeapObj<F> {
// the InternalTable or user-defined memory.
class Node {
private:
DEBUG_ONLY(size_t _saved_hash);
Node * volatile _next;
VALUE _value;
public:
Expand All @@ -77,6 +78,10 @@ class ConcurrentHashTable : public CHeapObj<F> {
Node* next() const;
void set_next(Node* node) { _next = node; }
Node* const volatile * next_ptr() { return &_next; }
#ifdef ASSERT
size_t saved_hash() const { return _saved_hash; }
void set_saved_hash(size_t hash) { _saved_hash = hash; }
#endif

VALUE* value() { return &_value; }

Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/share/utilities/concurrentHashTable.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,9 @@ inline bool ConcurrentHashTable<CONFIG, F>::
// Keep in odd list
odd = aux->next_ptr();
} else {
fatal("aux_index does not match even or odd indices");
const char* msg = "Cannot resize table: Node hash code has changed possibly due to corruption of the contents.";
DEBUG_ONLY(fatal("%s Node hash code changed from " SIZE_FORMAT " to " SIZE_FORMAT, msg, aux->saved_hash(), aux_hash);)
NOT_DEBUG(fatal("%s", msg);)
}
}
aux = aux_next;
Expand Down Expand Up @@ -892,6 +894,7 @@ inline bool ConcurrentHashTable<CONFIG, F>::
size_t i = 0;
uintx hash = lookup_f.get_hash();
Node* new_node = Node::create_node(_context, value, nullptr);
DEBUG_ONLY(new_node->set_saved_hash(hash);)

while (true) {
{
Expand Down Expand Up @@ -1117,6 +1120,7 @@ inline bool ConcurrentHashTable<CONFIG, F>::
Bucket* bucket = get_bucket_in(table, hash);
assert(!bucket->have_redirect() && !bucket->is_locked(), "bad");
Node* new_node = Node::create_node(_context, value, bucket->first());
DEBUG_ONLY(new_node->set_saved_hash(hash);)
if (!bucket->cas_first(new_node, bucket->first())) {
assert(false, "bad");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024, 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 8333356
* @summary Verify new error message for corrupting string table contents.
* @requires vm.flagless
* @modules java.base/java.lang:open
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @run driver StringTableCorruptionTest test
*/

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;

public class StringTableCorruptionTest {
public static void main(String[] args) throws Exception {
if (args.length > 0) {
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--add-opens", "java.base/java.lang=ALL-UNNAMED",
"-XX:-CreateCoredumpOnCrash", "StringTableCorruptionTest");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Node hash code has changed possibly due to corruption of the contents.");
output.shouldNotHaveExitValue(0);
return;
}

Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
f.set("s1".intern(), f.get("s2"));
for (int i = 0; i < 4_000_000; i++) {
("s_" + i).intern();
}
}
}

0 comments on commit 069e0ea

Please sign in to comment.