8316417: ObjectMonitorIterator does not return the most recent monitor and is incorrect if no monitors exists

Reviewed-by: cjplummer, dholmes
This commit is contained in:
Axel Boldt-Christmas 2023-09-27 08:16:34 +00:00
parent fee9d3362c
commit 50a7a04e9a
6 changed files with 26 additions and 28 deletions
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot
test
hotspot/jtreg
runtime/cds/appcds
serviceability/sa
lib/jdk/test/lib/apps

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2023, 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
@ -43,8 +43,10 @@ public class ObjectSynchronizer {
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ObjectSynchronizer");
inUseList = type.getAddressField("_in_use_list").getValue();
Type objectSynchronizerType = db.lookupType("ObjectSynchronizer");
Type monitorListType = db.lookupType("MonitorList");
Address monitorListAddr = objectSynchronizerType.getField("_in_use_list").getStaticFieldAddress();
inUseListHead = monitorListType.getAddressField("_head").getAddress(monitorListAddr);
}
public long identityHashValueFor(Oop obj) {
@ -70,11 +72,7 @@ public class ObjectSynchronizer {
}
public static Iterator objectMonitorIterator() {
if (inUseList != null) {
return new ObjectMonitorIterator();
} else {
return null;
}
return new ObjectMonitorIterator();
}
private static class ObjectMonitorIterator implements Iterator {
@ -83,21 +81,23 @@ public class ObjectSynchronizer {
// are not returned by this Iterator.
ObjectMonitorIterator() {
mon = new ObjectMonitor(inUseList);
mon = inUseListHead == null ? null : new ObjectMonitor(inUseListHead);
}
public boolean hasNext() {
return (mon.nextOM() != null);
return (mon != null);
}
public Object next() {
// advance to next entry
Address monAddr = mon.nextOM();
if (monAddr == null) {
ObjectMonitor ret = mon;
if (ret == null) {
throw new NoSuchElementException();
}
mon = new ObjectMonitor(monAddr);
return mon;
// advance to next entry
Address nextMon = mon.nextOM();
mon = nextMon == null ? null : new ObjectMonitor(nextMon);
return ret;
}
public void remove() {
@ -107,6 +107,6 @@ public class ObjectSynchronizer {
private ObjectMonitor mon;
}
private static Address inUseList;
private static Address inUseListHead;
}

@ -94,11 +94,6 @@ public class MonitorCacheDumpPanel extends JPanel {
private void dumpOn(PrintStream tty) {
Iterator i = ObjectSynchronizer.objectMonitorIterator();
if (i == null) {
tty.println("This version of HotSpot VM doesn't support monitor cache dump.");
tty.println("You need 1.4.0_04, 1.4.1_01 or later versions");
return;
}
ObjectMonitor mon;
while (i.hasNext()) {
mon = (ObjectMonitor)i.next();

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, 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
@ -38,7 +38,7 @@ import jtreg.SkippedException;
* @build JCmdTestLingeredApp Hello jdk.test.lib.apps.LingeredApp
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar loadclass.jar JCmdTestLingeredApp
* jdk.test.lib.apps.LingeredApp jdk.test.lib.apps.LingeredApp$1
* jdk.test.lib.apps.LingeredApp jdk.test.lib.apps.LingeredApp$1 jdk.test.lib.apps.LingeredApp$SteadyStateLock
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox
* @run main/othervm/timeout=500 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar DynamicSharedSymbols
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, 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
@ -64,7 +64,8 @@ public abstract class JCmdTestDumpBase {
private static final String TEST_CLASSES[] =
{"JCmdTestLingeredApp",
"jdk/test/lib/apps/LingeredApp",
"jdk/test/lib/apps/LingeredApp$1"};
"jdk/test/lib/apps/LingeredApp$1",
"jdk/test/lib/apps/LingeredApp$SteadyStateLock"};
private static final String BOOT_CLASSES[] = {"Hello"};
protected static String testJar = null;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -82,6 +82,7 @@ public class TestObjectMonitorIterate {
Long.toString(lingeredAppPid));
SATestUtils.addPrivilegesIfNeeded(processBuilder);
OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
SAOutput.shouldContain("SteadyStateLock");
SAOutput.shouldHaveExitValue(0);
System.out.println(SAOutput.getOutput());
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, 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
@ -587,6 +587,7 @@ public class LingeredApp {
}
}
static class SteadyStateLock {};
/**
* This part is the application itself. First arg is optional "forceCrash".
@ -616,7 +617,7 @@ public class LingeredApp {
Path path = Paths.get(theLockFileName);
try {
Object steadyStateObj = new Object();
Object steadyStateObj = new SteadyStateLock();
synchronized(steadyStateObj) {
startSteadyStateThread(steadyStateObj);
if (forceCrash) {