jdk/test/java/lang/ref/CleanerTest.java
author duke
Wed, 05 Jul 2017 21:46:33 +0200
changeset 38602 b72e50a81d43
parent 36237 963d1115678b
child 40686 1b855fa5c9c5
permissions -rw-r--r--
Merge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     1
/*
34942
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
     2
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     4
 *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     7
 * published by the Free Software Foundation.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     8
 *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    13
 * accompanied this code).
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    14
 *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    18
 *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    21
 * questions.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    22
 */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    23
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    24
import java.lang.ref.Cleaner;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    25
import java.lang.ref.Reference;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    26
import java.lang.ref.PhantomReference;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    27
import java.lang.ref.ReferenceQueue;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    28
import java.lang.ref.SoftReference;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    29
import java.lang.ref.WeakReference;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    30
import java.util.Objects;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    31
import java.util.concurrent.ConcurrentHashMap;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    32
import java.util.concurrent.Semaphore;
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    33
import java.util.concurrent.TimeUnit;
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    34
import java.util.function.Consumer;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    35
import java.util.function.Supplier;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    36
34942
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
    37
import jdk.internal.ref.PhantomCleanable;
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
    38
import jdk.internal.ref.WeakCleanable;
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
    39
import jdk.internal.ref.SoftCleanable;
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
    40
import jdk.internal.ref.CleanerFactory;
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    41
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    42
import sun.hotspot.WhiteBox;
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    43
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
    44
