Skip to content

Commit

Permalink
Added proper processing of Cleanables.
Browse files Browse the repository at this point in the history
  • Loading branch information
christianhaeubl committed Oct 29, 2019
1 parent 1c563ca commit f2fead2
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,6 @@ static void distributeReferences() {
trace.string(" dr: ").object(dr).newline();
if (dr instanceof FeebleReference<?>) {
final FeebleReference<?> fr = (FeebleReference<?>) dr;
/*
* For GR-14335: Rather than getting a NullPointerException, print out some
* values.
*/
if (fr.hasList()) {
final FeebleReferenceList<?> frList = fr.getList();
if (frList != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,6 @@ private static void toStdout(String msg) {
}
}

@TargetClass(className = "jdk.internal.ref.PhantomCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_PhantomCleanable {
}

@TargetClass(className = "jdk.internal.ref.WeakCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_WeakCleanable {
}

@TargetClass(className = "jdk.internal.ref.SoftCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_SoftCleanable {
}

@Platforms(Platform.HOSTED_ONLY.class)
class Package_jdk_internal_perf implements Function<TargetClass, String> {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, 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
Expand All @@ -24,29 +24,41 @@
*/
package com.oracle.svm.core.jdk;

import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.thread.ThreadingSupportImpl;
import com.oracle.svm.core.util.VMError;

/** Access to methods in support of {@link sun.misc}. */
public class SunMiscSupport {

@SuppressFBWarnings(value = "BC", justification = "Target_jdk_internal_ref_Cleaner is an alias for a class that extends Reference")
@SuppressWarnings("try")
public static void drainCleanerQueue() {
Target_java_lang_ref_ReferenceQueue queue = SubstrateUtil.cast(Target_jdk_internal_ref_Cleaner.dummyQueue, Target_java_lang_ref_ReferenceQueue.class);
Target_java_lang_ref_ReferenceQueue cleanerQueue = SubstrateUtil.cast(Target_jdk_internal_ref_Cleaner.dummyQueue, Target_java_lang_ref_ReferenceQueue.class);
processQueue(cleanerQueue);

if (JavaVersionUtil.JAVA_SPEC > 8) {
Target_java_lang_ref_ReferenceQueue cleanableQueue = SubstrateUtil.cast(Target_jdk_internal_ref_CleanerFactory.cleaner().impl.queue, Target_java_lang_ref_ReferenceQueue.class);
processQueue(cleanableQueue);
}
}

private static void processQueue(Target_java_lang_ref_ReferenceQueue queue) {
if (!queue.isEmpty()) {
ThreadingSupportImpl.pauseRecurringCallback("An exception in a recurring callback must not interrupt the cleaner processing as this would result in a memory leak.");
try {
for (; /* return */ ;) {
final Object entry = queue.poll();
Object entry = queue.poll();
if (entry == null) {
return;
}

if (entry instanceof Target_jdk_internal_ref_Cleaner) {
final Target_jdk_internal_ref_Cleaner cleaner = (Target_jdk_internal_ref_Cleaner) entry;
Target_jdk_internal_ref_Cleaner cleaner = (Target_jdk_internal_ref_Cleaner) entry;
cleaner.clean();
} else if (JavaVersionUtil.JAVA_SPEC > 8 && entry instanceof Target_java_lang_ref_Cleaner_Cleanable) {
Target_java_lang_ref_Cleaner_Cleanable cleaner = (Target_java_lang_ref_Cleaner_Cleanable) entry;
cleaner.clean();
} else {
VMError.shouldNotReachHere("Unexpected type: " + entry.getClass().getName());
}
}
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,35 @@ public final class Target_jdk_internal_ref_Cleaner {
static ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();

@Alias
public static native void create(Object obj, Runnable runnable);
native void clean();
}

/**
* On JDK11+, the cleaner infrastructure is quite different from JDK8:
* <ul>
* <li>java.lang.ref.Cleaner: starts a new thread to process its reference queue.</li>
* <li>jdk.internal.ref.CleanerFactory: provides a common cleaner that is used in all places that
* don't want to start an explicit reference cleaner thread. In native-image, we do not spawn a
* separate thread for the reference processing. Instead, we drain the queue after garbage
* collections in {@link SunMiscSupport#drainCleanerQueue()}.</li>
* <li>jdk.internal.ref.Cleaner: this only seems to be used by DirectByteBuffer but at least the
* handling is the same as on JDK 8.
* </ul>
*/
@TargetClass(className = "jdk.internal.ref.CleanerFactory", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_CleanerFactory {
@Alias
public static native Target_java_lang_ref_Cleaner cleaner();
}

@TargetClass(className = "java.lang.ref.Cleaner", onlyWith = JDK11OrLater.class)
final class Target_java_lang_ref_Cleaner {
@Alias//
public Target_jdk_internal_ref_CleanerImpl impl;
}

@TargetClass(className = "java.lang.ref.Cleaner$Cleanable", onlyWith = JDK11OrLater.class)
final class Target_java_lang_ref_Cleaner_Cleanable {
@Alias
native void clean();
}
Expand All @@ -87,5 +114,17 @@ final class Target_jdk_internal_ref_CleanerImpl {
Target_jdk_internal_ref_SoftCleanable softCleanableList;

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.lang.ref.ReferenceQueue")//
ReferenceQueue<Object> queue;
public ReferenceQueue<Object> queue;
}

@TargetClass(className = "jdk.internal.ref.PhantomCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_PhantomCleanable {
}

@TargetClass(className = "jdk.internal.ref.WeakCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_WeakCleanable {
}

@TargetClass(className = "jdk.internal.ref.SoftCleanable", onlyWith = JDK11OrLater.class)
final class Target_jdk_internal_ref_SoftCleanable {
}

0 comments on commit f2fead2

Please sign in to comment.