8259008: ArithmeticException was thrown at "Monitor Cache Dump" on HSDB
Reviewed-by: dcubed, gziemski, eosterlund, cjplummer, sspitsyn
This commit is contained in:
parent
69ee314b63
commit
6b24e98c42
src
hotspot/share/runtime
jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime
test/hotspot/jtreg/serviceability/sa
@ -58,31 +58,6 @@
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/preserveException.hpp"
|
||||
|
||||
class MonitorList {
|
||||
ObjectMonitor* volatile _head;
|
||||
volatile size_t _count;
|
||||
volatile size_t _max;
|
||||
|
||||
public:
|
||||
void add(ObjectMonitor* monitor);
|
||||
size_t unlink_deflated(Thread* self, LogStream* ls, elapsedTimer* timer_p,
|
||||
GrowableArray<ObjectMonitor*>* unlinked_list);
|
||||
size_t count() const;
|
||||
size_t max() const;
|
||||
|
||||
class Iterator;
|
||||
Iterator iterator() const;
|
||||
};
|
||||
|
||||
class MonitorList::Iterator {
|
||||
ObjectMonitor* _current;
|
||||
|
||||
public:
|
||||
Iterator(ObjectMonitor* head) : _current(head) {}
|
||||
bool has_next() const { return _current != NULL; }
|
||||
ObjectMonitor* next();
|
||||
};
|
||||
|
||||
void MonitorList::add(ObjectMonitor* m) {
|
||||
ObjectMonitor* head;
|
||||
do {
|
||||
@ -240,7 +215,7 @@ void ObjectSynchronizer::initialize() {
|
||||
set_in_use_list_ceiling(AvgMonitorsPerThreadEstimate);
|
||||
}
|
||||
|
||||
static MonitorList _in_use_list;
|
||||
MonitorList ObjectSynchronizer::_in_use_list;
|
||||
// monitors_used_above_threshold() policy is as follows:
|
||||
//
|
||||
// The ratio of the current _in_use_list count to the ceiling is used
|
||||
|
@ -35,6 +35,34 @@ class LogStream;
|
||||
class ObjectMonitor;
|
||||
class ThreadsList;
|
||||
|
||||
class MonitorList {
|
||||
friend class VMStructs;
|
||||
|
||||
private:
|
||||
ObjectMonitor* volatile _head;
|
||||
volatile size_t _count;
|
||||
volatile size_t _max;
|
||||
|
||||
public:
|
||||
void add(ObjectMonitor* monitor);
|
||||
size_t unlink_deflated(Thread* self, LogStream* ls, elapsedTimer* timer_p,
|
||||
GrowableArray<ObjectMonitor*>* unlinked_list);
|
||||
size_t count() const;
|
||||
size_t max() const;
|
||||
|
||||
class Iterator;
|
||||
Iterator iterator() const;
|
||||
};
|
||||
|
||||
class MonitorList::Iterator {
|
||||
ObjectMonitor* _current;
|
||||
|
||||
public:
|
||||
Iterator(ObjectMonitor* head) : _current(head) {}
|
||||
bool has_next() const { return _current != NULL; }
|
||||
ObjectMonitor* next();
|
||||
};
|
||||
|
||||
class ObjectSynchronizer : AllStatic {
|
||||
friend class VMStructs;
|
||||
|
||||
@ -144,6 +172,7 @@ class ObjectSynchronizer : AllStatic {
|
||||
private:
|
||||
friend class SynchronizerTest;
|
||||
|
||||
static MonitorList _in_use_list;
|
||||
static volatile bool _is_async_deflation_requested;
|
||||
static volatile bool _is_final_audit;
|
||||
static jlong _last_async_deflation_time_ns;
|
||||
|
@ -890,6 +890,8 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
volatile_nonstatic_field(ObjectMonitor, _recursions, intx) \
|
||||
nonstatic_field(BasicObjectLock, _lock, BasicLock) \
|
||||
nonstatic_field(BasicObjectLock, _obj, oop) \
|
||||
static_field(ObjectSynchronizer, _in_use_list, MonitorList) \
|
||||
volatile_nonstatic_field(MonitorList, _head, ObjectMonitor*) \
|
||||
\
|
||||
/*********************/ \
|
||||
/* Matcher (C2 only) */ \
|
||||
@ -1468,6 +1470,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
/************/ \
|
||||
\
|
||||
declare_toplevel_type(ObjectMonitor) \
|
||||
declare_toplevel_type(MonitorList) \
|
||||
declare_toplevel_type(ObjectSynchronizer) \
|
||||
declare_toplevel_type(BasicLock) \
|
||||
declare_toplevel_type(BasicObjectLock) \
|
||||
@ -2420,12 +2423,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
declare_constant(Deoptimization::Action_make_not_compilable) \
|
||||
declare_constant(Deoptimization::Action_LIMIT) \
|
||||
\
|
||||
/***************************************************/ \
|
||||
/* DEFAULT_CACHE_LINE_SIZE (globalDefinitions.hpp) */ \
|
||||
/***************************************************/ \
|
||||
\
|
||||
declare_preprocessor_constant("DEFAULT_CACHE_LINE_SIZE", DEFAULT_CACHE_LINE_SIZE) \
|
||||
\
|
||||
declare_constant(Deoptimization::Unpack_deopt) \
|
||||
declare_constant(Deoptimization::Unpack_exception) \
|
||||
declare_constant(Deoptimization::Unpack_uncommon_trap) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -43,22 +43,8 @@ public class ObjectSynchronizer {
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
||||
Type type;
|
||||
try {
|
||||
type = db.lookupType("ObjectSynchronizer");
|
||||
gBlockList = type.getAddressField("g_block_list").getValue();
|
||||
blockSize = db.lookupIntConstant("ObjectSynchronizer::_BLOCKSIZE").intValue();
|
||||
defaultCacheLineSize = db.lookupIntConstant("DEFAULT_CACHE_LINE_SIZE").intValue();
|
||||
} catch (RuntimeException e) { }
|
||||
type = db.lookupType("ObjectMonitor");
|
||||
objectMonitorTypeSize = type.getSize();
|
||||
if ((objectMonitorTypeSize % defaultCacheLineSize) != 0) {
|
||||
// sizeof(ObjectMonitor) is not already a multiple of a cache line.
|
||||
// The ObjectMonitor allocation code in ObjectSynchronizer pads each
|
||||
// ObjectMonitor in a block to the next cache line boundary.
|
||||
int needLines = ((int)objectMonitorTypeSize / defaultCacheLineSize) + 1;
|
||||
objectMonitorTypeSize = needLines * defaultCacheLineSize;
|
||||
}
|
||||
Type type = db.lookupType("ObjectSynchronizer");
|
||||
inUseList = type.getAddressField("_in_use_list").getValue();
|
||||
}
|
||||
|
||||
public long identityHashValueFor(Oop obj) {
|
||||
@ -84,7 +70,7 @@ public class ObjectSynchronizer {
|
||||
}
|
||||
|
||||
public static Iterator objectMonitorIterator() {
|
||||
if (gBlockList != null) {
|
||||
if (inUseList != null) {
|
||||
return new ObjectMonitorIterator();
|
||||
} else {
|
||||
return null;
|
||||
@ -93,47 +79,34 @@ public class ObjectSynchronizer {
|
||||
|
||||
private static class ObjectMonitorIterator implements Iterator {
|
||||
|
||||
// JVMTI raw monitors are not pointed by gBlockList
|
||||
// and are not included by this Iterator. May add them later.
|
||||
// JVMTI raw monitors are not included in _in_use_list and
|
||||
// are not returned by this Iterator.
|
||||
|
||||
ObjectMonitorIterator() {
|
||||
blockAddr = gBlockList;
|
||||
index = blockSize - 1;
|
||||
block = new ObjectMonitor(blockAddr);
|
||||
mon = new ObjectMonitor(inUseList);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return (index > 0 || block.nextOM() != null);
|
||||
return (mon.nextOM() != null);
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Address addr;
|
||||
if (index == 0) {
|
||||
// advance to next block
|
||||
blockAddr = block.nextOM();
|
||||
if (blockAddr == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
block = new ObjectMonitor(blockAddr);
|
||||
index = blockSize - 1;
|
||||
// advance to next entry
|
||||
Address monAddr = mon.nextOM();
|
||||
if (monAddr == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
|
||||
index --;
|
||||
return new ObjectMonitor(addr);
|
||||
mon = new ObjectMonitor(monAddr);
|
||||
return mon;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private ObjectMonitor block;
|
||||
private int index;
|
||||
private Address blockAddr;
|
||||
private ObjectMonitor mon;
|
||||
}
|
||||
|
||||
private static Address gBlockList;
|
||||
private static int blockSize;
|
||||
private static int defaultCacheLineSize;
|
||||
private static long objectMonitorTypeSize;
|
||||
private static Address inUseList;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, NTT DATA.
|
||||
* 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 sun.jvm.hotspot.HotSpotAgent;
|
||||
import sun.jvm.hotspot.oops.Oop;
|
||||
import sun.jvm.hotspot.runtime.ObjectMonitor;
|
||||
import sun.jvm.hotspot.runtime.ObjectSynchronizer;
|
||||
import sun.jvm.hotspot.runtime.VM;
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.SA.SATestUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8259008
|
||||
* @library /test/lib
|
||||
* @requires vm.hasSA
|
||||
* @modules jdk.hotspot.agent/sun.jvm.hotspot
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.oops
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.runtime
|
||||
* @run main TestObjectMonitorIterate
|
||||
*/
|
||||
|
||||
public class TestObjectMonitorIterate {
|
||||
|
||||
private static void test(String pid) {
|
||||
HotSpotAgent agent = new HotSpotAgent();
|
||||
agent.attach(Integer.parseInt(pid));
|
||||
try {
|
||||
var heap = VM.getVM().getObjectHeap();
|
||||
var itr = ObjectSynchronizer.objectMonitorIterator();
|
||||
|
||||
if (!itr.hasNext()) {
|
||||
throw new RuntimeException("Monitor not found");
|
||||
}
|
||||
|
||||
while (itr.hasNext()) {
|
||||
ObjectMonitor mon = (ObjectMonitor)itr.next();
|
||||
Oop oop = heap.newOop(mon.object());
|
||||
System.out.println("Monitor found: " + oop.getKlass().getName().asString());
|
||||
}
|
||||
} finally {
|
||||
agent.detach();
|
||||
}
|
||||
}
|
||||
|
||||
private static void createAnotherToAttach(long lingeredAppPid) throws Exception {
|
||||
// Start a new process to attach to the lingered app
|
||||
ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"--add-modules=jdk.hotspot.agent",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED",
|
||||
"TestObjectMonitorIterate",
|
||||
Long.toString(lingeredAppPid));
|
||||
SATestUtils.addPrivilegesIfNeeded(processBuilder);
|
||||
OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
|
||||
SAOutput.shouldHaveExitValue(0);
|
||||
System.out.println(SAOutput.getOutput());
|
||||
}
|
||||
|
||||
public static void main (String... args) throws Exception {
|
||||
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
|
||||
|
||||
if (args == null || args.length == 0) {
|
||||
LingeredApp app = new LingeredAppWithLock();
|
||||
try {
|
||||
LingeredApp.startApp(app, "-XX:+UsePerfData");
|
||||
createAnotherToAttach(app.getPid());
|
||||
} finally {
|
||||
LingeredApp.stopApp(app);
|
||||
}
|
||||
} else {
|
||||
test(args[0]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user