import jdk.test.lib.Utils;
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
    45
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    46
import org.testng.Assert;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    47
import org.testng.TestNG;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    48
import org.testng.annotations.Test;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    49
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    50
/*
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    51
 * @test
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
    52
 * @library /test/lib/share/classes /lib/testlibrary /test/lib
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    53
 * @build sun.hotspot.WhiteBox
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
    54
 * @build jdk.test.lib.Utils
36237
963d1115678b 8150998: Fix module dependences in java/lang tests
shurailine
parents: 35612
diff changeset
    55
 * @modules java.base/jdk.internal
963d1115678b 8150998: Fix module dependences in java/lang tests
shurailine
parents: 35612
diff changeset
    56
 *          java.base/jdk.internal.misc
963d1115678b 8150998: Fix module dependences in java/lang tests
shurailine
parents: 35612
diff changeset
    57
 *          java.base/jdk.internal.ref
963d1115678b 8150998: Fix module dependences in java/lang tests
shurailine
parents: 35612
diff changeset
    58
 *          java.management
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    59
 * @run main ClassFileInstaller sun.hotspot.WhiteBox
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    60
 * @run testng/othervm
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    61
 *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
34950
7593604a704d 8146671: [TEST BUG] java/lang/ref/CleanerTest.java required more memory for -UseCompressedOops runs
rriggs
parents: 34942
diff changeset
    62
 *      -verbose:gc CleanerTest
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    63
 */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    64
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    65
@Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    66
public class CleanerTest {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    67
    // A common CleaningService used by the test for notifications
34942
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
    68
    static final Cleaner COMMON = CleanerFactory.cleaner();
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    69
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    70
    // Access to WhiteBox utilities
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    71
    static final WhiteBox whitebox = WhiteBox.getWhiteBox();
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
    72
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    73
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    74
     * Test that sequences of the various actions on a Reference
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    75
     * and on the Cleanable instance have the desired result.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    76
     * The test cases are generated for each of phantom, weak and soft
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    77
     * references.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    78
     * The sequence of actions includes all permutations to an initial
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    79
     * list of actions including clearing the ref and resulting garbage
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    80
     * collection actions on the reference and explicitly performing
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    81
     * the cleaning action.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    82
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    83
    @Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    84
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    85
    void testCleanableActions() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    86
        Cleaner cleaner = Cleaner.create();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    87
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    88
        // Individually
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    89
        generateCases(cleaner, c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    90
        generateCases(cleaner, c -> c.doClean());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    91
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    92
        // Pairs
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    93
        generateCases(cleaner, c -> c.doClean(), c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    94
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    95
        CleanableCase s = setupPhantom(COMMON, cleaner);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    96
        cleaner = null;
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
    97
        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    98
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
    99
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   100
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   101
     * Test the jdk.internal.misc APIs with sequences of the various actions
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   102
     * on a Reference and on the Cleanable instance have the desired result.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   103
     * The test cases are generated for each of phantom, weak and soft
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   104
     * references.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   105
     * The sequence of actions includes all permutations to an initial
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   106
     * list of actions including clearing the ref and resulting garbage
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   107
     * collection actions on the reference, explicitly performing
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   108
     * the cleanup and explicitly clearing the cleaning action.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   109
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   110
    @Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   111
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   112
    void testRefSubtypes() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   113
        Cleaner cleaner = Cleaner.create();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   114
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   115
        // Individually
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   116
        generateCasesInternal(cleaner, c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   117
        generateCasesInternal(cleaner, c -> c.doClean());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   118
        generateCasesInternal(cleaner, c -> c.doClear());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   119
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   120
        // Pairs
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   121
        generateCasesInternal(cleaner,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   122
                c -> c.doClear(), c -> c.doClean());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   123
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   124
        // Triplets
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   125
        generateCasesInternal(cleaner,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   126
                c -> c.doClear(), c -> c.doClean(), c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   127
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   128
        generateExceptionCasesInternal(cleaner);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   129
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   130
        CleanableCase s = setupPhantom(COMMON, cleaner);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   131
        cleaner = null;
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   132
        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   133
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   134
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   135
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   136
     * Generate tests using the runnables for each of phantom, weak,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   137
     * and soft references.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   138
     * @param cleaner  the cleaner
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   139
     * @param runnables the sequence of actions on the test case
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   140
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   141
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   142
    void generateCases(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   143
        generateCases(() -> setupPhantom(cleaner, null), runnables.length, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   144
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   145
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   146
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   147
    void generateCasesInternal(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   148
        generateCases(() -> setupPhantomSubclass(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   149
                runnables.length, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   150
        generateCases(() -> setupWeakSubclass(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   151
                runnables.length, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   152
        generateCases(() -> setupSoftSubclass(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   153
                runnables.length, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   154
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   155
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   156
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   157
    void generateExceptionCasesInternal(Cleaner cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   158
        generateCases(() -> setupPhantomSubclassException(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   159
                1, c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   160
        generateCases(() -> setupWeakSubclassException(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   161
                1, c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   162
        generateCases(() -> setupSoftSubclassException(cleaner, null),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   163
                1, c -> c.clearRef());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   164
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   165
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   166
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   167
     * Generate all permutations of the sequence of runnables
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   168
     * and test each one.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   169
     * The permutations are generated using Heap, B.R. (1963) Permutations by Interchanges.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   170
     * @param generator the supplier of a CleanableCase
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   171
     * @param n the first index to interchange
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   172
     * @param runnables the sequence of actions
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   173
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   174
    @SuppressWarnings("unchecked")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   175
    void generateCases(Supplier<CleanableCase> generator, int n,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   176
                       Consumer<CleanableCase> ... runnables) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   177
        if (n == 1) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   178
            CleanableCase test = generator.get();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   179
            try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   180
                verifyGetRef(test);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   181
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   182
                // Apply the sequence of actions on the Ref
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   183
                for (Consumer<CleanableCase> c : runnables) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   184
                    c.accept(test);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   185
                }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   186
                verify(test);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   187
            } catch (Exception e) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   188
                Assert.fail(test.toString(), e);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   189
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   190
        } else {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   191
            for (int i = 0; i < n - 1; i += 1) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   192
                generateCases(generator, n - 1, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   193
                Consumer<CleanableCase> t = runnables[n - 1];
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   194
                int ndx = ((n & 1) == 0) ? i : 0;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   195
                runnables[n - 1] = runnables[ndx];
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   196
                runnables[ndx] = t;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   197
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   198
            generateCases(generator, n - 1, runnables);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   199
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   200
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   201
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   202
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   203
     * Verify the test case.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   204
     * Any actions directly on the Reference or Cleanable have been executed.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   205
     * The CleanableCase under test is given a chance to do the cleanup
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   206
     * by forcing a GC.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   207
     * The result is compared with the expected result computed
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   208
     * from the sequence of operations on the Cleanable.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   209
     * The Cleanable itself should have been cleanedup.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   210
     *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   211
     * @param test A CleanableCase containing the references
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   212
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   213
    void verify(CleanableCase test) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   214
        System.out.println(test);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   215
        int r = test.expectedResult();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   216
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   217
        CleanableCase cc = setupPhantom(COMMON, test.getCleanable());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   218
        test.clearCleanable();        // release this hard reference
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   219
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   220
        checkCleaned(test.getSemaphore(),
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   221
                r == CleanableCase.EV_CLEAN,
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   222
                "Cleanable was cleaned:");
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   223
        checkCleaned(cc.getSemaphore(), true,
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   224
                "The reference to the Cleanable was freed:");
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   225
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   226
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   227
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   228
     * Verify that the reference.get works (or not) as expected.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   229
     * It handles the cases where UnsupportedOperationException is expected.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   230
     *
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   231
     * @param test the CleanableCase
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   232
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   233
    void verifyGetRef(CleanableCase test) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   234
        Reference<?> r = (Reference) test.getCleanable();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   235
        try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   236
            Object o = r.get();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   237
            Reference<?> expectedRef = test.getRef();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   238
            Assert.assertEquals(expectedRef.get(), o,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   239
                    "Object reference incorrect");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   240
            if (r.getClass().getName().endsWith("CleanableRef")) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   241
                Assert.fail("should not be able to get referent");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   242
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   243
        } catch (UnsupportedOperationException uoe) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   244
            if (r.getClass().getName().endsWith("CleanableRef")) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   245
                // Expected exception
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   246
            } else {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   247
                Assert.fail("Unexpected exception from subclassed cleanable: " +
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   248
                        uoe.getMessage() + ", class: " + r.getClass());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   249
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   250
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   251
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   252
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   253
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   254
     * Test that releasing the reference to the Cleaner service allows it to be
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   255
     * be freed.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   256
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   257
    @Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   258
    void testCleanerTermination() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   259
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   260
        Cleaner service = Cleaner.create();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   261
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   262
        PhantomReference<Object> ref = new PhantomReference<>(service, queue);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   263
        System.gc();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   264
        // Clear the Reference to the cleaning service and force a gc.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   265
        service = null;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   266
        System.gc();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   267
        try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   268
            Reference<?> r = queue.remove(1000L);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   269
            Assert.assertNotNull(r, "queue.remove timeout,");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   270
            Assert.assertEquals(r, ref, "Wrong Reference dequeued");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   271
        } catch (InterruptedException ie) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   272
            System.out.printf("queue.remove Interrupted%n");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   273
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   274
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   275
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   276
    /**
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   277
     * Check a semaphore having been released by cleanup handler.
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   278
     * Force a number of GC cycles to give the GC a chance to process
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   279
     * the Reference and for the cleanup action to be run.
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   280
     * Use a larger number of cycles to wait for an expected cleaning to occur.
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   281
     *
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   282
     * @param semaphore a Semaphore
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   283
     * @param expectCleaned true if cleaning should occur
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   284
     * @param msg a message to explain the error
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   285
     */
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   286
    static void checkCleaned(Semaphore semaphore, boolean expectCleaned,
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   287
                             String msg) {
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   288
        long max_cycles = expectCleaned ? 10 : 3;
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   289
        long cycle = 0;
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   290
        for (; cycle < max_cycles; cycle++) {
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   291
            // Force GC
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   292
            whitebox.fullGC();
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   293
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   294
            try {
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   295
                if (semaphore.tryAcquire(Utils.adjustTimeout(10L), TimeUnit.MILLISECONDS)) {
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   296
                    System.out.printf(" Cleanable cleaned in cycle: %d%n", cycle);
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   297
                    Assert.assertEquals(true, expectCleaned, msg);
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   298
                    return;
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   299
                }
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   300
            } catch (InterruptedException ie) {
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   301
                // retry in outer loop
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   302
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   303
        }
34823
f3f6509be104 8146012: CleanerTest fails: Cleanable should have been freed
rriggs
parents: 34724
diff changeset
   304
        // Object has not been cleaned
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   305
        Assert.assertEquals(false, expectCleaned, msg);
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   306
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   307
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   308
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   309
     * Create a CleanableCase for a PhantomReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   310
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   311
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   312
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   313
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   314
    static CleanableCase setupPhantom(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   315
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   316
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   317
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   318
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   319
        Cleaner.Cleanable c1 = cleaner.register(obj, () -> s1.release());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   320
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   321
        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   322
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   323
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   324
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   325
     * Create a CleanableCase for a PhantomReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   326
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   327
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   328
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   329
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   330
    static CleanableCase setupPhantomSubclass(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   331
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   332
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   333
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   334
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   335
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   336
        Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   337
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   338
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   339
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   340
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   341
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   342
        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   343
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   344
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   345
     * Create a CleanableCase for a WeakReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   346
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   347
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   348
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   349
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   350
    static CleanableCase setupWeakSubclass(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   351
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   352
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   353
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   354
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   355
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   356
        Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   357
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   358
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   359
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   360
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   361
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   362
        return new CleanableCase(new WeakReference<>(obj, null), c1, s1);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   363
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   364
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   365
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   366
     * Create a CleanableCase for a SoftReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   367
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   368
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   369
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   370
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   371
    static CleanableCase setupSoftSubclass(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   372
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   373
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   374
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   375
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   376
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   377
        Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   378
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   379
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   380
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   381
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   382
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   383
        return new CleanableCase(new SoftReference<>(obj, null), c1, s1);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   384
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   385
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   386
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   387
     * Create a CleanableCase for a PhantomReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   388
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   389
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   390
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   391
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   392
    static CleanableCase setupPhantomSubclassException(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   393
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   394
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   395
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   396
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   397
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   398
        Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   399
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   400
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   401
                throw new RuntimeException("Exception thrown to cleaner thread");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   402
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   403
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   404
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   405
        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1, true);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   406
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   407
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   408
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   409
     * Create a CleanableCase for a WeakReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   410
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   411
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   412
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   413
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   414
    static CleanableCase setupWeakSubclassException(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   415
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   416
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   417
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   418
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   419
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   420
        Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   421
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   422
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   423
                throw new RuntimeException("Exception thrown to cleaner thread");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   424
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   425
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   426
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   427
        return new CleanableCase(new WeakReference<>(obj, null), c1, s1, true);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   428
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   429
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   430
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   431
     * Create a CleanableCase for a SoftReference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   432
     * @param cleaner the cleaner to use
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   433
     * @param obj an object or null to create a new Object
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   434
     * @return a new CleanableCase preset with the object, cleanup, and semaphore
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   435
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   436
    static CleanableCase setupSoftSubclassException(Cleaner cleaner, Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   437
        if (obj == null) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   438
            obj = new Object();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   439
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   440
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   441
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   442
        Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   443
            protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   444
                s1.release();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   445
                throw new RuntimeException("Exception thrown to cleaner thread");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   446
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   447
        };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   448
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   449
        return new CleanableCase(new SoftReference<>(obj, null), c1, s1, true);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   450
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   451
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   452
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   453
     * CleanableCase encapsulates the objects used for a test.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   454
     * The reference to the object is not held directly,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   455
     * but in a Reference object that can be cleared.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   456
     * The semaphore is used to count whether the cleanup occurred.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   457
     * It can be awaited on to determine that the cleanup has occurred.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   458
     * It can be checked for non-zero to determine if it was
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   459
     * invoked or if it was invoked twice (a bug).
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   460
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   461
    static class CleanableCase {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   462
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   463
        private volatile Reference<?> ref;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   464
        private volatile Cleaner.Cleanable cleanup;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   465
        private final Semaphore semaphore;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   466
        private final boolean throwsEx;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   467
        private final int[] events;   // Sequence of calls to clean, clear, etc.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   468
        private volatile int eventNdx;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   469
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   470
        public static int EV_UNKNOWN = 0;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   471
        public static int EV_CLEAR = 1;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   472
        public static int EV_CLEAN = 2;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   473
        public static int EV_UNREF = 3;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   474
        public static int EV_CLEAR_CLEANUP = 4;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   475
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   476
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   477
        CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   478
                      Semaphore semaphore) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   479
            this.ref = ref;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   480
            this.cleanup = cleanup;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   481
            this.semaphore = semaphore;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   482
            this.throwsEx = false;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   483
            this.events = new int[4];
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   484
            this.eventNdx = 0;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   485
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   486
        CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   487
                      Semaphore semaphore,
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   488
                      boolean throwsEx) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   489
            this.ref = ref;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   490
            this.cleanup = cleanup;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   491
            this.semaphore = semaphore;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   492
            this.throwsEx = throwsEx;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   493
            this.events = new int[4];
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   494
            this.eventNdx = 0;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   495
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   496
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   497
        public Reference<?> getRef() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   498
            return ref;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   499
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   500
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   501
        public void clearRef() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   502
            addEvent(EV_UNREF);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   503
            ref.clear();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   504
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   505
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   506
        public Cleaner.Cleanable getCleanable() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   507
            return cleanup;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   508
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   509
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   510
        public void doClean() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   511
            try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   512
                addEvent(EV_CLEAN);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   513
                cleanup.clean();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   514
            } catch (RuntimeException ex) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   515
                if (!throwsEx) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   516
                    // unless it is known this case throws an exception, rethrow
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   517
                    throw ex;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   518
                }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   519
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   520
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   521
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   522
        public void doClear() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   523
            addEvent(EV_CLEAR);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   524
            ((Reference)cleanup).clear();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   525
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   526
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   527
        public void clearCleanable() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   528
            addEvent(EV_CLEAR_CLEANUP);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   529
            cleanup = null;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   530
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   531
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   532
        public Semaphore getSemaphore() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   533
            return semaphore;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   534
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   535
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   536
        public boolean isCleaned() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   537
            return semaphore.availablePermits() != 0;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   538
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   539
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   540
        private synchronized void addEvent(int e) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   541
            events[eventNdx++] = e;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   542
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   543
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   544
        /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   545
         * Computed the expected result from the sequence of events.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   546
         * If EV_CLEAR appears before anything else, it is cleared.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   547
         * If EV_CLEAN appears before EV_UNREF, then it is cleaned.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   548
         * Anything else is Unknown.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   549
         * @return EV_CLEAR if the cleanup should occur;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   550
         *         EV_CLEAN if the cleanup should occur;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   551
         *         EV_UNKNOWN if it is unknown.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   552
         */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   553
        public synchronized int expectedResult() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   554
            // Test if EV_CLEAR appears before anything else
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   555
            int clearNdx = indexOfEvent(EV_CLEAR);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   556
            int cleanNdx = indexOfEvent(EV_CLEAN);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   557
            int unrefNdx = indexOfEvent(EV_UNREF);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   558
            if (clearNdx < cleanNdx) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   559
                return EV_CLEAR;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   560
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   561
            if (cleanNdx < clearNdx || cleanNdx < unrefNdx) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   562
                return EV_CLEAN;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   563
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   564
            if (unrefNdx < eventNdx) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   565
                return EV_CLEAN;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   566
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   567
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   568
            return EV_UNKNOWN;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   569
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   570
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   571
        private synchronized  int indexOfEvent(int e) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   572
            for (int i = 0; i < eventNdx; i++) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   573
                if (events[i] == e) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   574
                    return i;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   575
                }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   576
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   577
            return eventNdx;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   578
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   579
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   580
        private static final String[] names =
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   581
                {"UNKNOWN", "EV_CLEAR", "EV_CLEAN", "EV_UNREF", "EV_CLEAR_CLEANUP"};
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   582
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   583
        public String eventName(int event) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   584
            return names[event];
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   585
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   586
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   587
        public synchronized String eventsString() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   588
            StringBuilder sb = new StringBuilder();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   589
            sb.append('[');
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   590
            for (int i = 0; i < eventNdx; i++) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   591
                if (i > 0) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   592
                    sb.append(", ");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   593
                }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   594
                sb.append(eventName(events[i]));
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   595
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   596
            sb.append(']');
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   597
            sb.append(", throwEx: ");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   598
            sb.append(throwsEx);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   599
            return sb.toString();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   600
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   601
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   602
        public String toString() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   603
            return String.format("Case: %s, expect: %s, events: %s",
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   604
                    getRef().getClass().getName(),
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   605
                    eventName(expectedResult()), eventsString());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   606
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   607
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   608
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   609
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   610
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   611
     * Example using a Cleaner to remove WeakKey references from a Map.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   612
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   613
    @Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   614
    void testWeakKey() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   615
        ConcurrentHashMap<WeakKey<String>, String> map = new ConcurrentHashMap<>();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   616
        Cleaner cleaner = Cleaner.create();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   617
        String key = new String("foo");  //  ensure it is not interned
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   618
        String data = "bar";
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   619
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   620
        map.put(new WeakKey<>(key, cleaner, map), data);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   621
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   622
        WeakKey<String> k2 = new WeakKey<>(key, cleaner, map);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   623
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   624
        Assert.assertEquals(map.get(k2), data, "value should be found in the map");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   625
        key = null;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   626
        System.gc();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   627
        Assert.assertNotEquals(map.get(k2), data, "value should not be found in the map");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   628
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   629
        final long CYCLE_MAX = Utils.adjustTimeout(30L);
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   630
        for (int i = 1; map.size() > 0 && i < CYCLE_MAX; i++) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   631
            map.forEach( (k, v) -> System.out.printf("    k: %s, v: %s%n", k, v));
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   632
            try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   633
                Thread.sleep(10L);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   634
            } catch (InterruptedException ie) {}
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   635
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   636
        Assert.assertEquals(map.size(), 0, "Expected map to be empty;");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   637
        cleaner = null;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   638
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   639
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   640
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   641
     * Test sample class for WeakKeys in Map.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   642
     * @param <K> A WeakKey of type K
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   643
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   644
    class WeakKey<K> extends WeakReference<K> {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   645
        private final int hash;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   646
        private final ConcurrentHashMap<WeakKey<K>, ?> map;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   647
        Cleaner.Cleanable cleanable;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   648
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   649
        public WeakKey(K key, Cleaner c, ConcurrentHashMap<WeakKey<K>, ?> map) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   650
            super(key);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   651
            this.hash = key.hashCode();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   652
            this.map = map;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   653
            cleanable = new WeakCleanable<Object>(key, c) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   654
                protected void performCleanup() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   655
                    map.remove(WeakKey.this);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   656
                }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   657
            };
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   658
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   659
        public int hashCode() { return hash; }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   660
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   661
        public boolean equals(Object obj) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   662
            if (obj == this) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   663
                return true;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   664
            }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   665
            if (!(obj instanceof WeakKey)) return false;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   666
            K key = get();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   667
            if (key == null) return obj == this;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   668
            return key == ((WeakKey<?>)obj).get();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   669
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   670
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   671
        public String toString() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   672
            return "WeakKey:" + Objects.toString(get() + ", cleanableRef: " +
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   673
                    ((Reference)cleanable).get());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   674
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   675
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   676
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   677
    /**
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   678
     * Verify that casting a Cleanup to a Reference is not allowed to
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   679
     * get the referent or clear the reference.
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   680
     */
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   681
    @Test
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   682
    @SuppressWarnings("rawtypes")
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   683
    void testReferentNotAvailable() {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   684
        Cleaner cleaner = Cleaner.create();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   685
        Semaphore s1 = new Semaphore(0);
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   686
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   687
        Object obj = new String("a new string");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   688
        Cleaner.Cleanable c = cleaner.register(obj, () -> s1.release());
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   689
        Reference r = (Reference) c;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   690
        try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   691
            Object o = r.get();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   692
            System.out.printf("r: %s%n", Objects.toString(o));
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   693
            Assert.fail("should not be able to get the referent from Cleanable");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   694
        } catch (UnsupportedOperationException uoe) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   695
            // expected
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   696
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   697
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   698
        try {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   699
            r.clear();
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   700
            Assert.fail("should not be able to clear the referent from Cleanable");
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   701
        } catch (UnsupportedOperationException uoe) {
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   702
            // expected
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   703
        }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   704
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   705
        obj = null;
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   706
        checkCleaned(s1, true, "reference was cleaned:");
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   707
        cleaner = null;
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   708
    }
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   709
34942
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   710
    /**
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   711
     * Test the Cleaner from the CleanerFactory.
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   712
     */
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   713
    @Test
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   714
    void testCleanerFactory() {
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   715
        Cleaner cleaner = CleanerFactory.cleaner();
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   716
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   717
        Object obj = new Object();
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   718
        CleanableCase s = setupPhantom(cleaner, obj);
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   719
        obj = null;
35612
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   720
        checkCleaned(s.getSemaphore(), true,
500ebb7a5ed9 8146773: java/lang/ref/CleanerTest.java CleanerTest.testRefSubtypes() fails
rriggs
parents: 34950
diff changeset
   721
                "Object was cleaned using CleanerFactor.cleaner():");
34942
4b462ee18ed9 8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents: 34823
diff changeset
   722
    }
34724
e664c5672743 8138696: java.lang.ref.Cleaner - an easy to use alternative to finalization
rriggs
parents:
diff changeset
   723
}