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