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