1 /*
   2  * Copyright (c) 2001, 2002, 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 4446677
  27  *  @summary debuggee crashes when debugging under jbuilder
  28  *
  29  *  @author jjh
  30  *
  31  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  32  *  @run compile -g BacktraceFieldTest.java
  33  *  @run driver BacktraceFieldTest
  34  */
  35 
  36 /*
  37  * The fix for this bug filters out the backtrace field from the list
  38  * of fields for java.lang.Throwable.
  39  * This test verifies that this really happens, and also verifies that the fix
  40  * doesn't incorrectly discard other fields.
  41  */
  42 
  43 import com.sun.jdi.*;
  44 import com.sun.jdi.event.*;
  45 import com.sun.jdi.request.*;
  46 
  47 import java.util.*;
  48 
  49 /********** target program **********/
  50 
  51 class Testy {
  52     /*
  53      * This is used to verify that the fix doesn't filter out fields that it
  54      * shouldn't.  7 is an abitrary number, and this isn't a definitive
  55      * test; the fix could conceivably filter out the 89th field of a class
  56      * named Foo.
  57      * To verify that this part of this test works, first uncomment the field8
  58      * line and verify that the test fails, and then rename a field to xxx and
  59      * verify that the test fails.
  60      */
  61     int field1;
  62     int field2;
  63     int field3;
  64     int field4;
  65     int field5;
  66     int field6;
  67     final static int field7 = 7;  // Value is the number of fields.
  68     //int field8;
  69 
  70     Testy() {
  71     }
  72 }
  73 
  74 
  75 class BacktraceFieldTarg {
  76     public static void gus() {
  77     }
  78 
  79     public static void main(String[] args) {
  80         Testy myTesty = new Testy();
  81         try {
  82             throw new RuntimeException("jjException");
  83         } catch (Exception ee) {
  84             gus();
  85             System.out.println("debuggee: Exception: " + ee);
  86         }
  87     }
  88 }
  89 
  90 /********** test program **********/
  91 
  92 public class BacktraceFieldTest extends TestScaffold {
  93     ThreadReference mainThread;
  94 
  95     BacktraceFieldTest (String args[]) {
  96         super(args);
  97     }
  98 
  99     public static void main(String[] args)      throws Exception {
 100         new BacktraceFieldTest(args).startTests();
 101     }
 102 
 103     /********** test core **********/
 104 
 105     protected void runTests() throws Exception {
 106         /*
 107          * Get to the top of gus()
 108          * to determine mainThread
 109          */
 110         BreakpointEvent bpe = startTo("BacktraceFieldTarg", "gus", "()V");
 111         mainThread = bpe.thread();
 112 
 113         /*
 114          * We are now one frame below the exception frame that contains
 115          * our ee var.
 116          */
 117         StackFrame myFrame = mainThread.frame(1);
 118 
 119         LocalVariable lv = myFrame.visibleVariableByName("ee");
 120         println("BT: lv = " + lv);
 121         println("BT: lvType = " + lv.typeName());
 122 
 123         List allFields = ((ReferenceType)(lv.type())).allFields();
 124         println("BT: allFields = " + allFields);
 125 
 126         /*
 127          * Search through the fields of ee to verify that
 128          * java.lang.Throwable.backtrace isn't there.
 129          */
 130         Iterator iter = allFields.iterator();
 131         while(iter.hasNext()) {
 132             Field ff = (Field)iter.next();
 133             if (ff.toString().equals("java.lang.Throwable.backtrace")) {
 134                 failure("ERROR: java.lang.Throwable.backtrace field not filtered out.");
 135 
 136                 /*
 137                  * If you want to experience the segv this bug causes, change
 138                  * this test to 1 == 1 and run it with jdk 1.4, build 74 or earlier
 139                  */
 140                 if (1 == 0) {
 141                     // The following code will show the segv that this can cause.
 142                     ObjectReference myVal = (ObjectReference)myFrame.getValue(lv);
 143                     println("BT: myVal = " + myVal);
 144 
 145                     ArrayReference backTraceVal = null;
 146                     backTraceVal = (ArrayReference)myVal.getValue(ff);
 147                     println("BT: backTraceVal = " + backTraceVal);
 148 
 149                     ArrayReference secondVal = (ArrayReference)backTraceVal.getValue(1);
 150                     println("BT: secondVal = " + secondVal);
 151 
 152                     Object x2Val = (Object)secondVal.getValue(0);
 153                     println("BT: x2Val = " + x2Val);
 154 
 155                     ArrayReference firstVal = (ArrayReference)backTraceVal.getValue(0);
 156                     println("BT: firstVal = " + firstVal);
 157 
 158                     // The segv happens here.
 159                     Object xVal = (Object)firstVal.getValue(0);
 160                     println("BT: xVal = " + xVal);
 161                 }
 162                 break;
 163             }
 164         }
 165 
 166         // Next, verify that we don't accidently discard a field that we shouldn't
 167 
 168         if (!testFailed) {
 169             lv = myFrame.visibleVariableByName("myTesty");
 170 
 171             allFields = ((ReferenceType)(lv.type())).allFields();
 172             println("BT: allFields = " + allFields);
 173 
 174             if (allFields.size() != Testy.field7) {
 175                 failure("ERROR: wrong number of fields; expected " + Testy.field7 + ", Got " + allFields.size());
 176             } else {
 177                 iter = allFields.iterator();
 178                 while(iter.hasNext()) {
 179                     String fieldName = ((Field)iter.next()).toString();
 180                     if (!fieldName.startsWith("Testy.field", 0)) {
 181                         failure("ERROR: Found bogus field: " + fieldName.toString());
 182                     }
 183                 }
 184             }
 185         }
 186 
 187         listenUntilVMDisconnect();
 188 
 189         /*
 190          * deal with results of test
 191          * if anything has called failure("foo") testFailed will be true
 192          */
 193         if (!testFailed) {
 194             println("BacktraceFieldTest: passed");
 195         } else {
 196             throw new Exception("BacktraceFieldTest: failed");
 197         }
 198     }
 199 }