1 /*
   2  * Copyright (c) 2007, 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 
  24 /*
  25  * @test
  26  *
  27  * @summary converted from VM Testbase nsk/jdi/ObjectReference/referringObjects/referringObjects001.
  28  * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6]
  29  * VM Testbase readme:
  30  * DESCRIPTION
  31  *     Test checks behaviour of ReferenceType.instances, VirtualMachine.instanceCounts, ObjectReference.referringObjects
  32  *     in cases when object is reacheable via following types of references:
  33  *         - strong
  34  *         - soft
  35  *         - weak
  36  *         - phantom
  37  *         - jni local
  38  *         - jni global
  39  *         - jni weak
  40  *     Test is executed for following sublcasses of ObjectReference: StringReference, ThreadReference, ClassLoaderReference, ArrayReference.
  41  *     The test scenario is following:
  42  *     - Debugger VM
  43  *         for refererence_type in <Strong, JNI_Local_Ref, JNI_Global_Ref, JNI_Weak_Ref, PhantomReference, SoftReference, WeakReference>
  44  *         do
  45  *                 - initiate creation of referring objects of type 'refererence_type'
  46  *                 - check the number of referrers and instances is correct
  47  *                 - initiate deletion of some referreres(making them unreachable)
  48  *                 - check the number of referrers and instances is correct
  49  *         done
  50  *     - Debugger VM
  51  *         create references of all possible types to single object, ObjectReference.referringObjects should return only
  52  *         referrers with supported type(Strong, PhantomReference, SoftReference, WeakReference)
  53  *
  54  * @requires vm.gc != "Z"
  55  * @library /vmTestbase
  56  *          /test/lib
  57  * @run driver jdk.test.lib.FileInstaller . .
  58  * @build nsk.jdi.ObjectReference.referringObjects.referringObjects001.referringObjects001
  59  *        nsk.share.jdi.TestClass1
  60  * @run main/othervm/native PropertyResolvingWrapper
  61  *      nsk.jdi.ObjectReference.referringObjects.referringObjects001.referringObjects001
  62  *      -verbose
  63  *      -arch=${os.family}-${os.simpleArch}
  64  *      -waittime=5
  65  *      -debugee.vmkind=java
  66  *      -transport.address=dynamic
  67  *      "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}"
  68  */
  69 
  70 package nsk.jdi.ObjectReference.referringObjects.referringObjects001;
  71 
  72 import java.io.PrintStream;
  73 import java.util.*;
  74 
  75 import nsk.share.*;
  76 import nsk.share.jdi.*;
  77 
  78 
  79 import com.sun.jdi.*;
  80 import nsk.share.jpda.AbstractDebuggeeTest;
  81 
  82 public class referringObjects001 extends HeapwalkingDebugger {
  83 
  84     public static void main(String argv[]) {
  85         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
  86     }
  87 
  88     public static int run(String argv[], PrintStream out) {
  89         return new referringObjects001().runIt(argv, out);
  90         }
  91 
  92     protected String debuggeeClassName() {
  93         return nsk.share.jdi.HeapwalkingDebuggee.class.getName();
  94     }
  95 
  96     // test given class with all references types
  97     protected void testClass(String className) {
  98         log.display("Test ObjectReference for class: " + className);
  99 
 100         // force GC in debuggee VM to avoid collection of weak references during test execution
 101         forceGC();
 102 
 103         for (String referrerType : ObjectInstancesManager.allReferenceTypes) {
 104             testReferrerType(referrerType, className);
 105             if (ObjectInstancesManager.isWeak(referrerType)) {
 106                 resetStatusIfGC();
 107             }
 108         }
 109 
 110         int createInstanceCount = 10;
 111         List<ObjectReference> objectsToFilter = getObjectReferences(className, vm);
 112 
 113         // create instances reachable via all types of references
 114         pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_ALL_TYPE_REFERENCES + ":" + className + ":" + createInstanceCount);
 115 
 116         if (!isDebuggeeReady())
 117             return;
 118 
 119         // ObjectReference.referringObjects should include only supported types of references
 120         checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, createInstanceCount, true,
 121                 HeapwalkingDebuggee.includedIntoReferrersCountTypes.size());
 122 
 123         for (int i = 0; i < ObjectInstancesManager.allReferenceTypes.size(); i++) {
 124             pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + 1);
 125 
 126             if (!isDebuggeeReady())
 127                 return;
 128         }
 129     }
 130 
 131 
 132     protected void testReferrerType(String referrerType, String className) {
 133         // can't check number of referrers for objects that was created in debugee VM
 134         // before debugger command (for example primitive type arrays), so we should filter such objects
 135         List<ObjectReference> objectsToFilter = HeapwalkingDebugger.getObjectReferences(className, vm);
 136 
 137         boolean includedInReferrersCount = HeapwalkingDebuggee.isIncludedIntoReferrersCount(referrerType);
 138         boolean includedInInstancesCount = HeapwalkingDebuggee.isIncludedIntoInstancesCount(referrerType);
 139 
 140         int createInstanceCount = 4;
 141         int referrerCount = 10;
 142 
 143         // create 'createInstanceCount' instances with 'referrerCount' referrers
 144 
 145         pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + createInstanceCount + ":" + referrerCount + ":"
 146                 + referrerType);
 147 
 148         int expectedInstanceCount;
 149 
 150         if (includedInInstancesCount)
 151             expectedInstanceCount = createInstanceCount;
 152         else
 153             expectedInstanceCount = 0;
 154 
 155         // Note!
 156         // Test broken - assumes that no GC is run before heap walk.
 157         // G1 fails, just like ZGC, if en explicitly GC is done here.
 158         // forceGC();
 159 
 160         checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter);
 161         checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount);
 162 
 163         // delete half of referrers
 164 
 165         int deleteCount = referrerCount / 2;
 166 
 167         pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + deleteCount);
 168 
 169         referrerCount -= deleteCount;
 170 
 171         if (includedInInstancesCount)
 172             expectedInstanceCount = createInstanceCount;
 173         else
 174             expectedInstanceCount = 0;
 175 
 176         checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter);
 177         checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount);
 178 
 179         // delete half of instances
 180 
 181         deleteCount = createInstanceCount / 2;
 182         pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + deleteCount);
 183 
 184         createInstanceCount -= deleteCount;
 185 
 186         if (includedInInstancesCount)
 187             expectedInstanceCount = createInstanceCount;
 188         else
 189             expectedInstanceCount = 0;
 190 
 191         checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter);
 192         checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount);
 193 
 194         // delete all referrers (make object unreachable)
 195 
 196         deleteCount = referrerCount;
 197 
 198         pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + deleteCount);
 199 
 200         referrerCount = 0;
 201         createInstanceCount = 0;
 202 
 203         expectedInstanceCount = 0;
 204 
 205         checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter);
 206         checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount);
 207     }
 208 
 209     protected void checkDebugeeAnswer_instances_referringObjects(List<ObjectReference> objectsToFilter, String className, int expectedInstances,
 210             boolean checkReferrers, int expectedReferrers) {
 211         try {
 212             ReferenceType referenceType = debuggee.classByName(className);
 213 
 214             if (checkReferrers) {
 215                 List<ObjectReference> objectReferrences = HeapwalkingDebugger.filterObjectReferrence(objectsToFilter, referenceType.instances(0));
 216 
 217                 // used for non-strict check
 218                 int correctObjectsFound = 0;
 219 
 220                 for (ObjectReference objectReference : objectReferrences) {
 221                     int referrerCount = objectReference.referringObjects(0).size();
 222 
 223                     if (strictCheck(className)) {
 224                         if (referrerCount != expectedReferrers) {
 225                             setSuccess(false);
 226                             log.complain("List with wrong size was returned by ObjectReference.referringObjects: " + referrerCount + ", expected: "
 227                                     + expectedReferrers);
 228                         }
 229                     } else {
 230                         if (referrerCount == expectedReferrers) {
 231                             correctObjectsFound++;
 232                         }
 233                     }
 234                 }
 235 
 236                 if (!strictCheck(className)) {
 237                     if (correctObjectsFound != expectedInstances) {
 238                         setSuccess(false);
 239                         log.complain("List with wrong size was returned by ObjectReference.referringObjects, expected: " + expectedReferrers);
 240                     }
 241                 }
 242             }
 243         } catch (Throwable t) {
 244             log.complain("Unexpected exception:");
 245             t.printStackTrace(log.getOutStream());
 246         }
 247     }
 248 
 249     protected void doTest() {
 250         String[] testClassNames = { "java.lang.String", "nsk.share.jdi.TestClass1", "boolean[]",
 251                 "float[]" };
 252 
 253         for (String className : testClassNames) {
 254             testClass(className);
 255         }
 256     }
 257 }