1 /*
   2  * Copyright (c) 1999, 2015, 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  * @bug 4272800 4274208 4392010
  27  * @summary Test debugger operations in finalize() methods
  28  * @author Gordon Hirsch  (modified for HotSpot by tbell & rfield)
  29  *
  30  * @run build TestScaffold VMConnection TargetListener TargetAdapter
  31  * @run compile -g FinalizerTest.java
  32  *
  33  * @run driver FinalizerTest
  34  */
  35 import com.sun.jdi.*;
  36 import com.sun.jdi.event.*;
  37 import com.sun.jdi.request.*;
  38 
  39 import java.util.List;
  40 import java.util.ArrayList;
  41 import java.util.Iterator;
  42 
  43 
  44 /*
  45  * Debuggee which exercises a finalize() method. There's no guarantee
  46  * that this will work, but we need some way of attempting to test
  47  * the debugging of finalizers.
  48  * @author Gordon Hirsch  (modified for HotSpot by tbell & rfield)
  49  */
  50 class FinalizerTarg {
  51     static String lockit = "lock";
  52     static boolean finalizerRun = false;
  53     static class BigObject {
  54         String name;
  55         byte[] foo = new byte[300000];
  56 
  57         public BigObject (String _name) {
  58             super();
  59             this.name = _name;
  60         }
  61 
  62         protected void finalize() throws Throwable {
  63             /*
  64              * JLS 2nd Ed. section 12.6 "Finalization of Class Instances" "[...]
  65              * invoke the finalize method for its superclass, [...] usually good
  66              * practice [...]"
  67              */
  68             super.finalize();
  69             //Thread.dumpStack();
  70             finalizerRun = true;
  71         }
  72     }
  73 
  74     static void waitForAFinalizer() {
  75         String s = Integer.toString(1);
  76         BigObject b = new BigObject (s);
  77         b = null; // Drop the object, creating garbage...
  78         System.gc();
  79         System.runFinalization();
  80 
  81         // Now, we have to make sure the finalizer
  82         // gets run.  We will keep allocating more
  83         // and more memory with the idea that eventually,
  84         // the memory occupied by the BigObject will get reclaimed
  85         // and the finalizer will be run.
  86         List holdAlot = new ArrayList();
  87         for (int chunk=10000000; chunk > 10000; chunk = chunk / 2) {
  88             if (finalizerRun) {
  89                 return;
  90             }
  91             try {
  92                 while(true) {
  93                     holdAlot.add(new byte[chunk]);
  94                     System.err.println("Allocated " + chunk);
  95                 }
  96             }
  97             catch ( Throwable thrown ) {  // OutOfMemoryError
  98                 System.gc();
  99             }
 100             System.runFinalization();
 101         }
 102         return;  // not reached
 103     }
 104 
 105     public static void main(String[] args) throws Exception {
 106         /*
 107          * Spin in waitForAFinalizer() while waiting for
 108          * another thread to run the finalizer on one of the
 109          * BigObjects ...
 110          */
 111         waitForAFinalizer();
 112     }
 113 }
 114 ///// End of debuggee
 115 
 116 
 117 public class FinalizerTest extends TestScaffold {
 118 
 119     public static void main(String args[])
 120         throws Exception {
 121         new FinalizerTest (args).startTests();
 122     }
 123 
 124     public FinalizerTest (String args[]) {
 125         super(args);
 126     }
 127 
 128     protected void runTests() throws Exception {
 129         try {
 130             BreakpointEvent event0 = startToMain("FinalizerTarg");
 131 
 132             BreakpointEvent event1 = resumeTo("FinalizerTarg$BigObject",
 133                                               "finalize", "()V");
 134 
 135             println("Breakpoint at " +
 136                     event1.location().method().name() + ":" +
 137                     event1.location().lineNumber() + " (" +
 138                     event1.location().codeIndex() + ")");
 139 
 140             /*
 141              * Record information about the current location
 142              */
 143             List frames = event1.thread().frames();
 144             List methodStack = new ArrayList(frames.size());
 145             Iterator iter = frames.iterator();
 146             while (iter.hasNext()) {
 147                 StackFrame frame = (StackFrame) iter.next();
 148                 methodStack.add(frame.location().declaringType().name() +
 149                                 "." + frame.location().method().name());
 150             }
 151             println("Try a stepOverLine()...");
 152             StepEvent stepEvent = stepOverLine(event1.thread());
 153 
 154             println("Step Complete at " +
 155                                stepEvent.location().method().name() + ":" +
 156                                stepEvent.location().lineNumber() + " (" +
 157                                stepEvent.location().codeIndex() + ")");
 158 
 159             /*
 160              * Compare current location with recorded location
 161              */
 162             if (stepEvent.thread().frameCount() != methodStack.size()) {
 163                 throw new Exception("Stack depths do not match: original=" +
 164                                     methodStack.size() +
 165                                     ", current=" +
 166                                     stepEvent.thread().frameCount());
 167             }
 168             iter = stepEvent.thread().frames().iterator();
 169             Iterator iter2 = methodStack.iterator();
 170             while (iter.hasNext()) {
 171                 StackFrame frame = (StackFrame) iter.next();
 172                 String name = (String) iter2.next();
 173                 String currentName = frame.location().declaringType().name() +
 174                 "." + frame.location().method().name();
 175                 if (!name.equals(currentName)) {
 176                     throw new Exception("Stacks do not match at: original=" +
 177                                          name + ", current=" + currentName);
 178 
 179                 }
 180             }
 181         } catch(Exception ex) {
 182             ex.printStackTrace();
 183             testFailed = true;
 184         } finally {
 185             // Allow application to complete and shut down
 186             listenUntilVMDisconnect();
 187         }
 188         if (!testFailed) {
 189             println("FinalizerTest: passed");
 190         } else {
 191             throw new Exception("FinalizerTest: failed");
 192         }
 193     }
 194 }