diff -r 4ebc2e2fb97c -r 71c04702a3d5 test/jdk/com/sun/jdi/BacktraceFieldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/jdi/BacktraceFieldTest.java Tue Sep 12 19:03:39 2017 +0200 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2016, 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 4446677 + * @bug 8158237 + * @summary debuggee used to crash when debugging under jbuilder + * @author jjh + * + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @run compile -g BacktraceFieldTest.java + * @run driver BacktraceFieldTest + */ + +/* + * The fix for this bug filters out the backtrace field from the list + * of fields for java.lang.Throwable. + * This test verifies that this really happens, and also verifies that the fix + * doesn't incorrectly discard other fields. + */ + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; + +/********** target program **********/ + +class Testy { + /* + * This is used to verify that the fix doesn't filter out fields that it + * shouldn't. 7 is an abitrary number, and this isn't a definitive + * test; the fix could conceivably filter out the 89th field of a class + * named Foo. + * To verify that this part of this test works, first uncomment the field8 + * line and verify that the test fails, and then rename a field to xxx and + * verify that the test fails. + */ + int field1; + int field2; + int field3; + int field4; + int field5; + int field6; + final static int field7 = 7; // Value is the number of fields. + //int field8; + + Testy() { + } +} + + +class BacktraceFieldTarg { + public static void gus() { + } + + public static void main(String[] args) { + Testy myTesty = new Testy(); + try { + throw new RuntimeException("jjException"); + } catch (Exception ee) { + gus(); + System.out.println("debuggee: Exception: " + ee); + } + } +} + +/********** test program **********/ + +public class BacktraceFieldTest extends TestScaffold { + ThreadReference mainThread; + + BacktraceFieldTest (String args[]) { + super(args); + } + + public static void main(String[] args) throws Exception { + new BacktraceFieldTest(args).startTests(); + } + + private void printval(ArrayReference backTraceVal, int index) throws Exception { + ArrayReference val = (ArrayReference)backTraceVal.getValue(index); + println("BT: val at " + index + " = " + val); + + // The segv used to happen here for index = 0 + // Now all objects in the backtrace are objects. + Object xVal = (Object)val.getValue(0); + println("BT: xVal = " + xVal); + } + + /********** test core **********/ + + protected void runTests() throws Exception { + /* + * Get to the top of gus() + * to determine mainThread + */ + BreakpointEvent bpe = startTo("BacktraceFieldTarg", "gus", "()V"); + mainThread = bpe.thread(); + + /* + * We are now one frame below the exception frame that contains + * our ee var. + */ + StackFrame myFrame = mainThread.frame(1); + + LocalVariable lv = myFrame.visibleVariableByName("ee"); + println("BT: lv = " + lv); + println("BT: lvType = " + lv.typeName()); + + List allFields = ((ReferenceType)(lv.type())).allFields(); + println("BT: allFields = " + allFields); + + /* + * Search through the fields of ee to verify that + * java.lang.Throwable.backtrace isn't there. + */ + boolean backtrace_found = false; + Iterator iter = allFields.iterator(); + while(iter.hasNext()) { + Field ff = (Field)iter.next(); + if (ff.toString().equals("java.lang.Throwable.backtrace")) { + backtrace_found = true; + println("java.lang.Throwable.backtrace field not filtered out."); + + /* + * If you want to experience the segv this bug causes, change + * this test to 1 == 1 and run it with jdk 1.4, build 74 or earlier + */ + if (1 == 1) { + // The following code will show the segv that this can cause. + ObjectReference myVal = (ObjectReference)myFrame.getValue(lv); + println("BT: myVal = " + myVal); + + ArrayReference backTraceVal = (ArrayReference)myVal.getValue(ff); + println("BT: backTraceVal = " + backTraceVal); + + printval(backTraceVal, 0); + printval(backTraceVal, 1); + printval(backTraceVal, 2); + printval(backTraceVal, 3); // backtrace has 4 elements + + try { + printval(backTraceVal, 4); + } catch (Exception e) { + println("Exception " + e); + } + } + break; + } + } + + if (!backtrace_found) { + failure("ERROR: java.lang.Throwable.backtrace field filtered out."); + } + + // Next, verify that we don't accidently discard a field that we shouldn't + + if (!testFailed) { + lv = myFrame.visibleVariableByName("myTesty"); + + allFields = ((ReferenceType)(lv.type())).allFields(); + println("BT: allFields = " + allFields); + + if (allFields.size() != Testy.field7) { + failure("ERROR: wrong number of fields; expected " + Testy.field7 + ", Got " + allFields.size()); + } else { + iter = allFields.iterator(); + while(iter.hasNext()) { + String fieldName = ((Field)iter.next()).toString(); + if (!fieldName.startsWith("Testy.field", 0)) { + failure("ERROR: Found bogus field: " + fieldName.toString()); + } + } + } + } + + listenUntilVMDisconnect(); + + /* + * deal with results of test + * if anything has called failure("foo") testFailed will be true + */ + if (!testFailed) { + println("BacktraceFieldTest: passed"); + } else { + throw new Exception("BacktraceFieldTest: failed"); + } + } +}