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