| /* |
| * Copyright (c) 2002, 2015, 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 4628726 |
| * @summary Test class redefinition - method data line numbers and local vars, |
| * |
| * @author Robert Field |
| * |
| * @library .. |
| * @modules jdk.jdi |
| * @run build TestScaffold VMConnection TargetListener TargetAdapter |
| * @run compile -g RedefineTest.java |
| * @run shell RedefineSetUp.sh |
| * @run driver RedefineTest -repeat 3 |
| * @run driver RedefineTest |
| */ |
| import com.sun.jdi.*; |
| import com.sun.jdi.event.*; |
| import com.sun.jdi.request.*; |
| import java.util.*; |
| import java.io.*; |
| |
| /********** target program **********/ |
| |
| class RedefineTarg { |
| public static void main(String[] args){ |
| RedefineSubTarg.stemcp(); |
| RedefineSubTarg sub = new RedefineSubTarg(); |
| sub.bottom(); |
| RedefineSubTarg.stnemcp(); |
| RedefineSubTarg.stemcp(); |
| } |
| } |
| |
| /********** test program **********/ |
| |
| public class RedefineTest extends TestScaffold { |
| static int redefineRepeat = 1; |
| int bpCnt = 0; |
| |
| // isObsolete, linenumber, lv name, lv value, lv isArg |
| String[] before = { |
| "+ 3", |
| "+ 6 eights 888 T", |
| "+ 11 rot 4 F", |
| "+ 15", |
| "+ 20 myArg 56 T paramy 12 F", |
| "+ 24", |
| "+ 28", |
| "+ 33" }; |
| String[] after = { |
| "+ 5", |
| "O", |
| "O", |
| "+ 16", |
| "+ 21 whoseArg 56 T parawham 12 F", |
| "+ 25", |
| "O", |
| "+ 34" }; |
| String[] shorter = { |
| "+ 5", |
| "+ 9 eights 88 T", |
| "+ 13", |
| "+ 16", |
| "+ 21 whoseArg 56 T parawham 12 F", |
| "+ 25" }; |
| String[] refresh = { |
| "+ 5", |
| "+ 9 eights 88 T", |
| "+ 13", |
| "+ 16", |
| "+ 21 whoseArg 56 T parawham 12 F", |
| "+ 25", |
| "+ 29", |
| "+ 34" }; |
| int[] bps = {7, 12, 16, 21, 25, 30, 34}; |
| String[][] bpPlaces = { |
| {"+ 16"}, |
| {"+ 21 myArg 56 T paramy 12 F"}, |
| {"+ 25"}, |
| {"+ 34"} }; |
| |
| static String[] processArgs(String args[]) { |
| if (args.length > 0 && args[0].equals("-repeat")) { |
| redefineRepeat = Integer.decode(args[1]).intValue(); |
| String[] args2 = new String[args.length - 2]; |
| System.arraycopy(args, 2, args2, 0, args.length - 2); |
| return args2; |
| } else { |
| return args; |
| } |
| } |
| |
| RedefineTest (String args[]) { |
| super(args); |
| } |
| |
| public static void main(String[] args) throws Exception { |
| new RedefineTest(processArgs(args)).startTests(); |
| } |
| |
| |
| /********** event handlers **********/ |
| |
| public void breakpointReached(BreakpointEvent event) { |
| println("Got BreakpointEvent - " + event); |
| try { |
| checkFrames(event.thread(), bpPlaces[bpCnt++]); |
| if (bpCnt >= bpPlaces.length) { |
| eventRequestManager().deleteAllBreakpoints(); |
| } |
| } catch (Exception exc) { |
| failure("FAIL: breakpoint checking threw " + exc); |
| } |
| } |
| |
| /********** test assists **********/ |
| |
| // isObsolete, linenumber, lv name, lv value, lv isArg |
| // equals: ref type (always), method (not obsolete) |
| void checkFrames(ThreadReference thread, String[] matchList) throws Exception { |
| for (int i = 0; i < matchList.length; ++i) { |
| String match = matchList[i]; |
| StackFrame frame = thread.frame(i); |
| Location loc = frame.location(); |
| ReferenceType refType = loc.declaringType(); |
| Method meth = loc.method(); |
| String errInfo = "\nframe " + i + ": " + loc + "\n match: " + match; |
| if (!findReferenceType("RedefineSubTarg").equals(refType)) { |
| failure("FAIL: Bad reference type - " + errInfo); |
| return; // might be bad class, but might have run past bottom |
| } |
| StringTokenizer st = new StringTokenizer(match); |
| boolean expectObs = st.nextToken().equals("O"); |
| println("Frame " + i + ": " + meth); |
| if (meth.isObsolete()) { |
| if (!expectObs) { |
| failure("FAIL: Method should NOT be obsolete - " + errInfo); |
| } |
| } else { |
| if (expectObs) { |
| failure("FAIL: Method should be obsolete - " + errInfo); |
| break; // no more data to read |
| } |
| if (!findMethod(refType, meth.name(), meth.signature()).equals(meth)) { |
| failure("FAIL: Non matching method - " + errInfo); |
| } |
| int line = loc.lineNumber(); |
| if (line != Integer.parseInt(st.nextToken())) { |
| failure("FAIL: Unexpected line number: " + errInfo); |
| } |
| // local var matching |
| int lvCnt = 0; |
| while (st.hasMoreTokens()) { |
| ++lvCnt; |
| String lvName = st.nextToken(); |
| int lvValue = Integer.parseInt(st.nextToken()); |
| boolean isArg = st.nextToken().equals("T"); |
| LocalVariable lv = frame.visibleVariableByName(lvName); |
| if (lv == null) { |
| failure("FAIL: local var not found: '" + lvName + |
| "' -- " + errInfo); |
| } else { |
| Value val = frame.getValue(lv); |
| int ival = ((IntegerValue)val).value(); |
| if (ival != lvValue) { |
| failure("FAIL: expected value: '" + lvValue + |
| "' got: '" + ival + "' -- " + errInfo); |
| } |
| if (lv.isArgument() != isArg) { |
| failure("FAIL: expected argument: '" + isArg + |
| "' got: '" + lv.isArgument() + "' -- " + errInfo); |
| } |
| } |
| } |
| List locals = frame.visibleVariables(); |
| if (locals.size() != lvCnt) { |
| failure("FAIL: expected '" + lvCnt + |
| "' locals were '" + locals.size() + |
| "' -- " + errInfo + "' -- " + locals); |
| } |
| } |
| } |
| } |
| |
| |
| void doRedefine(String fileName) throws Exception { |
| File phyl = new File(fileName); |
| byte[] bytes = new byte[(int)phyl.length()]; |
| InputStream in = new FileInputStream(phyl); |
| in.read(bytes); |
| in.close(); |
| |
| Map map = new HashMap(); |
| map.put(findReferenceType("RedefineSubTarg"), bytes); |
| |
| try { |
| for (int i = 0; i < redefineRepeat; ++i) { |
| vm().redefineClasses(map); |
| } |
| } catch (Exception thr) { |
| failure("FAIL: unexpected exception: " + thr); |
| } |
| } |
| |
| ThreadReference toTop() { |
| BreakpointEvent bpe = resumeTo("RedefineSubTarg", "top", "()V"); |
| return bpe.thread(); |
| } |
| |
| void setBP(int line) { |
| try { |
| Location loc = findLocation(findReferenceType("RedefineSubTarg"), line); |
| final BreakpointRequest request = |
| eventRequestManager().createBreakpointRequest(loc); |
| request.enable(); |
| } catch (Exception exc) { |
| failure("FAIL: Attempt to set BP at line " + line + " threw " + exc); |
| } |
| } |
| |
| /********** test core **********/ |
| |
| protected void runTests() throws Exception { |
| |
| startToMain("RedefineTarg"); |
| |
| ThreadReference thread = toTop(); |
| |
| println("------ Before Redefine ------"); |
| checkFrames(thread, before); |
| |
| println("------ After Redefine ------"); |
| doRedefine("Different_RedefineSubTarg.class"); |
| checkFrames(thread, after); |
| |
| println("------ Static 2 ------"); |
| toTop(); |
| checkFrames(thread, shorter); |
| |
| println("------ Instance ------"); |
| toTop(); |
| checkFrames(thread, shorter); |
| |
| println("------ Re-entered ------"); |
| toTop(); |
| checkFrames(thread, refresh); |
| |
| println("------ Breakpoints ------"); |
| doRedefine("RedefineSubTarg.class"); |
| for (int i = 0; i < bps.length; ++i) { |
| setBP(bps[i]); |
| } |
| |
| /* |
| * resume the target listening for events |
| */ |
| listenUntilVMDisconnect(); |
| |
| if (bpCnt != bpPlaces.length) { |
| failure("FAIL: Wrong number of breakpoints encountered: " + bpCnt); |
| } |
| |
| /* |
| * deal with results of test |
| * if anything has called failure("foo") testFailed will be true |
| */ |
| if (!testFailed) { |
| println("RedefineTest(method): passed"); |
| } else { |
| throw new Exception("RedefineTest(method): failed"); |
| } |
| } |
| } |