1 /*
   2  * Copyright (c) 2001, 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 6496524
  27  *  @summary Setting breakpoint in jdb crashes Hotspot JVM
  28  *
  29  *  @author jjh
  30  *
  31  *  @modules jdk.jdi
  32  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  33  *  @run compile -g BreakpointTest.java
  34  *  @run driver BreakpointTest
  35  */
  36 import com.sun.jdi.*;
  37 import com.sun.jdi.event.*;
  38 import com.sun.jdi.request.*;
  39 
  40 import java.util.*;
  41 
  42 // The debuggee just runs in a loop. The debugger
  43 // sets a bkpt on the Math.random call.  When the
  44 // bkpt is hit, the debugger disables it, resumes
  45 // the debuggee, waits a bit, and enables the bkpt again.
  46 
  47 class BreakpointTarg {
  48     public final static int BKPT_LINE = 55;
  49             // LINE NUMBER SENSITIVE
  50 
  51     public static long count;
  52     static void doit() {
  53         Object[] roots = new Object[200000];
  54         while (true) {
  55             int index = (int) (Math.random() * roots.length); // BKPT_LINE
  56             // This println makes the test pass
  57             //System.out.println("Debuggee: index = " + index);
  58             roots[index] = new Object();   // bkpt here passes
  59                                            // and null instead of new Object()
  60                                            // passes
  61             count++;
  62         }
  63     }
  64 
  65     public static void main(String[] args) {
  66         doit();
  67     }
  68 }
  69 
  70     /********** test program **********/
  71 
  72 public class BreakpointTest extends TestScaffold {
  73     ClassType targetClass;
  74     ThreadReference mainThread;
  75 
  76     BreakpointTest (String args[]) {
  77         super(args);
  78     }
  79 
  80     public static void main(String[] args)      throws Exception {
  81         new BreakpointTest(args).startTests();
  82     }
  83 
  84     /********** event handlers **********/
  85 
  86     static int maxBkpts = 50;
  87     int bkptCount;
  88     BreakpointRequest bkptRequest;
  89     Field debuggeeCountField;
  90 
  91     // When we get a bkpt we want to disable the request,
  92     // resume the debuggee, and then re-enable the request
  93     public void breakpointReached(BreakpointEvent event) {
  94         System.out.println("Got BreakpointEvent: " + bkptCount +
  95                            ", debuggeeCount = " +
  96                            ((LongValue)targetClass.
  97                             getValue(debuggeeCountField)).value()
  98                            );
  99         bkptRequest.disable();
 100     }
 101 
 102     public void eventSetComplete(EventSet set) {
 103         set.resume();
 104 
 105         // The main thread watchs the bkptCount to
 106         // see if bkpts stop coming in.  The
 107         // test _should_ fail well before maxBkpts bkpts.
 108         if (bkptCount++ < maxBkpts) {
 109             try {
 110                 Thread.sleep(100);
 111             } catch (InterruptedException ee) {
 112             }
 113             bkptRequest.enable();
 114         }
 115     }
 116 
 117     public void vmDisconnected(VMDisconnectEvent event) {
 118         println("Got VMDisconnectEvent");
 119     }
 120 
 121     /********** test core **********/
 122 
 123     protected void runTests() throws Exception {
 124         /*
 125          * Get to the top of main()
 126          * to determine targetClass and mainThread
 127          */
 128         BreakpointEvent bpe = startToMain("BreakpointTarg");
 129         targetClass = (ClassType)bpe.location().declaringType();
 130         mainThread = bpe.thread();
 131         EventRequestManager erm = vm().eventRequestManager();
 132 
 133         Location loc1 = findLocation(
 134                             targetClass,
 135                             BreakpointTarg.BKPT_LINE);
 136 
 137         bkptRequest = erm.createBreakpointRequest(loc1);
 138         bkptRequest.enable();
 139         debuggeeCountField = targetClass.fieldByName("count");
 140         try {
 141 
 142             addListener (this);
 143         } catch (Exception ex){
 144             ex.printStackTrace();
 145             failure("failure: Could not add listener");
 146             throw new Exception("BreakpointTest: failed");
 147         }
 148 
 149         int prevBkptCount;
 150         vm().resume();
 151         while (!vmDisconnected && bkptCount < maxBkpts) {
 152             try {
 153                 Thread.sleep(5000);
 154             } catch (InterruptedException ee) {
 155             }
 156         }
 157 
 158         println("done with loop, final count = " +
 159                     ((LongValue)targetClass.
 160                      getValue(debuggeeCountField)).value());
 161         bkptRequest.disable();
 162         removeListener(this);
 163 
 164 
 165         /*
 166          * deal with results of test
 167          * if anything has called failure("foo") testFailed will be true
 168          */
 169         if (!testFailed) {
 170             println("BreakpointTest: passed");
 171         } else {
 172             throw new Exception("BreakpointTest: failed");
 173         }
 174     }
 175 }