/* * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package nsk.share; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; /* * This class create/delete reference with given type. * * Supported reference types are: * - strong * - soft * - weak * - phantom * - jni local * - jni global * - jni weak */ public class ReferringObject { static { System.loadLibrary("JNIreferences"); } public final static int maxJNIGlobalReferences = 1000; public final static int maxJNIWeakReferences = 1000; private Object reference; private String referenceType; //used for storing jni global and jni weak references private int referenceIndex; public ReferringObject(Object object, String referenceType) { this.referenceType = referenceType; if(referenceType.equals(ObjectInstancesManager.STRONG_REFERENCE)) { createStrongReference(object); } else if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE)) { createSoftReference(object); } else if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE)) { createWeakReference(object); } else if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE)) { createPhantomReference(object); } else if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE)) { createJNIGlobalReference(object); } else if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE)) { createJNILocalReference(object); } else if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE)) { createJNIWeakReference(object); } else throw new IllegalArgumentException("Invalid reference type: " + referenceType); } public void delete() { if(referenceType == null) { throw new TestBug("Reference type is null"); } if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE)) { if(reference == null) { throw new TestBug("Reference is null for SoftReference"); } if(((SoftReference)reference).get() == null) { // throw new TestBug("Test execution error: SoftReference was collected"); } } else if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE)) { if(reference == null) { throw new TestBug("Reference is null for WeakReference"); } if(((WeakReference)reference).get() == null) { // throw new TestBug("Test execution error: WeakReference was collected"); } } else if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE)) { if(reference == null) { throw new TestBug("Reference is null for PhantomReference"); } } else if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE)) { deleteJNIGlobalReferenceNative(referenceIndex); } else if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE)) { deleteJNILocalReference(); } else if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE)) { try { deleteJNIWeakReferenceNative(referenceIndex); } catch (Throwable t) { } } reference = null; } private void createStrongReference(Object object) { reference = object; } private void createSoftReference(Object object) { reference = new SoftReference(object); } private void createWeakReference(Object object) { reference = new WeakReference(object); } private void createPhantomReference(Object object) { reference = new PhantomReference(object, new ReferenceQueue()); } private void createJNIGlobalReference(Object object) { referenceIndex = createJNIGlobalReferenceNative(object, maxJNIGlobalReferences); if(referenceIndex < 0) { throw new TestBug("Error on creation of JNI_Global reference, Possible number of JNI_Global references exceeded max available value!"); } } /* * Since jni local reference valid only for duration of native method call, to create jni local reference * special thread is created which enter in native method, create jni local reference and wait */ private void createJNILocalReference(Object object) { this.reference = object; jniLocalReferenceThread = new JNILocalReferenceThread(); jniLocalReferenceThread.start(); // wait till JNI local reference will be created jniLocalReferenceThread.createWhicket.waitFor(); reference = null; } private void deleteJNILocalReference() { // notify JNI method that JNI local reference is not needed any more and could be released jniLocalReferenceThread.deleteWhicket.unlock(); try { jniLocalReferenceThread.join(1000 * 60 * 2); if(jniLocalReferenceThread.isAlive()) { throw new TestBug("JNI_Local_Reference thread can't finish execution"); } } catch(InterruptedException e) { throw new TestBug("deleteJNILocalReference was interrupted"); } } private void createJNIWeakReference(Object object) { referenceIndex = createJNIWeakReferenceNative(object, maxJNIWeakReferences); if(referenceIndex < 0) { throw new TestBug("Error on creation of JNI_Weak reference. Possible number of JNI_Weak references exceeded max available value!"); } } class JNILocalReferenceThread extends Thread { Wicket createWhicket = new Wicket(); Wicket deleteWhicket = new Wicket(); public void run() { createJNILocalReferenceNative(reference, createWhicket, deleteWhicket); } } private JNILocalReferenceThread jniLocalReferenceThread; private native int createJNIGlobalReferenceNative(Object object, int maxJNIGlobalReferences); private native void deleteJNIGlobalReferenceNative(int index); private native void createJNILocalReferenceNative(Object object, Wicket createWhicket, Wicket deleteWhicket); private native int createJNIWeakReferenceNative(Object object, int maxJNIWeakReferences); private native void deleteJNIWeakReferenceNative(int index); }