1/*
2 * Copyright (c) 2001, 2016, 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 * @bug 8158237
28 * @summary debuggee used to crash when debugging under jbuilder
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
43import com.sun.jdi.*;
44import com.sun.jdi.event.*;
45import com.sun.jdi.request.*;
46
47import java.util.*;
48
49/********** target program **********/
50
51class 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
75class 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
92public 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    private void printval(ArrayReference backTraceVal, int index) throws Exception {
104        ArrayReference val = (ArrayReference)backTraceVal.getValue(index);
105        println("BT: val at " + index + " = " + val);
106
107        // The segv used to happen here for index = 0
108        // Now all objects in the backtrace are objects.
109        Object xVal = (Object)val.getValue(0);
110        println("BT: xVal = " + xVal);
111    }
112
113    /********** test core **********/
114
115    protected void runTests() throws Exception {
116        /*
117         * Get to the top of gus()
118         * to determine mainThread
119         */
120        BreakpointEvent bpe = startTo("BacktraceFieldTarg", "gus", "()V");
121        mainThread = bpe.thread();
122
123        /*
124         * We are now one frame below the exception frame that contains
125         * our ee var.
126         */
127        StackFrame myFrame = mainThread.frame(1);
128
129        LocalVariable lv = myFrame.visibleVariableByName("ee");
130        println("BT: lv = " + lv);
131        println("BT: lvType = " + lv.typeName());
132
133        List allFields = ((ReferenceType)(lv.type())).allFields();
134        println("BT: allFields = " + allFields);
135
136        /*
137         * Search through the fields of ee to verify that
138         * java.lang.Throwable.backtrace isn't there.
139         */
140        boolean backtrace_found = false;
141        Iterator iter = allFields.iterator();
142        while(iter.hasNext()) {
143            Field ff = (Field)iter.next();
144            if (ff.toString().equals("java.lang.Throwable.backtrace")) {
145                backtrace_found = true;
146                println("java.lang.Throwable.backtrace field not filtered out.");
147
148                /*
149                 * If you want to experience the segv this bug causes, change
150                 * this test to 1 == 1 and run it with jdk 1.4, build 74 or earlier
151                 */
152                if (1 == 1) {
153                    // The following code will show the segv that this can cause.
154                    ObjectReference myVal = (ObjectReference)myFrame.getValue(lv);
155                    println("BT: myVal = " + myVal);
156
157                    ArrayReference backTraceVal = (ArrayReference)myVal.getValue(ff);
158                    println("BT: backTraceVal = " + backTraceVal);
159
160                    printval(backTraceVal, 0);
161                    printval(backTraceVal, 1);
162                    printval(backTraceVal, 2);
163                    printval(backTraceVal, 3);  // backtrace has 4 elements
164
165                    try {
166                        printval(backTraceVal, 4);
167                    } catch (Exception e) {
168                        println("Exception " + e);
169                    }
170                }
171                break;
172            }
173        }
174
175        if (!backtrace_found) {
176            failure("ERROR: java.lang.Throwable.backtrace field filtered out.");
177        }
178
179        // Next, verify that we don't accidently discard a field that we shouldn't
180
181        if (!testFailed) {
182            lv = myFrame.visibleVariableByName("myTesty");
183
184            allFields = ((ReferenceType)(lv.type())).allFields();
185            println("BT: allFields = " + allFields);
186
187            if (allFields.size() != Testy.field7) {
188                failure("ERROR: wrong number of fields; expected " + Testy.field7 + ", Got " + allFields.size());
189            } else {
190                iter = allFields.iterator();
191                while(iter.hasNext()) {
192                    String fieldName = ((Field)iter.next()).toString();
193                    if (!fieldName.startsWith("Testy.field", 0)) {
194                        failure("ERROR: Found bogus field: " + fieldName.toString());
195                    }
196                }
197            }
198        }
199
200        listenUntilVMDisconnect();
201
202        /*
203         * deal with results of test
204         * if anything has called failure("foo") testFailed will be true
205         */
206        if (!testFailed) {
207            println("BacktraceFieldTest: passed");
208        } else {
209            throw new Exception("BacktraceFieldTest: failed");
210        }
211    }
212}
213