8249276: CDS archived objects must have "neutral" markwords

Reviewed-by: coleenp, dholmes
This commit is contained in:
Ioi Lam 2020-08-11 22:05:56 -07:00
parent a5ae1e306e
commit 178eea6065
5 changed files with 216 additions and 7 deletions

View File

@ -136,17 +136,23 @@ oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) {
return NULL;
}
// Pre-compute object identity hash at CDS dump time.
obj->identity_hash();
oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len);
if (archived_oop != NULL) {
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(obj), cast_from_oop<HeapWord*>(archived_oop), len);
MetaspaceShared::relocate_klass_ptr(archived_oop);
// Clear age -- it might have been set if a GC happened during -Xshare:dump
markWord mark = archived_oop->mark_raw();
mark = mark.set_age(0);
archived_oop->set_mark_raw(mark);
// Reinitialize markword to remove age/marking/locking/etc.
//
// We need to retain the identity_hash, because it may have been used by some hashtables
// in the shared heap. This also has the side effect of pre-initializing the
// identity_hash for all shared objects, so they are less likely to be written
// into during run time, increasing the potential of memory sharing.
int hash_original = obj->identity_hash();
archived_oop->set_mark_raw(markWord::prototype().copy_set_hash(hash_original));
assert(archived_oop->mark().is_unlocked(), "sanity");
DEBUG_ONLY(int hash_archived = archived_oop->identity_hash());
assert(hash_original == hash_archived, "Different hash codes: original %x, archived %x", hash_original, hash_archived);
ArchivedObjectCache* cache = archived_object_cache();
cache->put(obj, archived_oop);
log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,

View File

@ -326,6 +326,7 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/javaldr/ArrayTest.java \
-runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java \
-runtime/cds/appcds/javaldr/HumongousDuringDump.java \
-runtime/cds/appcds/javaldr/LockDuringDump.java \
-runtime/cds/appcds/sharedStrings \
-runtime/cds/appcds/ArchiveRelocationTest.java \
-runtime/cds/appcds/DumpClassList.java \

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2020, 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 8249276
* @summary When dumping the CDS archive, try to lock some objects. These objects should be archived
* without the locking bits in the markWord.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @requires vm.cds
* @requires vm.flavor != "minimal"
* @modules java.instrument
* @run driver LockDuringDump
*/
import jdk.test.lib.process.OutputAnalyzer;
public class LockDuringDump {
public static String appClasses[] = {
LockDuringDumpApp.class.getName(),
};
public static String agentClasses[] = {
LockDuringDumpAgent.class.getName(),
};
private static final String MANIFEST =
"Manifest-Version: 1.0\nPremain-Class: LockDuringDumpAgent\n";
public static void main(String[] args) throws Throwable {
String agentJar =
ClassFileInstaller.writeJar("LockDuringDumpAgent.jar",
ClassFileInstaller.Manifest.fromString(MANIFEST),
agentClasses);
String appJar =
ClassFileInstaller.writeJar("LockDuringDumpApp.jar", appClasses);
for (int i = 0; i < 3; i++) {
// i = 0 -- dump without agent
// i = 1 -- dump with agent = disable BiasedLocking
// i = 2 -- dump with agent = enable BiasedLocking
String agentArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
String agentArg2 = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
String biasedLock = (i != 2) ? "-showversion" : "-XX:+UseBiasedLocking";
OutputAnalyzer out =
TestCommon.testDump(appJar, TestCommon.list(LockDuringDumpApp.class.getName()),
"-XX:+UnlockDiagnosticVMOptions",
agentArg, agentArg2, biasedLock);
if (i != 0) {
out.shouldContain("Let's hold the lock on the literal string");
}
TestCommon.run(
"-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions", agentArg2, biasedLock,
LockDuringDumpApp.class.getName())
.assertNormalExit("I am able to lock the literal string");
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2020, 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.
*
*/
import java.lang.instrument.Instrumentation;
public class LockDuringDumpAgent implements Runnable {
static boolean threadStarted = false;
static Object lock = new Object();
// The following literal string will be stored into the VM's interned string table when this
// class (or the LockDuringDumpApp class) is loaded during -Xshare:dump. As a result it will be
// stored in the CDS archived heap (all strings in the dump-time interned string table are archived).
//
// We try to make sure this string is locked while the archived heap is dumped. CDS should
// clear the lock states in this string's object header. See JDK-8249276.
//
// At run time, when LockDuringDumpApp loads this literal string (from the shared string table)
// it should be able to lock it without problems.
static String LITERAL = "@@LockDuringDump@@LITERAL"; // must be the same as in LockDuringDumpAgent
public static void premain(String agentArg, Instrumentation instrumentation) {
System.out.println("inside LockDuringDumpAgent: " + LockDuringDumpAgent.class.getClassLoader());
Thread t = new Thread(new LockDuringDumpAgent());
t.setDaemon(true);
t.start();
waitForThreadStart();
}
static void waitForThreadStart() {
try {
synchronized (lock) {
while (!threadStarted) {
lock.wait();
}
System.out.println("Thread has started");
}
} catch (Throwable t) {
System.err.println("Unexpected: " + t);
throw new RuntimeException(t);
}
}
public void run() {
try {
synchronized (LITERAL) {
System.out.println("Let's hold the lock on the literal string \"" + LITERAL + "\" + forever .....");
synchronized (lock) {
threadStarted = true;
lock.notifyAll();
}
//if (false) {
while (true) {
Thread.sleep(1);
}
//}
}
} catch (Throwable t) {
System.err.println("Unexpected: " + t);
throw new RuntimeException(t);
}
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020, 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.
*
*/
public class LockDuringDumpApp {
static String LITERAL = "@@LockDuringDump@@LITERAL"; // must be the same as in LockDuringDumpAgent
public static void main(String args[]) {
synchronized (LITERAL) { // See comments in LockDuringDumpAgent.java
System.out.println("I am able to lock the literal string \"" + LITERAL + "\"");
}
}
}