jdk/test/com/sun/jdi/ReferrersTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /**
       
    25  *  @test
       
    26  *  @bug 5089849
       
    27  *  @summary Add support for backtracking reference graph.
       
    28  *  @author jjh
       
    29  *
       
    30  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
       
    31  *  @run compile -g ReferrersTest.java
       
    32  *  @run main ReferrersTest
       
    33  */
       
    34 
       
    35 /*
       
    36  *  To run this test do this:
       
    37  *     runregress -no ReferrersTest <cmd line options>
       
    38  *
       
    39  *  where <cmd line options> are the options to be used to
       
    40  *  launch the debuggee, with the classname prefixed with @@.
       
    41  *  For example, this would run java2d demo as the debuggee:
       
    42  *     runregress -no ReferrersTest -classpath
       
    43  *                                    $jdkDir/demo/jfc/Java2D/Java2Demo.jar \
       
    44  *                                    -client @@java2d.Java2Demo
       
    45  *
       
    46  * In this mode, the specified debuggee is launched in debug mode,
       
    47  * and the debugger waits for a keystroke before connecting to the debuggee.
       
    48  *
       
    49  * If <cmd line options> is not specified, then the ReferrersTarg class below
       
    50  * is run as the debuggee.
       
    51  */
       
    52 import com.sun.jdi.*;
       
    53 import com.sun.jdi.event.*;
       
    54 import com.sun.jdi.request.*;
       
    55 
       
    56 import java.util.*;
       
    57 
       
    58 class ReferrersFiller {
       
    59     // This many instances of this are created.
       
    60     static int FILLER_COUNT = 20000;
       
    61     static ReferrersFiller[] lotsAndLots = new ReferrersFiller[
       
    62                                                ReferrersFiller.FILLER_COUNT];
       
    63     int xx;
       
    64     ReferrersFiller(int p1) {
       
    65         xx = p1;
       
    66     }
       
    67 }
       
    68 
       
    69 class ReferrersTarg {
       
    70     // This many instances + 1 of this class are created.
       
    71     static int TARG_COUNT = 10;
       
    72     static ReferrersTarg theReferrersTarg;
       
    73     static ReferrersTarg[] allReferrersTargs;
       
    74 
       
    75     // Each instance will point to the theReferrersTarg
       
    76     ReferrersTarg oneReferrersTarg;
       
    77 
       
    78     public static void bkpt() {
       
    79     }
       
    80 
       
    81     public static void main(String[] args) {
       
    82         System.out.println("Howdy!");
       
    83         for (int ii = 0; ii < ReferrersFiller.lotsAndLots.length; ii++) {
       
    84             ReferrersFiller.lotsAndLots[ii] = new ReferrersFiller(ii);
       
    85         }
       
    86 
       
    87         theReferrersTarg = new ReferrersTarg();
       
    88         allReferrersTargs = new ReferrersTarg[ReferrersTarg.TARG_COUNT];
       
    89         for (int ii = 0; ii < ReferrersTarg.TARG_COUNT; ii++) {
       
    90             allReferrersTargs[ii] = new ReferrersTarg();
       
    91             allReferrersTargs[ii].oneReferrersTarg = theReferrersTarg;
       
    92         }
       
    93         bkpt();
       
    94 
       
    95         System.out.println("Goodbye from ReferrersTarg!");
       
    96     }
       
    97 }
       
    98 
       
    99 /********** test program **********/
       
   100 
       
   101 public class ReferrersTest extends TestScaffold {
       
   102     static String targetName = "ReferrersTarg";
       
   103     ReferenceType targetClass;
       
   104     ThreadReference mainThread;
       
   105 
       
   106     ReferrersTest(String args[]) {
       
   107         super(args);
       
   108     }
       
   109 
       
   110     public static void main(String[] args) throws Exception {
       
   111         /*
       
   112          * If args contains @@xxxx, then that is the
       
   113          * name of the class we are to run.
       
   114          */
       
   115         for (int ii = 0; ii < args.length; ii ++) {
       
   116             if (args[ii].startsWith("@@")) {
       
   117                 targetName = args[ii] = args[ii].substring(2);
       
   118                 break;
       
   119             }
       
   120         }
       
   121         new ReferrersTest(args).startTests();
       
   122     }
       
   123 
       
   124     /*
       
   125      * Used to sort a list of ReferenceTypes by
       
   126      * instance count.
       
   127      */
       
   128     class ToSort implements Comparable<ToSort> {
       
   129         long count;
       
   130         ReferenceType rt;
       
   131 
       
   132         public ToSort(long count, ReferenceType rt) {
       
   133             this.count = count;
       
   134             this.rt = rt;
       
   135         }
       
   136 
       
   137         public int compareTo(ToSort obj) {
       
   138             if (count < obj.count) return -1;
       
   139             if (count == obj.count) return 0;
       
   140             return 1;
       
   141         }
       
   142     }
       
   143 
       
   144     protected void runTests() throws Exception {
       
   145         /*
       
   146          * Get to the top of main()
       
   147          * to determine targetClass and mainThread
       
   148          */
       
   149         int CUT_OFF = 1000;
       
   150         BreakpointEvent bpe;
       
   151         bpe = startToMain(targetName);
       
   152         targetClass = bpe.location().declaringType();
       
   153         mainThread = bpe.thread();
       
   154 
       
   155         if (targetName.equals("ReferrersTarg")) {
       
   156             resumeTo("ReferrersTarg", "bkpt", "()V");
       
   157         } else {
       
   158             // Let debuggee run for awhile to get classes loaded
       
   159             vm().resume();
       
   160             try {
       
   161                 System.err.println("Press <enter> to continue");
       
   162                 System.in.read();
       
   163                 System.err.println("running...");
       
   164 
       
   165             } catch(Exception e) {
       
   166             }
       
   167             vm().suspend();
       
   168         }
       
   169 
       
   170         // Get all classes.
       
   171         long start = System.currentTimeMillis();
       
   172         List<ReferenceType> allClasses = vm().allClasses();
       
   173         long end = System.currentTimeMillis();
       
   174         System.out.println( allClasses.size() +
       
   175                             " classes from vm.allClasses() took " +
       
   176                             (end - start) + " ms");
       
   177 
       
   178         long[] counts;
       
   179 
       
   180         // Test for NPE
       
   181         {
       
   182             boolean pass = false;
       
   183             try {
       
   184                 counts = vm().instanceCounts(null);
       
   185             } catch (NullPointerException ee) {
       
   186                 pass = true;
       
   187             }
       
   188             if (!pass) {
       
   189                 failure("failure: NullPointerException not thrown on instanceCounts(null)");
       
   190             }
       
   191         }
       
   192 
       
   193         // Test for 0 length array
       
   194         {
       
   195             List<ReferenceType>someClasses = new ArrayList(2);
       
   196             counts = vm().instanceCounts(someClasses);
       
   197             if (counts.length != 0) {
       
   198                 failure("failure: instanceCounts with a zero length array fails: " +
       
   199                         counts.length);
       
   200             }
       
   201         }
       
   202 
       
   203         // Test various values of maxInstances
       
   204         if (targetClass.name().equals("ReferrersTarg")) {
       
   205             List<ObjectReference> noInstances = targetClass.instances(0);
       
   206             if (noInstances.size() != ReferrersTarg.TARG_COUNT + 1) {
       
   207                 failure("failure: instances(0): " + noInstances.size() + ", for " + targetClass);
       
   208             }
       
   209             noInstances = targetClass.instances(1);
       
   210             if (noInstances.size() != 1) {
       
   211                 failure("failure: instances(1): " + noInstances.size() + ", for " + targetClass);
       
   212             }
       
   213             boolean pass = false;
       
   214             try {
       
   215                 noInstances = targetClass.instances(-1);
       
   216             } catch (IllegalArgumentException ee) {
       
   217                 pass = true;
       
   218             }
       
   219             if (!pass) {
       
   220                 failure("failure: instances(-1) did not get an exception");
       
   221             }
       
   222         }
       
   223 
       
   224         // Instance counts for all classes
       
   225         start = System.currentTimeMillis();
       
   226         counts = vm().instanceCounts(allClasses);
       
   227         end = System.currentTimeMillis();
       
   228 
       
   229         if (counts.length == 0) {
       
   230             System.out.println("failure: No instances found");
       
   231             throw new Exception("ReferrersTest: failed");
       
   232         }
       
   233 
       
   234         // Create a list of ReferenceTypes sorted by instance count
       
   235         int size = 0;
       
   236         List<ToSort> sorted = new ArrayList(allClasses.size());
       
   237         for (int ii = 0; ii < allClasses.size(); ii++) {
       
   238             size += counts[ii];
       
   239             ToSort tos = new ToSort(counts[ii], allClasses.get(ii));
       
   240             sorted.add(tos);
       
   241         }
       
   242 
       
   243         System.out.println("instance counts for " + counts.length +
       
   244                            " classes got " + size + " instances and took " +
       
   245                             (end - start) + " ms");
       
   246 
       
   247 
       
   248         boolean gotReferrersFiller = false;
       
   249         boolean gotReferrersTarg = false;
       
   250 
       
   251         Collections.sort(sorted);
       
   252         for (int ii = sorted.size() - 1; ii >= 0 ; ii--) {
       
   253             ToSort xxx = sorted.get(ii);
       
   254 
       
   255             if (xxx.rt.name().equals("ReferrersFiller") &&
       
   256                 xxx.count == ReferrersFiller.FILLER_COUNT) {
       
   257                 gotReferrersFiller = true;
       
   258             }
       
   259             if (xxx.rt.name().equals("ReferrersTarg") &&
       
   260                 xxx.count == ReferrersTarg.TARG_COUNT + 1) {
       
   261                 gotReferrersTarg = true;
       
   262             }
       
   263         }
       
   264         if (!gotReferrersFiller) {
       
   265             failure("failure: Expected " + ReferrersFiller.FILLER_COUNT +
       
   266                         " instances of ReferrersFiller");
       
   267         }
       
   268         if (!gotReferrersTarg) {
       
   269             failure("failure: Expected " + (ReferrersTarg.TARG_COUNT + 1) +
       
   270                     " instances of ReferrersTarg");
       
   271         }
       
   272 
       
   273         List<List<ObjectReference>> allInstances = new ArrayList(10);
       
   274 
       
   275         // Instances, one class at a time, in sorted order, printing each line
       
   276         if (true) {
       
   277             System.out.println("\nGetting instances for one class " +
       
   278                                "at a time (limited) in sorted order");
       
   279             List<ReferenceType> rtList = new ArrayList(1);
       
   280             rtList.add(null);
       
   281             long start1 = System.currentTimeMillis();
       
   282             size = 0;
       
   283             long count = 0;
       
   284             for (int ii = sorted.size() - 1; ii >= 0 ; ii--) {
       
   285                 ToSort xxx = sorted.get(ii);
       
   286                 if (xxx.count <= CUT_OFF) {
       
   287                     break;
       
   288                 }
       
   289                 rtList.set(0, xxx.rt);
       
   290                 start = System.currentTimeMillis();
       
   291                 List<ObjectReference> oneInstances = xxx.rt.instances(19999999);
       
   292                 end = System.currentTimeMillis();
       
   293                 size += oneInstances.size();
       
   294                 count++;
       
   295                 System.out.println("Expected " + xxx.count + " instances, got " +
       
   296                                    oneInstances.size() +
       
   297                                    " instances for " + sorted.get(ii).rt +
       
   298                                    " in " + (end - start) + " ms");
       
   299 
       
   300                 if (xxx.rt.name().equals("ReferrersFiller") &&
       
   301                     oneInstances.size() != ReferrersFiller.FILLER_COUNT) {
       
   302                     failure("failure: Expected " + ReferrersFiller.FILLER_COUNT +
       
   303                             " instances of ReferrersFiller");
       
   304                 }
       
   305                 if (xxx.rt.name().equals("ReferrersTarg") &&
       
   306                     oneInstances.size() != ReferrersTarg.TARG_COUNT + 1) {
       
   307                     failure("failure: Expected " + (ReferrersTarg.TARG_COUNT + 1) +
       
   308                             " instances of ReferrersTarg");
       
   309                 }
       
   310                 allInstances.add(oneInstances);
       
   311             }
       
   312 
       
   313             end = System.currentTimeMillis();
       
   314 
       
   315             System.out.println(size + " instances via making one vm.instances" +
       
   316                                " call for each of " + count +
       
   317                                " classes took " + (end - start1) + " ms");
       
   318             System.out.println("Per class = " +
       
   319                                (end - start) / allClasses.size() + " ms");
       
   320         }
       
   321 
       
   322 
       
   323         // referrers
       
   324 
       
   325         // Test various values of maxReferrers
       
   326         if (targetClass.name().equals("ReferrersTarg")) {
       
   327             Field field1 = targetClass.fieldByName("theReferrersTarg");
       
   328             ObjectReference anInstance = (ObjectReference)targetClass.getValue(field1);
       
   329             List<ObjectReference> noReferrers = anInstance.referringObjects(0);
       
   330             if (noReferrers.size() != ReferrersTarg.TARG_COUNT + 1 ) {
       
   331                 failure("failure: referringObjects(0) got " + noReferrers.size() +
       
   332                         ", for " + anInstance);
       
   333             }
       
   334             noReferrers = anInstance.referringObjects(1);
       
   335             if (noReferrers.size() != 1 ) {
       
   336                 failure("failure: referringObjects(1) got " + noReferrers.size() +
       
   337                         ", for " + anInstance);
       
   338             }
       
   339             boolean pass = false;
       
   340             try {
       
   341                 noReferrers = anInstance.referringObjects(-1);
       
   342             } catch (IllegalArgumentException ee) {
       
   343                 pass = true;
       
   344             }
       
   345             if (!pass) {
       
   346                 failure("failure: referringObjects(-1) did not get an exception");
       
   347             }
       
   348         }
       
   349 
       
   350         List<ObjectReference> allReferrers = null;
       
   351         List<ObjectReference> someInstances = new ArrayList();
       
   352         if (targetName.equals("ReferrersTarg")) {
       
   353             Field field1 = targetClass.fieldByName("theReferrersTarg");
       
   354             ObjectReference val = (ObjectReference)targetClass.getValue(field1);
       
   355             someInstances.add(val);
       
   356             allReferrers = val.referringObjects(99999);  //LIMIT
       
   357             if (allReferrers.size() != ReferrersTarg.TARG_COUNT + 1) {
       
   358                 failure("failure: expected " + (ReferrersTarg.TARG_COUNT + 1) +
       
   359                         "referrers, but got " + allReferrers.size() +
       
   360                         " referrers for " + val);
       
   361             }
       
   362         } else {
       
   363             // referrers
       
   364             // Create someInstances to find the referrers of.
       
   365             for (int ii = 0; ii < allClasses.size(); ii++) {
       
   366                 List<ObjectReference> objRefList = allInstances.get(ii);
       
   367                 if (objRefList != null) {
       
   368                     int asize = objRefList.size();
       
   369                     if (false) {
       
   370                         System.out.println(asize + ", " + allClasses.get(ii));
       
   371                     }
       
   372                     // Remember one instance per class to get referrers
       
   373                     if (asize > 0) {
       
   374                         someInstances.add(objRefList.get(0));
       
   375                     }
       
   376                 }
       
   377             }
       
   378         }
       
   379 
       
   380         for (ObjectReference objRef: someInstances) {
       
   381             //System.out.println( "Getting referrers for " + objRef);
       
   382             start = System.currentTimeMillis();
       
   383             if ( true) {
       
   384                 showReferrers(objRef, 0, 0, 0);
       
   385             } else {
       
   386                 allReferrers = objRef.referringObjects(99999);  //LIMIT
       
   387                 end = System.currentTimeMillis();
       
   388                 if (true || allReferrers.size() > 1) {
       
   389                     System.out.println( allReferrers.size() + " referrers for " + objRef + " took " + (end - start) + " ms");
       
   390                 }
       
   391             }
       
   392         }
       
   393 
       
   394         /*
       
   395          * deal with results of test
       
   396          * if anything has called failure("foo") testFailed will be true
       
   397          */
       
   398         if (!testFailed) {
       
   399             println("ReferrersTest: passed");
       
   400         } else {
       
   401             throw new Exception("ReferrersTest: failed");
       
   402         }
       
   403     }
       
   404     void indent(int level) {
       
   405         for (int ii = 0; ii < level; ii++) {
       
   406             System.out.print("    ");
       
   407         }
       
   408     }
       
   409 
       
   410 
       
   411     Map<ObjectReference, Object> visited = new HashMap(100);
       
   412     void showReferrers(ObjectReference objRef, int level, int total, int which) {
       
   413 
       
   414         if (level == 0) {
       
   415             visited.clear();
       
   416         } else {
       
   417             if (visited.containsKey(objRef)) {
       
   418                 indent(level);
       
   419                 System.out.println("(" + which + ")" + ":<pruned> " + objRef);
       
   420                 return;
       
   421             }
       
   422             visited.put(objRef, null);
       
   423             indent(level);
       
   424             //System.out.println(which + "/" + total + ": " + objRef + " took " + time + " ms");
       
   425         }
       
   426 
       
   427         List<ObjectReference> allReferrers = null;
       
   428 
       
   429         //System.out.println( "Getting referrers for " + objRef);
       
   430         long start, end;
       
   431         start = System.currentTimeMillis();
       
   432         allReferrers = objRef.referringObjects(99999);  //LIMIT
       
   433         end = System.currentTimeMillis();
       
   434 
       
   435         if (which == 0) {
       
   436             System.out.println(allReferrers.size() + " referrers for " + objRef + " took " + (end - start) + " ms");
       
   437         } else {
       
   438             System.out.println("(" + which + ") "  + objRef);
       
   439             indent(level);
       
   440             System.out.println("    " + allReferrers.size() + " referrers for " + objRef + " took " + (end - start) + " ms");
       
   441         }
       
   442 
       
   443         // We have to stop going up a referrer chain in some cases
       
   444         Type rt = objRef.type();
       
   445         if (rt instanceof ClassType) {
       
   446             ClassType ct = (ClassType)rt;
       
   447             String name = ct.name();
       
   448             if (name.equals("sun.misc.SoftCache$ValueCell")) {
       
   449                 return;
       
   450             }
       
   451             if (name.equals("java.lang.ref.Finalizer")) {
       
   452                 return;
       
   453             }
       
   454             if (name.equals("java.lang.ref.SoftReference")) {
       
   455                 return;
       
   456             }
       
   457             // oh oh, should really check for a subclass of ClassLoader :-)
       
   458             if (name.indexOf("ClassLoader") >= 0) {
       
   459                 return;
       
   460             }
       
   461             // No doubt there are other reasons to stop ...
       
   462         }
       
   463         int itemNumber = 1;
       
   464         int allSize = allReferrers.size();
       
   465         for (ObjectReference objx: allReferrers) {
       
   466             showReferrers(objx, level + 1, allSize, itemNumber++);
       
   467         }
       
   468     }
       
   469 }