1 /* 2 * Copyright (c) 2025, 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 * @summary Sanity test for AccessWatchpoint/ModificationWatchpoint and InstanceFilter with value objects 27 * 28 * @library .. 29 * @enablePreview 30 * @run main/othervm FieldWatchpointsTest 31 * -XX:+UseArrayFlattening -XX:+UseFieldFlattening -XX:+UseAtomicValueFlattening -XX:+UseNullableValueFlattening 32 * -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlineLayout -XX:+PrintFlatArrayLayout 33 */ 34 import com.sun.jdi.Field; 35 import com.sun.jdi.ClassType; 36 import com.sun.jdi.Method; 37 import com.sun.jdi.ObjectReference; 38 import com.sun.jdi.ThreadReference; 39 import com.sun.jdi.Value; 40 import com.sun.jdi.event.AccessWatchpointEvent; 41 import com.sun.jdi.event.BreakpointEvent; 42 import com.sun.jdi.event.ModificationWatchpointEvent; 43 import com.sun.jdi.event.WatchpointEvent; 44 import com.sun.jdi.request.WatchpointRequest; 45 import java.util.ArrayList; 46 import java.util.List; 47 48 class FieldWatchpointsTarg { 49 static value class Value { 50 int v; 51 Value() { 52 this(0); 53 } 54 Value(int v) { 55 this.v = v; 56 } 57 public int getValue() { 58 return v; 59 } 60 } 61 62 static Value staticField = new Value(1); 63 64 public static void main(String[] args) { 65 System.out.println(">>Targ.main"); 66 Value obj = new Value(2); // modify 67 System.out.println("obj value = " + obj.v); // access 68 System.out.println("staticField value = " + staticField.v); // access 69 System.out.println("<<Targ.main"); 70 } 71 } 72 73 public class FieldWatchpointsTest extends TestScaffold { 74 75 FieldWatchpointsTest (String args[]) { 76 super(args); 77 } 78 79 public static void main(String[] args) throws Exception { 80 new FieldWatchpointsTest(args).startTests(); 81 } 82 83 boolean equals(ObjectReference obj1, ObjectReference obj2) throws Exception { 84 return obj1.equals(obj2); 85 } 86 87 void assertEqual(ObjectReference obj1, ObjectReference obj2) throws Exception { 88 if (!equals(obj1, obj2)) { 89 throw new RuntimeException("Values are not equal: " + obj1 + " and " + obj2); 90 } 91 } 92 93 void assertNotEqual(ObjectReference obj1, ObjectReference obj2) throws Exception { 94 if (equals(obj1, obj2)) { 95 throw new RuntimeException("Values are equal: " + obj1 + " and " + obj2); 96 } 97 } 98 99 public void fieldAccessed(AccessWatchpointEvent event) { 100 TestCase.watchpoint(event); 101 } 102 103 public void fieldModified(ModificationWatchpointEvent event) { 104 TestCase.watchpoint(event); 105 } 106 107 protected void runTests() throws Exception { 108 List<TestCase> testCases = new ArrayList<>(); 109 try { 110 BreakpointEvent bpe = startToMain("FieldWatchpointsTarg"); 111 ThreadReference mainThread = bpe.thread(); 112 ClassType testClass = (ClassType)bpe.location().declaringType(); 113 Field staticValueField = testClass.fieldByName("staticField"); 114 ClassType valueClass = (ClassType)staticValueField.type(); 115 ObjectReference staticFieldValue = (ObjectReference)testClass.getValue(staticValueField); 116 117 Field watchField = valueClass.fieldByName("v"); 118 119 WatchpointRequest request = eventRequestManager().createModificationWatchpointRequest(watchField); 120 testCases.add(new TestCase("modify", 1, request)); // obj ctor 121 122 request = eventRequestManager().createAccessWatchpointRequest(watchField); 123 testCases.add(new TestCase("access", 2, request)); // staticField, obj 124 125 request = eventRequestManager().createAccessWatchpointRequest(watchField); 126 request.addInstanceFilter(staticFieldValue); 127 testCases.add(new TestCase("access+instanceFilter", 1, request)); // only staticField 128 } finally { 129 listenUntilVMDisconnect(); 130 } 131 132 for (TestCase test: testCases) { 133 String msg = "Testcase: " + test.name 134 + ", count = " + test.count 135 + ", expectedCount = " + test.expectedCount; 136 System.out.println(msg); 137 if (test.count != test.expectedCount) { 138 throw new RuntimeException("FAILED " + msg); 139 } 140 } 141 } 142 143 class TestCase { 144 String name; 145 int count; 146 int expectedCount; 147 TestCase(String name, int expectedCount, WatchpointRequest request) { 148 this.name = name; 149 this.expectedCount = expectedCount; 150 request.putProperty("testcase", this); 151 request.enable(); 152 } 153 154 static void watchpoint(WatchpointEvent event) { 155 TestCase test = (TestCase)event.request().getProperty("testcase"); 156 test.count++; 157 } 158 } 159 }