| /* |
| * 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) |
| * |
| * @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"); |
| } |
| } |
| } |