Skip to content

Commit

Permalink
[GR-34096] Backport to 21.3: Workaround for Cleaner static synchroniz…
Browse files Browse the repository at this point in the history
…ed methods leading to recursive locking of additionalMonitors map.

PullRequest: graal/10592
  • Loading branch information
Christian Wimmer committed Dec 18, 2021
2 parents cf58bea + 84a47b1 commit bfbde8e
Showing 1 changed file with 32 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,38 @@ protected static int getMonitorOffset(Object obj) {
return DynamicHub.fromClass(obj.getClass()).getMonitorOffset();
}

protected final ReentrantLock getOrCreateMonitor(Object obj, boolean createIfNotExisting) {
private static final Object CLEANER_CLASS;
private static final Object CLEANER_REPLACEMENT;

static {
try {
CLEANER_CLASS = Class.forName((JavaVersionUtil.JAVA_SPEC <= 8 ? "sun.misc." : "jdk.internal.ref.") + "Cleaner");
} catch (ClassNotFoundException ex) {
throw VMError.shouldNotReachHere(ex);
}
CLEANER_REPLACEMENT = new Object();
VMError.guarantee(FORCE_MONITOR_SLOT_TYPES.contains(CLEANER_REPLACEMENT.getClass()), "Must have a monitor slot for Cleaner replacement object");
}

protected final ReentrantLock getOrCreateMonitor(Object unreplacedObject, boolean createIfNotExisting) {
Object obj;
if (unreplacedObject == CLEANER_CLASS) {
/*
* Workaround for jdk.internal.ref.Cleaner when cleaners do not run in a separate
* thread. Cleaner uses static synchronized methods. Since classes (= DynamicHub) never
* have a monitor slot, static synchronized methods always use the additionalMonitors
* map. When a Cleaner then runs at a time where the application thread already holds
* the additionalMonitorsLock, i.e., when a GC runs while allocating a monitor in
* getOrCreateMonitorFromMap(), a disallowed recursive locking of additionalMonitorsLock
* would happen. Note that CLEANER_REPLACEMENT is an Object which always has a monitor
* slot. This workaround will be removed when we have a better implementation of static
* synchronized methods.
*/
obj = CLEANER_REPLACEMENT;
} else {
obj = unreplacedObject;
}

assert obj != null;
int monitorOffset = getMonitorOffset(obj);
if (monitorOffset != 0) {
Expand Down

0 comments on commit bfbde8e

Please sign in to comment.