1 /*
2  * Copyright (c) 2006, 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 nsk.share;
24 
25 import java.lang.ref.PhantomReference;
26 import java.lang.ref.ReferenceQueue;
27 import java.lang.ref.SoftReference;
28 import java.lang.ref.WeakReference;
29 
30 /*
31  * This class create/delete reference with given type.
32  *
33  * Supported reference types are:
34  * - strong
35  * - soft
36  * - weak
37  * - phantom
38  * - jni local
39  * - jni global
40  * - jni weak
41  */
42 public class ReferringObject
43 {
44         static
45         {
46                 System.loadLibrary("JNIreferences");
47         }
48 
49         public final static int maxJNIGlobalReferences = 1000;
50         public final static int maxJNIWeakReferences = 1000;
51 
52         private Object reference;
53 
54         private String referenceType;
55 
56         //used for storing jni global and jni weak references
57         private int referenceIndex;
58 
ReferringObject(Object object, String referenceType)59         public ReferringObject(Object object, String referenceType)
60         {
61                 this.referenceType = referenceType;
62 
63                 if(referenceType.equals(ObjectInstancesManager.STRONG_REFERENCE))
64                 {
65                         createStrongReference(object);
66                 }
67                 else
68                 if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
69                 {
70                         createSoftReference(object);
71                 }
72                 else
73                 if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
74                 {
75                         createWeakReference(object);
76                 }
77                 else
78                 if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
79                 {
80                         createPhantomReference(object);
81                 }
82                 else
83                 if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
84                 {
85                         createJNIGlobalReference(object);
86                 }
87                 else
88                 if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
89                 {
90                         createJNILocalReference(object);
91                 }
92                 else
93                 if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
94                 {
95                         createJNIWeakReference(object);
96                 }
97                 else
98                         throw new IllegalArgumentException("Invalid reference type: " + referenceType);
99         }
100 
delete()101         public void delete()
102         {
103                 if(referenceType == null)
104                 {
105                         throw new TestBug("Reference type is null");
106                 }
107 
108                 if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
109                 {
110                         if(reference == null)
111                         {
112                                 throw new TestBug("Reference is null for SoftReference");
113                         }
114 
115                         if(((SoftReference)reference).get() == null)
116                         {
117                      //           throw new TestBug("Test execution error: SoftReference was collected");
118                         }
119                 }
120                 else
121                 if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
122                 {
123                         if(reference == null)
124                         {
125                                 throw new TestBug("Reference is null for WeakReference");
126                         }
127 
128                         if(((WeakReference)reference).get() == null)
129                         {
130                        //         throw new TestBug("Test execution error: WeakReference was collected");
131                         }
132                 }
133                 else
134                 if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
135                 {
136                         if(reference == null)
137                         {
138                                 throw new TestBug("Reference is null for PhantomReference");
139                         }
140                 }
141                 else
142                 if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
143                 {
144                         deleteJNIGlobalReferenceNative(referenceIndex);
145                 }
146                 else
147                 if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
148                 {
149                         deleteJNILocalReference();
150                 }
151                 else
152                 if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
153                 {
154                     try {
155                         deleteJNIWeakReferenceNative(referenceIndex);
156                     } catch (Throwable t)
157                     {
158 
159                     }
160                 }
161 
162                 reference = null;
163         }
164 
createStrongReference(Object object)165         private void createStrongReference(Object object)
166         {
167                 reference = object;
168         }
169 
createSoftReference(Object object)170         private void createSoftReference(Object object)
171         {
172                 reference = new SoftReference<Object>(object);
173         }
174 
createWeakReference(Object object)175         private void createWeakReference(Object object)
176         {
177                 reference = new WeakReference<Object>(object);
178         }
179 
createPhantomReference(Object object)180         private void createPhantomReference(Object object)
181         {
182                 reference = new PhantomReference<Object>(object, new ReferenceQueue<Object>());
183         }
184 
createJNIGlobalReference(Object object)185         private void createJNIGlobalReference(Object object)
186         {
187                 referenceIndex = createJNIGlobalReferenceNative(object, maxJNIGlobalReferences);
188 
189                 if(referenceIndex < 0)
190                 {
191                         throw new TestBug("Error on creation of JNI_Global reference, Possible number of JNI_Global references exceeded max available value!");
192                 }
193         }
194 
195         /*
196          * Since jni local reference valid only for duration of native method call, to create jni local reference
197          * special thread is created which enter in native method, create jni local reference and wait
198          */
createJNILocalReference(Object object)199         private void createJNILocalReference(Object object)
200         {
201                 this.reference = object;
202 
203                 jniLocalReferenceThread = new JNILocalReferenceThread();
204                 jniLocalReferenceThread.start();
205 
206                 // wait till JNI local reference will be created
207                 jniLocalReferenceThread.createWhicket.waitFor();
208 
209                 reference = null;
210         }
211 
deleteJNILocalReference()212         private void deleteJNILocalReference()
213         {
214                 // notify JNI method that JNI local reference is not needed any more and could be released
215                 jniLocalReferenceThread.deleteWhicket.unlock();
216 
217                 try
218                 {
219                         jniLocalReferenceThread.join(1000 * 60 * 2);
220 
221                         if(jniLocalReferenceThread.isAlive())
222                         {
223                                 throw new TestBug("JNI_Local_Reference thread can't finish execution");
224                         }
225                 }
226                 catch(InterruptedException e)
227                 {
228                         throw new TestBug("deleteJNILocalReference was interrupted");
229                 }
230         }
231 
createJNIWeakReference(Object object)232         private void createJNIWeakReference(Object object)
233         {
234                 referenceIndex = createJNIWeakReferenceNative(object, maxJNIWeakReferences);
235 
236                 if(referenceIndex < 0)
237                 {
238                         throw new TestBug("Error on creation of JNI_Weak reference. Possible number of JNI_Weak references exceeded max available value!");
239                 }
240         }
241 
242         class JNILocalReferenceThread
243                 extends Thread
244         {
245                 Wicket createWhicket = new Wicket();
246                 Wicket deleteWhicket = new Wicket();
247 
run()248                 public void run()
249                 {
250                         createJNILocalReferenceNative(reference, createWhicket, deleteWhicket);
251                 }
252         }
253 
254         private JNILocalReferenceThread jniLocalReferenceThread;
255 
createJNIGlobalReferenceNative(Object object, int maxJNIGlobalReferences)256         private native int createJNIGlobalReferenceNative(Object object, int maxJNIGlobalReferences);
257 
deleteJNIGlobalReferenceNative(int index)258         private native void deleteJNIGlobalReferenceNative(int index);
259 
createJNILocalReferenceNative(Object object, Wicket createWhicket, Wicket deleteWhicket)260         private native void createJNILocalReferenceNative(Object object, Wicket createWhicket, Wicket deleteWhicket);
261 
createJNIWeakReferenceNative(Object object, int maxJNIWeakReferences)262         private native int createJNIWeakReferenceNative(Object object, int maxJNIWeakReferences);
263 
deleteJNIWeakReferenceNative(int index)264         private native void deleteJNIWeakReferenceNative(int index);
265 }
266