540 lines
23 KiB
Diff
540 lines
23 KiB
Diff
|
|
From dfe3a75cf5c911a68ccd187c57f7d0d1f30f65f9 Mon Sep 17 00:00:00 2001
|
||
|
|
Date: Wed, 4 Jan 2023 20:41:20 +0800
|
||
|
|
Subject: 8253495: CDS generates non-deterministic output
|
||
|
|
|
||
|
|
---
|
||
|
|
make/GenerateLinkOptData.gmk | 7 +-
|
||
|
|
.../build/tools/classlist/SortClasslist.java | 79 +++++++++++++++++++
|
||
|
|
make/scripts/compare.sh | 8 +-
|
||
|
|
src/hotspot/share/cds/archiveBuilder.cpp | 5 +-
|
||
|
|
src/hotspot/share/cds/archiveUtils.hpp | 5 +-
|
||
|
|
src/hotspot/share/cds/heapShared.cpp | 8 +-
|
||
|
|
src/hotspot/share/gc/shared/collectedHeap.cpp | 18 ++++-
|
||
|
|
src/hotspot/share/gc/shared/collectedHeap.hpp | 1 +
|
||
|
|
src/hotspot/share/prims/jvm.cpp | 20 +++++
|
||
|
|
src/hotspot/share/runtime/os.cpp | 19 ++++-
|
||
|
|
test/hotspot/jtreg/ProblemList.txt | 1 -
|
||
|
|
.../jtreg/runtime/cds/DeterministicDump.java | 10 ++-
|
||
|
|
.../cds/appcds/javaldr/LockDuringDump.java | 4 +-
|
||
|
|
.../appcds/javaldr/LockDuringDumpAgent.java | 16 +++-
|
||
|
|
test/lib/jdk/test/lib/cds/CDSOptions.java | 33 ++++++--
|
||
|
|
15 files changed, 202 insertions(+), 32 deletions(-)
|
||
|
|
create mode 100644 make/jdk/src/classes/build/tools/classlist/SortClasslist.java
|
||
|
|
|
||
|
|
diff --git a/make/GenerateLinkOptData.gmk b/make/GenerateLinkOptData.gmk
|
||
|
|
index 0de28d643..5dd766c8c 100644
|
||
|
|
--- a/make/GenerateLinkOptData.gmk
|
||
|
|
+++ b/make/GenerateLinkOptData.gmk
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
#
|
||
|
|
-# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+# Copyright (c) 2016, 2021, 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
|
||
|
|
@@ -88,7 +88,10 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
|
||
|
|
$(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \
|
||
|
|
exit $$exitcode \
|
||
|
|
)
|
||
|
|
- $(GREP) -v HelloClasslist $@.raw.2 > $@
|
||
|
|
+ $(GREP) -v HelloClasslist $@.raw.2 > $@.raw.3
|
||
|
|
+ $(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java \
|
||
|
|
+ -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||
|
|
+ build.tools.classlist.SortClasslist $@.raw.3 > $@
|
||
|
|
|
||
|
|
# The jli trace is created by the same recipe as classlist. By declaring these
|
||
|
|
# dependencies, make will correctly rebuild both jli trace and classlist
|
||
|
|
diff --git a/make/jdk/src/classes/build/tools/classlist/SortClasslist.java b/make/jdk/src/classes/build/tools/classlist/SortClasslist.java
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..cf9e55a7b
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/make/jdk/src/classes/build/tools/classlist/SortClasslist.java
|
||
|
|
@@ -0,0 +1,79 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2022, Huawei Technologies Co., Ltd. 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.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+/**
|
||
|
|
+ * This application is meant to be run to create a classlist file representing
|
||
|
|
+ * common use.
|
||
|
|
+ *
|
||
|
|
+ * The classlist is produced by adding -XX:DumpLoadedClassList=classlist
|
||
|
|
+ */
|
||
|
|
+package build.tools.classlist;
|
||
|
|
+
|
||
|
|
+import java.io.FileInputStream;
|
||
|
|
+import java.io.FileNotFoundException;
|
||
|
|
+import java.util.ArrayList;
|
||
|
|
+import java.util.Collections;
|
||
|
|
+import java.util.regex.Pattern;
|
||
|
|
+import java.util.regex.Matcher;
|
||
|
|
+import java.util.Scanner;
|
||
|
|
+
|
||
|
|
+/**
|
||
|
|
+ * The classlist generated by build.tools.classlist.HelloClasslist
|
||
|
|
+ * may have non-deterministic contents, affected by Java thread execution order.
|
||
|
|
+ * SortClasslist sorts the file to make the JDK image's contents more deterministic.
|
||
|
|
+ */
|
||
|
|
+public class SortClasslist {
|
||
|
|
+ public static void main(String args[]) throws FileNotFoundException {
|
||
|
|
+ ArrayList<String> classes = new ArrayList<>();
|
||
|
|
+ ArrayList<String> lambdas = new ArrayList<>();
|
||
|
|
+
|
||
|
|
+ FileInputStream fis = new FileInputStream(args[0]);
|
||
|
|
+ Scanner scanner = new Scanner(fis);
|
||
|
|
+ while (scanner.hasNextLine()) {
|
||
|
|
+ String line = scanner.nextLine();
|
||
|
|
+ if (line.startsWith("#")) {
|
||
|
|
+ // Comments -- print them first without sorting. These appear only at the top
|
||
|
|
+ // of the file.
|
||
|
|
+ System.out.println(line);
|
||
|
|
+ } else if (line.startsWith("@")) {
|
||
|
|
+ // @lambda-form-invoker, @lambda-proxy, etc.
|
||
|
|
+ lambdas.add(line);
|
||
|
|
+ } else {
|
||
|
|
+ classes.add(line);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ Collections.sort(classes);
|
||
|
|
+ Collections.sort(lambdas);
|
||
|
|
+
|
||
|
|
+ for (String s : classes) {
|
||
|
|
+ System.out.println(s);
|
||
|
|
+ }
|
||
|
|
+ for (String s : lambdas) {
|
||
|
|
+ System.out.println(s);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh
|
||
|
|
index 42886573f..3075f9a82 100644
|
||
|
|
--- a/make/scripts/compare.sh
|
||
|
|
+++ b/make/scripts/compare.sh
|
||
|
|
@@ -1,6 +1,6 @@
|
||
|
|
#!/bin/bash
|
||
|
|
#
|
||
|
|
-# Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+# Copyright (c) 2012, 2022, 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
|
||
|
|
@@ -324,7 +324,7 @@ compare_general_files() {
|
||
|
|
! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
|
||
|
|
! -name "*.lib" ! -name "*.jmod" ! -name "*.exe" \
|
||
|
|
! -name "*.obj" ! -name "*.o" ! -name "jspawnhelper" ! -name "*.a" \
|
||
|
|
- ! -name "*.tar.gz" ! -name "*.jsa" ! -name "gtestLauncher" \
|
||
|
|
+ ! -name "*.tar.gz" ! -name "classes_nocoops.jsa" ! -name "gtestLauncher" \
|
||
|
|
! -name "*.map" \
|
||
|
|
| $GREP -v "./bin/" | $SORT | $FILTER)
|
||
|
|
|
||
|
|
@@ -356,8 +356,8 @@ compare_general_files() {
|
||
|
|
"
|
||
|
|
$CAT $OTHER_DIR/$f | eval "$SVG_FILTER" > $OTHER_FILE
|
||
|
|
$CAT $THIS_DIR/$f | eval "$SVG_FILTER" > $THIS_FILE
|
||
|
|
- elif [[ "$f" = *"/lib/classlist" ]] || [ "$SUFFIX" = "jar_contents" ]; then
|
||
|
|
- # The classlist files may have some lines in random order
|
||
|
|
+ elif [ "$SUFFIX" = "jar_contents" ]; then
|
||
|
|
+ # The jar_contents files may have some lines in random order
|
||
|
|
OTHER_FILE=$WORK_DIR/$f.other
|
||
|
|
THIS_FILE=$WORK_DIR/$f.this
|
||
|
|
$MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)
|
||
|
|
diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
|
||
|
|
index 699926fcf..8e12cdabb 100644
|
||
|
|
--- a/src/hotspot/share/cds/archiveBuilder.cpp
|
||
|
|
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2020, 2022, 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
|
||
|
|
@@ -540,7 +540,8 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref
|
||
|
|
if (MetaspaceShared::is_in_shared_metaspace(obj)) {
|
||
|
|
// Don't dump existing shared metadata again.
|
||
|
|
return point_to_it;
|
||
|
|
- } else if (ref->msotype() == MetaspaceObj::MethodDataType) {
|
||
|
|
+ } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
|
||
|
|
+ ref->msotype() == MetaspaceObj::MethodCountersType) {
|
||
|
|
return set_to_null;
|
||
|
|
} else {
|
||
|
|
if (ref->msotype() == MetaspaceObj::ClassType) {
|
||
|
|
diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp
|
||
|
|
index cdb3d99ab..6d8e0b43a 100644
|
||
|
|
--- a/src/hotspot/share/cds/archiveUtils.hpp
|
||
|
|
+++ b/src/hotspot/share/cds/archiveUtils.hpp
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2019, 2022, 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,6 +30,7 @@
|
||
|
|
#include "memory/virtualspace.hpp"
|
||
|
|
#include "utilities/bitMap.hpp"
|
||
|
|
#include "utilities/exceptions.hpp"
|
||
|
|
+#include "utilities/macros.hpp"
|
||
|
|
|
||
|
|
class BootstrapInfo;
|
||
|
|
class ReservedSpace;
|
||
|
|
@@ -142,7 +143,7 @@ public:
|
||
|
|
char* expand_top_to(char* newtop);
|
||
|
|
char* allocate(size_t num_bytes);
|
||
|
|
|
||
|
|
- void append_intptr_t(intptr_t n, bool need_to_mark = false);
|
||
|
|
+ void append_intptr_t(intptr_t n, bool need_to_mark = false) NOT_CDS_RETURN;
|
||
|
|
|
||
|
|
char* base() const { return _base; }
|
||
|
|
char* top() const { return _top; }
|
||
|
|
diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp
|
||
|
|
index 3e50dd750..fd3d199f8 100644
|
||
|
|
--- a/src/hotspot/share/cds/heapShared.cpp
|
||
|
|
+++ b/src/hotspot/share/cds/heapShared.cpp
|
||
|
|
@@ -454,7 +454,7 @@ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_
|
||
|
|
bool created;
|
||
|
|
Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k);
|
||
|
|
KlassSubGraphInfo* info =
|
||
|
|
- _dump_time_subgraph_info_table->put_if_absent(relocated_k, KlassSubGraphInfo(relocated_k, is_full_module_graph),
|
||
|
|
+ _dump_time_subgraph_info_table->put_if_absent(k, KlassSubGraphInfo(relocated_k, is_full_module_graph),
|
||
|
|
&created);
|
||
|
|
assert(created, "must not initialize twice");
|
||
|
|
return info;
|
||
|
|
@@ -462,8 +462,7 @@ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_
|
||
|
|
|
||
|
|
KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
|
||
|
|
assert(DumpSharedSpaces, "dump time only");
|
||
|
|
- Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k);
|
||
|
|
- KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k);
|
||
|
|
+ KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(k);
|
||
|
|
assert(info != NULL, "must have been initialized");
|
||
|
|
return info;
|
||
|
|
}
|
||
|
|
@@ -624,7 +623,8 @@ struct CopyKlassSubGraphInfoToArchive : StackObj {
|
||
|
|
(ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord));
|
||
|
|
record->init(&info);
|
||
|
|
|
||
|
|
- unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)klass);
|
||
|
|
+ Klass* relocated_k = ArchiveBuilder::get_relocated_klass(klass);
|
||
|
|
+ unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)relocated_k);
|
||
|
|
u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record);
|
||
|
|
_writer->add(hash, delta);
|
||
|
|
}
|
||
|
|
diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp
|
||
|
|
index 96b3eb946..5a2cb0e51 100644
|
||
|
|
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp
|
||
|
|
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2001, 2022, 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
|
||
|
|
@@ -405,6 +405,11 @@ size_t CollectedHeap::filler_array_min_size() {
|
||
|
|
return align_object_size(filler_array_hdr_size()); // align to MinObjAlignment
|
||
|
|
}
|
||
|
|
|
||
|
|
+void CollectedHeap::zap_filler_array_with(HeapWord* start, size_t words, juint value) {
|
||
|
|
+ Copy::fill_to_words(start + filler_array_hdr_size(),
|
||
|
|
+ words - filler_array_hdr_size(), value);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
#ifdef ASSERT
|
||
|
|
void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
|
||
|
|
{
|
||
|
|
@@ -415,8 +420,7 @@ void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
|
||
|
|
void CollectedHeap::zap_filler_array(HeapWord* start, size_t words, bool zap)
|
||
|
|
{
|
||
|
|
if (ZapFillerObjects && zap) {
|
||
|
|
- Copy::fill_to_words(start + filler_array_hdr_size(),
|
||
|
|
- words - filler_array_hdr_size(), 0XDEAFBABE);
|
||
|
|
+ zap_filler_array_with(start, words, 0XDEAFBABE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif // ASSERT
|
||
|
|
@@ -433,7 +437,13 @@ CollectedHeap::fill_with_array(HeapWord* start, size_t words, bool zap)
|
||
|
|
|
||
|
|
ObjArrayAllocator allocator(Universe::intArrayKlassObj(), words, (int)len, /* do_zero */ false);
|
||
|
|
allocator.initialize(start);
|
||
|
|
- DEBUG_ONLY(zap_filler_array(start, words, zap);)
|
||
|
|
+ if (DumpSharedSpaces) {
|
||
|
|
+ // This array is written into the CDS archive. Make sure it
|
||
|
|
+ // has deterministic contents.
|
||
|
|
+ zap_filler_array_with(start, words, 0);
|
||
|
|
+ } else {
|
||
|
|
+ DEBUG_ONLY(zap_filler_array(start, words, zap);)
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp
|
||
|
|
index 10baf8749..8d1087ed3 100644
|
||
|
|
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp
|
||
|
|
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp
|
||
|
|
@@ -143,6 +143,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||
|
|
static inline size_t filler_array_hdr_size();
|
||
|
|
static inline size_t filler_array_min_size();
|
||
|
|
|
||
|
|
+ static inline void zap_filler_array_with(HeapWord* start, size_t words, juint value);
|
||
|
|
DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);)
|
||
|
|
DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words, bool zap = true);)
|
||
|
|
|
||
|
|
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
|
||
|
|
index 8baba8c38..9057cc072 100644
|
||
|
|
--- a/src/hotspot/share/prims/jvm.cpp
|
||
|
|
+++ b/src/hotspot/share/prims/jvm.cpp
|
||
|
|
@@ -2852,6 +2852,26 @@ static void thread_entry(JavaThread* thread, TRAPS) {
|
||
|
|
|
||
|
|
|
||
|
|
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
|
||
|
|
+#if INCLUDE_CDS
|
||
|
|
+ if (DumpSharedSpaces) {
|
||
|
|
+ // During java -Xshare:dump, if we allow multiple Java threads to
|
||
|
|
+ // execute in parallel, symbols and classes may be loaded in
|
||
|
|
+ // random orders which will make the resulting CDS archive
|
||
|
|
+ // non-deterministic.
|
||
|
|
+ //
|
||
|
|
+ // Lucikly, during java -Xshare:dump, it's important to run only
|
||
|
|
+ // the code in the main Java thread (which is NOT started here) that
|
||
|
|
+ // creates the module graph, etc. It's safe to not start the other
|
||
|
|
+ // threads which are launched by class static initializers
|
||
|
|
+ // (ReferenceHandler, FinalizerThread and CleanerImpl).
|
||
|
|
+ if (log_is_enabled(Info, cds)) {
|
||
|
|
+ ResourceMark rm;
|
||
|
|
+ oop t = JNIHandles::resolve_non_null(jthread);
|
||
|
|
+ log_info(cds)("JVM_StartThread() ignored: %s", t->klass()->external_name());
|
||
|
|
+ }
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+#endif
|
||
|
|
JavaThread *native_thread = NULL;
|
||
|
|
|
||
|
|
// We cannot hold the Threads_lock when we throw an exception,
|
||
|
|
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
|
||
|
|
index bb6cea80e..bd5ab658c 100644
|
||
|
|
--- a/src/hotspot/share/runtime/os.cpp
|
||
|
|
+++ b/src/hotspot/share/runtime/os.cpp
|
||
|
|
@@ -674,6 +674,15 @@ static bool has_reached_max_malloc_test_peak(size_t alloc_size) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
+#ifdef ASSERT
|
||
|
|
+static void break_if_ptr_caught(void* ptr) {
|
||
|
|
+ if (p2i(ptr) == (intptr_t)MallocCatchPtr) {
|
||
|
|
+ log_warning(malloc, free)("ptr caught: " PTR_FORMAT, p2i(ptr));
|
||
|
|
+ breakpoint();
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+#endif // ASSERT
|
||
|
|
+
|
||
|
|
void* os::malloc(size_t size, MEMFLAGS flags) {
|
||
|
|
return os::malloc(size, flags, CALLER_PC);
|
||
|
|
}
|
||
|
|
@@ -746,7 +755,15 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// we do not track guard memory
|
||
|
|
- return MemTracker::record_malloc((address)ptr, size, memflags, stack, level);
|
||
|
|
+ void* const inner_ptr = MemTracker::record_malloc((address)ptr, size, memflags, stack, level);
|
||
|
|
+ if (DumpSharedSpaces) {
|
||
|
|
+ // Need to deterministically fill all the alignment gaps in C++ structures.
|
||
|
|
+ ::memset(inner_ptr, 0, size);
|
||
|
|
+ } else {
|
||
|
|
+ DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);)
|
||
|
|
+ }
|
||
|
|
+ DEBUG_ONLY(break_if_ptr_caught(inner_ptr);)
|
||
|
|
+ return inner_ptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) {
|
||
|
|
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
|
||
|
|
index 5d43b504f..ebc29f736 100644
|
||
|
|
--- a/test/hotspot/jtreg/ProblemList.txt
|
||
|
|
+++ b/test/hotspot/jtreg/ProblemList.txt
|
||
|
|
@@ -86,7 +86,6 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64
|
||
|
|
# :hotspot_runtime
|
||
|
|
|
||
|
|
runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP_JFR.java 8253437 windows-x64
|
||
|
|
-runtime/cds/DeterministicDump.java 8253495 generic-all
|
||
|
|
runtime/InvocationTests/invokevirtualTests.java#current-int 8271125 generic-all
|
||
|
|
runtime/InvocationTests/invokevirtualTests.java#current-comp 8271125 generic-all
|
||
|
|
runtime/InvocationTests/invokevirtualTests.java#old-int 8271125 generic-all
|
||
|
|
diff --git a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java b/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
|
||
|
|
index 9cdba1fa9..6e8ccffce 100644
|
||
|
|
--- a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
|
||
|
|
+++ b/test/hotspot/jtreg/runtime/cds/DeterministicDump.java
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2020, 2022, 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
|
||
|
|
@@ -54,6 +54,11 @@ public class DeterministicDump {
|
||
|
|
baseArgs.add("-Xmx128M");
|
||
|
|
|
||
|
|
if (Platform.is64bit()) {
|
||
|
|
+ if (!compressed) {
|
||
|
|
+ System.out.println("CDS archives with uncompressed oops are still non-deterministic");
|
||
|
|
+ System.out.println("See https://bugs.openjdk.java.net/browse/JDK-8282828");
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
// These options are available only on 64-bit.
|
||
|
|
String sign = (compressed) ? "+" : "-";
|
||
|
|
baseArgs.add("-XX:" + sign + "UseCompressedOops");
|
||
|
|
@@ -78,9 +83,12 @@ public class DeterministicDump {
|
||
|
|
static String dump(ArrayList<String> args, String... more) throws Exception {
|
||
|
|
String logName = "SharedArchiveFile" + (id++);
|
||
|
|
String archiveName = logName + ".jsa";
|
||
|
|
+ String mapName = logName + ".map";
|
||
|
|
CDSOptions opts = (new CDSOptions())
|
||
|
|
.addPrefix("-Xlog:cds=debug")
|
||
|
|
+ .addPrefix("-Xlog:cds+map=trace:file=" + mapName + ":none:filesize=0")
|
||
|
|
.setArchiveName(archiveName)
|
||
|
|
+ .addSuffix(args)
|
||
|
|
.addSuffix(more);
|
||
|
|
CDSTestUtils.createArchiveAndCheck(opts);
|
||
|
|
|
||
|
|
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
|
||
|
|
index d60e0d11a..5dc8dbc08 100644
|
||
|
|
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
|
||
|
|
+++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2020, 2022, 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
|
||
|
|
@@ -70,7 +70,7 @@ public class LockDuringDump {
|
||
|
|
TestCommon.testDump(appJar, TestCommon.list(LockDuringDumpApp.class.getName()),
|
||
|
|
"-XX:+UnlockDiagnosticVMOptions",
|
||
|
|
agentArg, agentArg2, biasedLock);
|
||
|
|
- if (i != 0) {
|
||
|
|
+ if (i != 0 && !out.getStdout().contains("LockDuringDumpAgent timeout")) {
|
||
|
|
out.shouldContain("Let's hold the lock on the literal string");
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java
|
||
|
|
index 5e053d83e..57db61e93 100644
|
||
|
|
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java
|
||
|
|
+++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2020, 2022, 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
|
||
|
|
@@ -51,9 +51,21 @@ public class LockDuringDumpAgent implements Runnable {
|
||
|
|
|
||
|
|
static void waitForThreadStart() {
|
||
|
|
try {
|
||
|
|
+ long started = System.currentTimeMillis();
|
||
|
|
+ long timeout = 10000;
|
||
|
|
+ synchronized (LITERAL) {
|
||
|
|
+ Thread.sleep(1);
|
||
|
|
+ }
|
||
|
|
synchronized (lock) {
|
||
|
|
while (!threadStarted) {
|
||
|
|
- lock.wait();
|
||
|
|
+ lock.wait(timeout);
|
||
|
|
+ long elapsed = System.currentTimeMillis() - started;
|
||
|
|
+ if (elapsed >= timeout) {
|
||
|
|
+ System.out.println("This JVM may decide to not launch any Java threads during -Xshare:dump.");
|
||
|
|
+ System.out.println("This is OK because no string objects could be in a locked state during heap dump.");
|
||
|
|
+ System.out.println("LockDuringDumpAgent timeout after " + elapsed + " ms");
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
System.out.println("Thread has started");
|
||
|
|
}
|
||
|
|
diff --git a/test/lib/jdk/test/lib/cds/CDSOptions.java b/test/lib/jdk/test/lib/cds/CDSOptions.java
|
||
|
|
index 2fa949dc4..1138b7757 100644
|
||
|
|
--- a/test/lib/jdk/test/lib/cds/CDSOptions.java
|
||
|
|
+++ b/test/lib/jdk/test/lib/cds/CDSOptions.java
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
/*
|
||
|
|
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||
|
|
+ * Copyright (c) 2017, 2022, 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
|
||
|
|
@@ -46,24 +46,43 @@ public class CDSOptions {
|
||
|
|
|
||
|
|
|
||
|
|
public CDSOptions addPrefix(String... prefix) {
|
||
|
|
- for (String s : prefix) this.prefix.add(s);
|
||
|
|
+ for (String s : prefix) {
|
||
|
|
+ this.prefix.add(s);
|
||
|
|
+ }
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
public CDSOptions addPrefix(String prefix[], String... extra) {
|
||
|
|
- for (String s : prefix) this.prefix.add(s);
|
||
|
|
- for (String s : extra) this.prefix.add(s);
|
||
|
|
+ for (String s : prefix) {
|
||
|
|
+ this.prefix.add(s);
|
||
|
|
+ }
|
||
|
|
+ for (String s : extra) {
|
||
|
|
+ this.prefix.add(s);
|
||
|
|
+ }
|
||
|
|
+ return this;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ public CDSOptions addSuffix(ArrayList<String> suffix) {
|
||
|
|
+ for (String s : suffix) {
|
||
|
|
+ this.suffix.add(s);
|
||
|
|
+ }
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
public CDSOptions addSuffix(String... suffix) {
|
||
|
|
- for (String s : suffix) this.suffix.add(s);
|
||
|
|
+ for (String s : suffix) {
|
||
|
|
+ this.suffix.add(s);
|
||
|
|
+ }
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
public CDSOptions addSuffix(String suffix[], String... extra) {
|
||
|
|
- for (String s : suffix) this.suffix.add(s);
|
||
|
|
- for (String s : extra) this.suffix.add(s);
|
||
|
|
+ for (String s : suffix) {
|
||
|
|
+ this.suffix.add(s);
|
||
|
|
+ }
|
||
|
|
+ for (String s : extra) {
|
||
|
|
+ this.suffix.add(s);
|
||
|
|
+ }
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
--
|
||
|
|
2.37.0
|
||
|
|
|