Home | History | Annotate | Download | only in ref
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.tests.java.lang.ref;
     19 
     20 import java.lang.ref.PhantomReference;
     21 import java.lang.ref.Reference;
     22 import java.lang.ref.ReferenceQueue;
     23 import libcore.java.lang.ref.FinalizationTester;
     24 
     25 //TODO: write a test to verify that the referent's finalize() happens
     26 //      before the PhantomReference is enqueued.
     27 
     28 public class PhantomReferenceTest extends junit.framework.TestCase {
     29     static Boolean bool;
     30     public boolean isCalled = false;
     31     protected void doneSuite() {
     32         bool = null;
     33     }
     34 
     35     /**
     36      * java.lang.ref.PhantomReference#get()
     37      */
     38     public void test_get() {
     39         ReferenceQueue rq = new ReferenceQueue();
     40         bool = new Boolean(false);
     41         PhantomReference pr = new PhantomReference(bool, rq);
     42         assertNull("get() should return null.", pr.get());
     43         pr.enqueue();
     44         assertNull("get() should return null.", pr.get());
     45         pr.clear();
     46         assertNull("get() should return null.", pr.get());
     47     }
     48 
     49     /**
     50      * java.lang.Runtime#gc()
     51      */
     52     public void test_gcInteraction_Runtime() {
     53         check_gcInteraction(() -> { Runtime.getRuntime().gc(); } );
     54     }
     55 
     56     /**
     57      * Checks that the sequence {@link System#gc()}, {@link System#runFinalization()}}
     58      * also has the effect as asserted for {@link Runtime#gc()} elsewhere. The
     59      * conditions under which System.gc() results in a garbage collection are an
     60      * implementation detail not guaranteed by documentation.
     61      */
     62     public void test_gcInteraction_System() {
     63         check_gcInteraction(() -> {
     64             System.gc();
     65             System.runFinalization();
     66         } );
     67     }
     68 
     69     private void check_gcInteraction(Runnable gc) {
     70         class TestPhantomReference<T> extends PhantomReference<T> {
     71             public TestPhantomReference(T referent,
     72                     ReferenceQueue<? super T> q) {
     73                 super(referent, q);
     74             }
     75             public boolean enqueue() {
     76                 // Initiate another GC from inside enqueue() to
     77                 // see if it causes any problems inside the VM.
     78                 gc.run();
     79                 return super.enqueue();
     80             }
     81         }
     82 
     83         final ReferenceQueue rq = new ReferenceQueue();
     84         final PhantomReference[] tprs = new PhantomReference[4];
     85 
     86         class TestThread extends Thread {
     87             public void run() {
     88                 // Create the object in a separate thread to ensure
     89                 // it will be gc'ed.
     90                 Object obj = new Object();
     91                 tprs[0] = new TestPhantomReference(obj, rq);
     92                 tprs[1] = new TestPhantomReference(obj, rq);
     93                 tprs[2] = new TestPhantomReference(obj, rq);
     94                 tprs[3] = new TestPhantomReference(obj, rq);
     95             }
     96         }
     97 
     98         try {
     99             Thread t = new TestThread();
    100             t.start();
    101             t.join();
    102 
    103             FinalizationTester.induceFinalization();
    104 
    105             assertNull("get() should return null.", tprs[0].get());
    106             assertNull("get() should return null.", tprs[1].get());
    107             assertNull("get() should return null.", tprs[2].get());
    108             assertNull("get() should return null.", tprs[3].get());
    109 
    110             for (int i = 0; i < 4; i++) {
    111                 Reference r = rq.remove(100L);
    112                 assertNotNull("Reference should have been enqueued.", r);
    113             }
    114 
    115             // These are to make sure that tprs and its elements don't get
    116             // optimized out.
    117             assertNull("get() should return null.", tprs[0].get());
    118             assertNull("get() should return null.", tprs[1].get());
    119             assertNull("get() should return null.", tprs[2].get());
    120             assertNull("get() should return null.", tprs[3].get());
    121         } catch (InterruptedException e) {
    122             fail("InterruptedException : " + e.getMessage());
    123         }
    124     }
    125 
    126     /**
    127      * java.lang.ref.PhantomReference#PhantomReference(java.lang.Object,
    128      *        java.lang.ref.ReferenceQueue)
    129      */
    130     public void test_ConstructorLjava_lang_ObjectLjava_lang_ref_ReferenceQueue() {
    131         ReferenceQueue rq = new ReferenceQueue();
    132         bool = new Boolean(true);
    133         try {
    134             PhantomReference pr = new PhantomReference(bool, rq);
    135             // Allow the finalizer to run to potentially enqueue
    136             Thread.sleep(1000);
    137             assertTrue("Initialization failed.", !pr.isEnqueued());
    138         } catch (Exception e) {
    139             fail("Exception during test : " + e.getMessage());
    140         }
    141         // need a reference to bool so the jit does not optimize it away
    142         assertTrue("should always pass", bool.booleanValue());
    143 
    144         boolean exception = false;
    145         try {
    146             new PhantomReference(bool, null);
    147         } catch (NullPointerException e) {
    148             exception = true;
    149         }
    150         assertTrue("Should not throw NullPointerException", !exception);
    151     }
    152 
    153     protected void setUp() {
    154     }
    155 
    156     protected void tearDown() {
    157     }
    158 }
    159