1 /*
2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package gc.gctests.PhantomReference;
24 
25 import java.lang.ref.ReferenceQueue;
26 import java.util.Date;
27 import java.util.HashMap;
28 
29 /**
30  * Helper class that tracks the original hash code for the
31  * object.
32  */
33 public final class PhantomHelper {
34 
35     private int originalHashCode;
36     private int hashCounter;
37 
38     /**
39      * Constructor for helper class that tracks the hash code.
40      *
41      * @param originalHashCode Referred objects hash code
42      */
PhantomHelper(int originalHashCode)43     public PhantomHelper(int originalHashCode) {
44         this.originalHashCode = originalHashCode;
45         hashCounter = 1;
46     }
47 
48     /**
49      * Get the referred objects original hash code.
50      *
51      * @return Original referred objects hash code
52      */
getOriginalHashCode()53     public int getOriginalHashCode() {
54         return originalHashCode;
55     }
56 
57     /**
58      * Increase the counter for the number of objects
59      * using this hash code.
60      */
increaseHashCounter()61     public void increaseHashCounter() {
62         hashCounter++;
63     }
64 
65     /**
66      * Decrease the counter for the number of objects
67      * using this hash code.
68      */
decreaseHashCounter()69     public void decreaseHashCounter() {
70         hashCounter--;
71     }
72 
73     /**
74      * Retreive the hash code counter.
75      *
76      * @return Hash code counter value
77      */
getHashCounter()78     public int getHashCounter() {
79         return hashCounter;
80     }
81 
82     /**
83      * Verify all the hash codes from the objects in the reference
84      * queue against the hash map.
85      *
86      * @param rq Reference queue for the phantom references.
87      * @param hmHelper Hashmap that contains all the hash codes
88      * @param maxWaitTime Maximum time to wait for completion of deref:ing
89      * from the reference queue.
90      * @return True if all hash codes matches
91      */
checkAllHashCodes(ReferenceQueue rq, HashMap hmHelper, long maxWaitTime)92     public static final String checkAllHashCodes(ReferenceQueue rq,
93                                                  HashMap hmHelper,
94                                                  long maxWaitTime) {
95         // Check all the phantom references
96         long startTime = new Date().getTime();
97         boolean keepRunning = true;
98 
99         while (keepRunning) {
100             try {
101                 PRHelper prh = (PRHelper) rq.remove(1000);
102 
103                 if (prh != null) {
104                     Integer ik = new Integer(prh.getReferentHashCode());
105                     PhantomHelper ph = (PhantomHelper) hmHelper.get(ik);
106 
107                     if (ph != null) {
108                         if (ph.getOriginalHashCode()
109                                 == prh.getReferentHashCode()) {
110                             ph.decreaseHashCounter();
111                             if (ph.getHashCounter() == 0) {
112                                 hmHelper.remove(
113                                         new Integer(prh.getReferentHashCode()));
114                             } else {
115                                 hmHelper.put(ik, ph);
116                             }
117                             prh.clear();
118                         }
119                     } else {
120                         return "Unmapped hash code detected. The test is faulty.";
121                     }
122 
123                     prh = null;
124                 }
125             } catch (InterruptedException e) {
126                 ; // Checkstyle wants at least one line here...
127             }
128 
129             if (new Date().getTime() - startTime > maxWaitTime) {
130                 return "All phantom references weren't processed "
131                         + "in the configured max time ("
132                         + (maxWaitTime / 1000) + " secs)";
133             }
134 
135             if (hmHelper.size() == 0) {
136                 keepRunning = false;
137             }
138         }
139 
140         return null;
141     }
142 }
143