/* * Copyright (c) 1999, 2015, 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. */ /** * @test * @bug 4272800 4274208 4392010 * @summary Test debugger operations in finalize() methods * @author Gordon Hirsch (modified for HotSpot by tbell & rfield) * * @modules jdk.jdi * @run build TestScaffold VMConnection TargetListener TargetAdapter * @run compile -g FinalizerTest.java * * @run driver FinalizerTest */ import com.sun.jdi.*; import com.sun.jdi.event.*; import com.sun.jdi.request.*; import java.util.List; import java.util.ArrayList; import java.util.Iterator; /* * Debuggee which exercises a finalize() method. There's no guarantee * that this will work, but we need some way of attempting to test * the debugging of finalizers. * @author Gordon Hirsch (modified for HotSpot by tbell & rfield) */ class FinalizerTarg { static String lockit = "lock"; static boolean finalizerRun = false; static class BigObject { String name; byte[] foo = new byte[300000]; public BigObject (String _name) { super(); this.name = _name; } protected void finalize() throws Throwable { /* * JLS 2nd Ed. section 12.6 "Finalization of Class Instances" "[...] * invoke the finalize method for its superclass, [...] usually good * practice [...]" */ super.finalize(); //Thread.dumpStack(); finalizerRun = true; } } static void waitForAFinalizer() { String s = Integer.toString(1); BigObject b = new BigObject (s); b = null; // Drop the object, creating garbage... System.gc(); System.runFinalization(); // Now, we have to make sure the finalizer // gets run. We will keep allocating more // and more memory with the idea that eventually, // the memory occupied by the BigObject will get reclaimed // and the finalizer will be run. List holdAlot = new ArrayList(); for (int chunk=10000000; chunk > 10000; chunk = chunk / 2) { if (finalizerRun) { return; } try { while(true) { holdAlot.add(new byte[chunk]); System.err.println("Allocated " + chunk); } } catch ( Throwable thrown ) { // OutOfMemoryError System.gc(); } System.runFinalization(); } return; // not reached } public static void main(String[] args) throws Exception { /* * Spin in waitForAFinalizer() while waiting for * another thread to run the finalizer on one of the * BigObjects ... */ waitForAFinalizer(); } } ///// End of debuggee public class FinalizerTest extends TestScaffold { public static void main(String args[]) throws Exception { new FinalizerTest (args).startTests(); } public FinalizerTest (String args[]) { super(args); } protected void runTests() throws Exception { try { BreakpointEvent event0 = startToMain("FinalizerTarg"); BreakpointEvent event1 = resumeTo("FinalizerTarg$BigObject", "finalize", "()V"); println("Breakpoint at " + event1.location().method().name() + ":" + event1.location().lineNumber() + " (" + event1.location().codeIndex() + ")"); /* * Record information about the current location */ List frames = event1.thread().frames(); List methodStack = new ArrayList(frames.size()); Iterator iter = frames.iterator(); while (iter.hasNext()) { StackFrame frame = (StackFrame) iter.next(); methodStack.add(frame.location().declaringType().name() + "." + frame.location().method().name()); } println("Try a stepOverLine()..."); StepEvent stepEvent = stepOverLine(event1.thread()); println("Step Complete at " + stepEvent.location().method().name() + ":" + stepEvent.location().lineNumber() + " (" + stepEvent.location().codeIndex() + ")"); /* * Compare current location with recorded location */ if (stepEvent.thread().frameCount() != methodStack.size()) { throw new Exception("Stack depths do not match: original=" + methodStack.size() + ", current=" + stepEvent.thread().frameCount()); } iter = stepEvent.thread().frames().iterator(); Iterator iter2 = methodStack.iterator(); while (iter.hasNext()) { StackFrame frame = (StackFrame) iter.next(); String name = (String) iter2.next(); String currentName = frame.location().declaringType().name() + "." + frame.location().method().name(); if (!name.equals(currentName)) { throw new Exception("Stacks do not match at: original=" + name + ", current=" + currentName); } } } catch(Exception ex) { ex.printStackTrace(); testFailed = true; } finally { // Allow application to complete and shut down listenUntilVMDisconnect(); } if (!testFailed) { println("FinalizerTest: passed"); } else { throw new Exception("FinalizerTest: failed"); } } }