1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.harmony.jpda.tests.jdwp.StackFrame; 20 21 import org.apache.harmony.jpda.tests.framework.TestErrorException; 22 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 23 import org.apache.harmony.jpda.tests.share.SyncDebuggee; 24 25 import java.lang.reflect.InvocationTargetException; 26 import java.lang.reflect.Method; 27 import java.util.Arrays; 28 29 /** 30 * Debuggee for GetValues002Test and SetValues002Test. 31 */ 32 public class StackTrace002Debuggee extends SyncDebuggee { 33 // Signals to select which method the debuggee needs to call. 34 static final String BOOLEAN_SIGNAL = "runBreakpointBoolean"; 35 static final String BYTE_SIGNAL = "runBreakpointByte"; 36 static final String CHAR_SIGNAL = "runBreakpointChar"; 37 static final String SHORT_SIGNAL = "runBreakpointShort"; 38 static final String INT_SIGNAL = "runBreakpointInt"; 39 static final String INT_METHOD2_SIGNAL = "runBreakpointInt2"; 40 static final String INT_CONSTANT_METHOD_SIGNAL = "runBreakpointIntConstant"; 41 static final String INT_TWO_CONSTANTS_METHOD_SIGNAL = "runBreakpointIntTwoConstants"; 42 static final String INT_CONSTANT_METHOD_WITH_EXCEPTION_SIGNAL = 43 "runBreakpointIntConstantWithException"; 44 static final String INT_CONSTANT_METHOD_WITH_EXCEPTION_IN_CALLEE_SIGNAL = 45 "runBreakpointIntConstantWithExceptionInCallee"; 46 static final String INT_CONSTANT_METHOD_WITH_EXCEPTION_IN_CALLER_SIGNAL = 47 "runBreakpointIntConstantWithExceptionInCaller"; 48 static final String INT_CONSTANT_METHOD_WITH_EXCEPTION_FROM_NATIVE_SIGNAL = 49 "runBreakpointIntConstantWithExceptionAndNativeTransition"; 50 static final String LONG_METHOD_SIGNAL = "runBreakpointLong"; 51 static final String FLOAT_METHOD = "runBreakpointFloat"; 52 static final String DOUBLE_METHOD = "runBreakpointDouble"; 53 static final String OBJECT_SIGNAL = "runBreakpointObject"; 54 static final String OBJECT_WITH_EXCEPTION_SIGNAL = "runBreakpointObjectWithException"; 55 static final String OBJECT_METHOD_WITH_EXCEPTION_IN_CALLEE_SIGNAL = 56 "runBreakpointObjectWithExceptionInCallee"; 57 static final String OBJECT_METHOD_WITH_EXCEPTION_IN_CALLER_SIGNAL = 58 "runBreakpointObjectWithExceptionInCaller"; 59 static final String OBJECT_METHOD_WITH_EXCEPTION_FROM_NATIVE_SIGNAL = 60 "runBreakpointObjectWithExceptionAndNativeTransition"; 61 static final String ARRAY_SIGNAL = "runBreakpointArray"; 62 static final String CLASS_SIGNAL = "runBreakpointClass"; 63 static final String CLASS_LOADER_SIGNAL = "runBreakpointClassLoader"; 64 static final String STRING_SIGNAL = "runBreakpointString"; 65 static final String THREAD_SIGNAL = "runBreakpointThread"; 66 static final String THREAD_GROUP_SIGNAL = "runBreakpointThreadGroup"; 67 static final String ARRAY_AS_OBJECT_SIGNAL = "runBreakpointArrayAsObject"; 68 static final String CLASS_AS_OBJECT_SIGNAL = "runBreakpointClassAsObject"; 69 static final String CLASS_LOADER_AS_OBJECT_SIGNAL = "runBreakpointClassLoaderAsObject"; 70 static final String STRING_AS_OBJECT_SIGNAL = "runBreakpointStringAsObject"; 71 static final String THREAD_AS_OBJECT_SIGNAL = "runBreakpointThreadAsObject"; 72 static final String THREAD_GROUP_AS_OBJECT_SIGNAL = "runBreakpointThreadGroupAsObject"; 73 74 // Values used to check StackFrame.GetValues. 75 static final boolean BOOLEAN_PARAM_VALUE = true; 76 static final byte BYTE_PARAM_VALUE = 123; 77 static final char CHAR_PARAM_VALUE = '@'; 78 static final short SHORT_PARAM_VALUE = 12345; 79 static final int INT_PARAM_VALUE = 123456789; 80 static final long LONG_PARAM_VALUE = 102030405060708090L; 81 static final float FLOAT_PARAM_VALUE = 123.456f; 82 static final double DOUBLE_PARAM_VALUE = 0.123456789; 83 static final Object OBJECT_PARAM_VALUE = new Object(); 84 static final int[] ARRAY_PARAM_VALUE = new int[]{1, 2, 3, 4, 5}; 85 static final Class<?> CLASS_PARAM_VALUE = StackTrace002Debuggee.class; 86 static final ClassLoader CLASS_LOADER_PARAM_VALUE = CLASS_PARAM_VALUE.getClassLoader(); 87 static final String STRING_PARAM_VALUE = "this is a string object"; 88 static final Thread THREAD_PARAM_VALUE = new Thread("this is a thread"); 89 static final ThreadGroup THREAD_GROUP_PARAM_VALUE = THREAD_PARAM_VALUE.getThreadGroup(); 90 91 // Values used to check StackFrame.SetValues. 92 static final boolean BOOLEAN_PARAM_VALUE_TO_SET = !BOOLEAN_PARAM_VALUE; 93 static final byte BYTE_PARAM_VALUE_TO_SET = -BYTE_PARAM_VALUE; 94 static final char CHAR_PARAM_VALUE_TO_SET = '%'; 95 static final short SHORT_PARAM_VALUE_TO_SET = -SHORT_PARAM_VALUE; 96 static final int INT_PARAM_VALUE_TO_SET = -INT_PARAM_VALUE; 97 static final long LONG_PARAM_VALUE_TO_SET = -LONG_PARAM_VALUE; 98 static final float FLOAT_PARAM_VALUE_TO_SET = -FLOAT_PARAM_VALUE; 99 static final double DOUBLE_PARAM_VALUE_TO_SET = -DOUBLE_PARAM_VALUE; 100 static final Object OBJECT_PARAM_VALUE_TO_SET = new Object(); 101 static final int[] ARRAY_PARAM_VALUE_TO_SET = new int[]{5, 4, 3, 2, 1}; 102 static final Class<?> CLASS_PARAM_VALUE_TO_SET = Object.class; 103 static final ClassLoader CLASS_LOADER_PARAM_VALUE_TO_SET = 104 CLASS_PARAM_VALUE_TO_SET.getClassLoader(); 105 static final String STRING_PARAM_VALUE_TO_SET = "this is another string object"; 106 static final Thread THREAD_PARAM_VALUE_TO_SET = new Thread("this is another thread"); 107 static final ThreadGroup THREAD_GROUP_PARAM_VALUE_TO_SET = 108 THREAD_PARAM_VALUE_TO_SET.getThreadGroup(); 109 110 // A reference to 'this' debuggee. 111 static Object THIS_OBJECT; 112 113 private static class TestException extends Exception { 114 } 115 116 public static void main(String[] args) { 117 runDebuggee(StackTrace002Debuggee.class); 118 } 119 120 @Override 121 public void run() { 122 THIS_OBJECT = this; 123 124 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY); 125 126 // Wait for test setup. 127 String signal = synchronizer.receiveMessage(); 128 129 // Invoke the method requested by the test. 130 switch (signal) { 131 case BOOLEAN_SIGNAL: 132 runBreakpointBoolean(BOOLEAN_PARAM_VALUE); 133 break; 134 case BYTE_SIGNAL: 135 runBreakpointByte(BYTE_PARAM_VALUE); 136 break; 137 case CHAR_SIGNAL: 138 runBreakpointChar(CHAR_PARAM_VALUE); 139 break; 140 case SHORT_SIGNAL: 141 runBreakpointShort(SHORT_PARAM_VALUE); 142 break; 143 case INT_SIGNAL: 144 runBreakpointInt(INT_PARAM_VALUE); 145 break; 146 case INT_METHOD2_SIGNAL: 147 runBreakpointInt2(INT_PARAM_VALUE); 148 break; 149 case INT_CONSTANT_METHOD_SIGNAL: 150 runBreakpointIntConstant(); 151 break; 152 case INT_TWO_CONSTANTS_METHOD_SIGNAL: 153 runBreakpointIntTwoConstants(); 154 break; 155 case INT_CONSTANT_METHOD_WITH_EXCEPTION_SIGNAL: 156 runBreakpointIntConstantWithException(); 157 break; 158 case INT_CONSTANT_METHOD_WITH_EXCEPTION_IN_CALLEE_SIGNAL: 159 runBreakpointIntConstantWithExceptionInCallee(); 160 break; 161 case INT_CONSTANT_METHOD_WITH_EXCEPTION_IN_CALLER_SIGNAL: 162 runBreakpointIntConstantWithExceptionInCaller(); 163 break; 164 case INT_CONSTANT_METHOD_WITH_EXCEPTION_FROM_NATIVE_SIGNAL: 165 runBreakpointIntConstantWithExceptionAndNativeTransition(); 166 break; 167 case LONG_METHOD_SIGNAL: 168 runBreakpointLong(LONG_PARAM_VALUE); 169 break; 170 case FLOAT_METHOD: 171 runBreakpointFloat(FLOAT_PARAM_VALUE); 172 break; 173 case DOUBLE_METHOD: 174 runBreakpointDouble(DOUBLE_PARAM_VALUE); 175 break; 176 case OBJECT_SIGNAL: 177 runBreakpointObject(OBJECT_PARAM_VALUE); 178 break; 179 case OBJECT_WITH_EXCEPTION_SIGNAL: 180 runBreakpointObjectWithException(); 181 break; 182 case OBJECT_METHOD_WITH_EXCEPTION_IN_CALLEE_SIGNAL: 183 runBreakpointObjectWithExceptionInCallee(); 184 break; 185 case OBJECT_METHOD_WITH_EXCEPTION_IN_CALLER_SIGNAL: 186 runBreakpointObjectWithExceptionInCaller(); 187 break; 188 case OBJECT_METHOD_WITH_EXCEPTION_FROM_NATIVE_SIGNAL: 189 runBreakpointObjectWithExceptionAndNativeTransition(); 190 break; 191 case ARRAY_SIGNAL: 192 runBreakpointArray(ARRAY_PARAM_VALUE); 193 break; 194 case CLASS_SIGNAL: 195 runBreakpointClass(CLASS_PARAM_VALUE); 196 break; 197 case CLASS_LOADER_SIGNAL: 198 runBreakpointClassLoader(CLASS_LOADER_PARAM_VALUE); 199 break; 200 case STRING_SIGNAL: 201 runBreakpointString(STRING_PARAM_VALUE); 202 break; 203 case THREAD_SIGNAL: 204 runBreakpointThread(THREAD_PARAM_VALUE); 205 break; 206 case THREAD_GROUP_SIGNAL: 207 runBreakpointThreadGroup(THREAD_GROUP_PARAM_VALUE); 208 break; 209 case ARRAY_AS_OBJECT_SIGNAL: 210 runBreakpointObject(ARRAY_PARAM_VALUE); 211 break; 212 case CLASS_AS_OBJECT_SIGNAL: 213 runBreakpointObject(CLASS_PARAM_VALUE); 214 break; 215 case CLASS_LOADER_AS_OBJECT_SIGNAL: 216 runBreakpointObject(CLASS_LOADER_PARAM_VALUE); 217 break; 218 case STRING_AS_OBJECT_SIGNAL: 219 runBreakpointObject(STRING_PARAM_VALUE); 220 break; 221 case THREAD_AS_OBJECT_SIGNAL: 222 runBreakpointObject(THREAD_PARAM_VALUE); 223 break; 224 case THREAD_GROUP_AS_OBJECT_SIGNAL: 225 runBreakpointObject(THREAD_GROUP_PARAM_VALUE); 226 break; 227 default: 228 throw new TestErrorException("Unexpected signal \"" + signal + "\""); 229 } 230 231 } 232 233 // Test boolean type. 234 public void runBreakpointBoolean(boolean param) { 235 breakpointBoolean(param); 236 breakpointBoolean(param); 237 } 238 239 public void breakpointBoolean(boolean param) { 240 logWriter.println("breakpointBoolean(param=" + param + ")"); 241 synchronizeWithTest(); 242 } 243 244 // Test byte type. 245 public void runBreakpointByte(byte param) { 246 breakpointByte(param); 247 breakpointByte(param); 248 } 249 250 public void breakpointByte(byte param) { 251 logWriter.println("breakpointByte(param=" + param + ")"); 252 synchronizeWithTest(); 253 } 254 255 // Test char type. 256 public void runBreakpointChar(char param) { 257 breakpointChar(param); 258 breakpointChar(param); 259 } 260 261 public void breakpointChar(char param) { 262 logWriter.println("breakpointChar(param=" + param + ")"); 263 synchronizeWithTest(); 264 } 265 266 // Test short type. 267 public void runBreakpointShort(short param) { 268 breakpointShort(param); 269 breakpointShort(param); 270 } 271 272 public void breakpointShort(short param) { 273 logWriter.println("breakpointShort(param=" + param + ")"); 274 synchronizeWithTest(); 275 } 276 277 // Test int type. 278 public void runBreakpointInt(int param) { 279 breakpointInt(param); 280 breakpointInt(param); 281 } 282 283 public void breakpointInt(int param) { 284 logWriter.println("breakpointInt(param=" + param + ")"); 285 synchronizeWithTest(); 286 } 287 288 public void runBreakpointInt2(int param) { 289 int local = param; 290 breakpointInt2(local); 291 local = local + param; 292 breakpointInt2(local); 293 } 294 295 public void breakpointInt2(int param) { 296 logWriter.println("breakpointInt2(param=" + param + ")"); 297 synchronizeWithTest(); 298 } 299 300 // Test int type with a constant. 301 public void runBreakpointIntConstant() { 302 int local = INT_PARAM_VALUE; 303 breakpointIntConstant(local); 304 breakpointIntConstant(local); 305 } 306 307 public void breakpointIntConstant(int param) { 308 logWriter.println("breakpointIntConstant(param=" + param + ")"); 309 synchronizeWithTest(); 310 } 311 312 // Test int type with two constants in the same frame. 313 public void runBreakpointIntTwoConstants() { 314 int local1 = INT_PARAM_VALUE; 315 int local2 = -INT_PARAM_VALUE; 316 breakpointIntTwoConstants(local1, local2); 317 breakpointIntTwoConstants(local1, local2); 318 } 319 320 public void breakpointIntTwoConstants(int param1, int param2) { 321 logWriter.println("breakpointIntTwoConstants(param1=" + param1 + 322 ", param2=" + param2 + ")"); 323 synchronizeWithTest(); 324 } 325 326 // Test setting a variable with a caught exception. 327 public void runBreakpointIntConstantWithException() { 328 int local = INT_PARAM_VALUE; 329 try { 330 breakpointIntConstantWithException(local); 331 } catch (TestException expected) { 332 } 333 try { 334 breakpointIntConstantWithException(local); 335 } catch (TestException expected) { 336 } 337 } 338 339 // Test setting a variable with a caught exception in the callee. 340 public void runBreakpointIntConstantWithExceptionInCallee() { 341 int local = INT_PARAM_VALUE; 342 breakpointIntConstantWithCaughtException(local); 343 breakpointIntConstantWithCaughtException(local); 344 } 345 346 // Test setting a variable with a caught exception in the caller. Because the frame will 347 // be unwound after throwing the exception, setting the variable has no effect. 348 public void runBreakpointIntConstantWithExceptionInCaller() { 349 // Call twice to remain compatible with the test expecting 2 suspensions. 350 try { 351 runBreakpointIntConstantWithExceptionInCallerImpl(); 352 } catch (TestException expected) { 353 } 354 try { 355 runBreakpointIntConstantWithExceptionInCallerImpl(); 356 } catch (TestException expected) { 357 } 358 } 359 360 public void runBreakpointIntConstantWithExceptionInCallerImpl() throws TestException { 361 int local = INT_PARAM_VALUE; 362 // We're going to throw in the callee and the exception is caught in our caller so we 363 // won't execute the current frame anymore. 364 breakpointIntConstantWithException(local); 365 } 366 367 private void breakpointIntConstantWithCaughtException(int param) { 368 try { 369 breakpointIntConstantWithException(param); 370 } catch (TestException expected) { 371 } 372 } 373 374 public void breakpointIntConstantWithException(int param) throws TestException { 375 logWriter.println("breakpointIntConstantWithException(param=" + param + ")"); 376 synchronizeWithTest(); 377 throw new TestException(); 378 } 379 380 // Test setting a variable with a caught exception with a native transition (using reflect). 381 public void runBreakpointIntConstantWithExceptionAndNativeTransition() { 382 int local = INT_PARAM_VALUE; 383 try { 384 breakpointIntConstantWithExceptionAndNativeTransition(local); 385 } catch (TestException expected) { 386 } 387 try { 388 breakpointIntConstantWithExceptionAndNativeTransition(local); 389 } catch (TestException expected) { 390 } 391 } 392 393 private void breakpointIntConstantWithExceptionAndNativeTransition(int local) throws TestException { 394 try { 395 Method suspensionMethod = 396 StackTrace002Debuggee.class.getDeclaredMethod("breakpointIntConstantWithException", 397 new Class<?>[]{int.class}); 398 suspensionMethod.invoke(this, local); 399 } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException e) { 400 throw new TestErrorException(e); 401 } catch (InvocationTargetException e) { 402 if (e.getTargetException() instanceof TestException) { 403 throw (TestException) e.getTargetException(); 404 } else { 405 throw new TestErrorException(e); 406 } 407 } 408 } 409 410 // Test long type. 411 public void runBreakpointLong(long param) { 412 breakpointLong(param); 413 breakpointLong(param); 414 } 415 416 public void breakpointLong(long param) { 417 logWriter.println("breakpointLong(param=" + param + ")"); 418 synchronizeWithTest(); 419 } 420 421 // Test float type. 422 public void runBreakpointFloat(float param) { 423 breakpointFloat(param); 424 breakpointFloat(param); 425 } 426 427 public void breakpointFloat(float param) { 428 logWriter.println("breakpointFloat(param=" + param + ")"); 429 synchronizeWithTest(); 430 } 431 432 // Test double type. 433 public void runBreakpointDouble(double param) { 434 breakpointDouble(param); 435 breakpointDouble(param); 436 } 437 438 public void breakpointDouble(double param) { 439 logWriter.println("breakpointDouble(param=" + param + ")"); 440 synchronizeWithTest(); 441 } 442 443 // Test java.lang.Object type. 444 public void runBreakpointObject(Object param) { 445 breakpointObject(param); 446 breakpointObject(param); 447 } 448 449 public void breakpointObject(Object param) { 450 logWriter.println("breakpointObject(param=\"" + param + "\")"); 451 synchronizeWithTest(); 452 } 453 454 // Test setting a java.lang.Object variable with a caught exception. 455 public void runBreakpointObjectWithException() { 456 Object local = OBJECT_PARAM_VALUE; 457 try { 458 breakpointObjectWithException(local); 459 } catch (TestException expected) { 460 } 461 try { 462 breakpointObjectWithException(local); 463 } catch (TestException expected) { 464 } 465 } 466 467 public void breakpointObjectWithException(Object param) throws TestException { 468 logWriter.println("breakpointObjectWithException(param=" + param + ")"); 469 synchronizeWithTest(); 470 throw new TestException(); 471 } 472 473 // Test setting a java.lang.Object variable with a caught exception in the callee. 474 public void runBreakpointObjectWithExceptionInCallee() { 475 Object local = OBJECT_PARAM_VALUE; 476 breakpointObjectWithCaughtException(local); 477 breakpointObjectWithCaughtException(local); 478 } 479 480 // Test setting a java.lang.Object variable with a caught exception in the caller. 481 // Because the frame will be unwound after throwing the exception, setting the 482 // variable has no effect. 483 public void runBreakpointObjectWithExceptionInCaller() { 484 // Call twice to remain compatible with the test expecting 2 suspensions. 485 try { 486 runBreakpointObjectWithExceptionInCallerImpl(); 487 } catch (TestException expected) { 488 } 489 try { 490 runBreakpointObjectWithExceptionInCallerImpl(); 491 } catch (TestException expected) { 492 } 493 } 494 495 public void runBreakpointObjectWithExceptionInCallerImpl() throws TestException { 496 Object local = OBJECT_PARAM_VALUE; 497 // We're going to throw in the callee and the exception is caught in our caller so we 498 // won't execute the current frame anymore. 499 breakpointObjectWithException(local); 500 } 501 502 private void breakpointObjectWithCaughtException(Object param) { 503 try { 504 breakpointObjectWithException(param); 505 } catch (TestException expected) { 506 } 507 } 508 509 // Test setting a java.lang.Object variable with a caught exception with a native 510 // transition (using reflect). 511 public void runBreakpointObjectWithExceptionAndNativeTransition() { 512 Object local = OBJECT_PARAM_VALUE; 513 try { 514 breakpointObjectWithExceptionAndNativeTransition(local); 515 } catch (TestException expected) { 516 } 517 try { 518 breakpointObjectWithExceptionAndNativeTransition(local); 519 } catch (TestException expected) { 520 } 521 } 522 523 private void breakpointObjectWithExceptionAndNativeTransition(Object local) 524 throws TestException { 525 try { 526 Method suspensionMethod = 527 StackTrace002Debuggee.class.getDeclaredMethod("breakpointObjectWithException", 528 new Class<?>[]{Object.class}); 529 suspensionMethod.invoke(this, local); 530 } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException e) { 531 throw new TestErrorException(e); 532 } catch (InvocationTargetException e) { 533 if (e.getTargetException() instanceof TestException) { 534 throw (TestException) e.getTargetException(); 535 } else { 536 throw new TestErrorException(e); 537 } 538 } 539 } 540 541 // Test array type. 542 public void runBreakpointArray(int[] param) { 543 breakpointArray(param); 544 breakpointArray(param); 545 } 546 547 public void breakpointArray(int[] param) { 548 logWriter.println("breakpointArray(param=\"" + Arrays.toString(param) + "\")"); 549 synchronizeWithTest(); 550 } 551 552 // Test java.lang.Class type. 553 public void runBreakpointClass(Class<?> param) { 554 breakpointClass(param); 555 breakpointClass(param); 556 } 557 558 public void breakpointClass(Class<?> param) { 559 logWriter.println("breakpointClass(param=\"" + param + "\")"); 560 synchronizeWithTest(); 561 } 562 563 // Test java.lang.ClassLoader type. 564 public void runBreakpointClassLoader(ClassLoader param) { 565 breakpointClassLoader(param); 566 breakpointClassLoader(param); 567 } 568 569 public void breakpointClassLoader(ClassLoader param) { 570 logWriter.println("breakpointClassLoader(param=\"" + param + "\")"); 571 synchronizeWithTest(); 572 } 573 574 // Test java.lang.String type. 575 public void runBreakpointString(String param) { 576 breakpointString(param); 577 breakpointString(param); 578 } 579 580 public void breakpointString(String param) { 581 logWriter.println("breakpointString(param=\"" + param + "\")"); 582 synchronizeWithTest(); 583 } 584 585 // Test java.lang.Thread type. 586 public void runBreakpointThread(Thread param) { 587 breakpointThread(param); 588 breakpointThread(param); 589 } 590 591 public void breakpointThread(Thread param) { 592 logWriter.println("breakpointThread(param=\"" + param + "\")"); 593 synchronizeWithTest(); 594 } 595 596 // Test java.lang.ThreadGroup type. 597 public void runBreakpointThreadGroup(ThreadGroup param) { 598 breakpointThreadGroup(param); 599 breakpointThreadGroup(param); 600 } 601 602 public void breakpointThreadGroup(ThreadGroup param) { 603 logWriter.println("breakpointThreadGroup(param=\"" + param + "\")"); 604 synchronizeWithTest(); 605 } 606 607 private void synchronizeWithTest() { 608 // Sends thread's name so the test can find its thread id. 609 synchronizer.sendMessage(Thread.currentThread().getName()); 610 611 // Wait for the test to signal us after its checks. 612 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 613 } 614 }