You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LocalVariableTableConcurrencyTest.java 3.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Dmitry Mikhaylov - initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.apache.bcel.classfile.tests;
  13. import org.aspectj.apache.bcel.classfile.Code;
  14. import org.aspectj.apache.bcel.classfile.JavaClass;
  15. import org.aspectj.apache.bcel.classfile.LocalVariableTable;
  16. import org.aspectj.apache.bcel.classfile.Method;
  17. import java.util.concurrent.CountDownLatch;
  18. import java.util.concurrent.ExecutorService;
  19. import java.util.concurrent.Executors;
  20. import java.util.concurrent.Semaphore;
  21. import java.util.concurrent.atomic.AtomicReference;
  22. public class LocalVariableTableConcurrencyTest extends BcelTestCase {
  23. private final int nThreads = Runtime.getRuntime().availableProcessors();
  24. private final ExecutorService[] workers = new ExecutorService[nThreads];
  25. private LocalVariableTable reference;
  26. protected void setUp() throws Exception {
  27. super.setUp();
  28. for (int i = 0; i < nThreads; i++) workers[i] = Executors.newSingleThreadExecutor();
  29. JavaClass clazz = getClassFromJar("SimpleGenericsProgram");
  30. Method mainMethod = getMethod(clazz,"main");
  31. Code codeAttr = (Code) findAttribute("Code",mainMethod.getAttributes());
  32. reference = (LocalVariableTable) findAttribute("LocalVariableTable",codeAttr.getAttributes());
  33. }
  34. /**
  35. * Try to hit concurrency bug in org.aspectj.apache.bcel.classfile.LocalVariableTable.unpack().
  36. * We do so by running unpack() on same instance with multiple threads, and artificially
  37. * delaying all threads but first so that they enter unpack() the moment first thread is about to leave it.
  38. *
  39. * Since this test relies on empirically obtained access pattern and number of iterations,
  40. * it never has 100% probability of hitting the bug. If it fails - there is certainly a bug.
  41. * If it passes, it could mean anything - fully correct code or slightly changed execution order preventing
  42. * threads to collide at problematic location.
  43. *
  44. * As such, it is not really good for unit testing.
  45. */
  46. public void testLocalVariableTableAttributeConcurrency() throws RuntimeException, InterruptedException {
  47. final AtomicReference<RuntimeException> error = new AtomicReference<>();
  48. for (int i = 0; i < 10000; i++) {
  49. LocalVariableTable sharedInstance = reference.copyFromPackedState();
  50. CountDownLatch preStart = new CountDownLatch(nThreads);
  51. Semaphore start = new Semaphore(0);
  52. CountDownLatch finish = new CountDownLatch(nThreads);
  53. for (int j = 0; j < nThreads; j++) {
  54. final boolean needsDelay = j > 0;
  55. workers[j].execute(() -> {
  56. preStart.countDown();
  57. start.acquireUninterruptibly();
  58. // trying to trigger concurrent unpacking bug - one tread should enter unpack() when other is about to leave it
  59. if (needsDelay) reference.copyFromPackedState().getTableLength();
  60. try {
  61. sharedInstance.getTableLength();
  62. }
  63. catch (RuntimeException ex) {
  64. error.compareAndSet(null, ex);
  65. }
  66. finish.countDown();
  67. });
  68. }
  69. preStart.await();
  70. start.release(nThreads);
  71. finish.await();
  72. if (error.get() != null) throw error.get();
  73. }
  74. }
  75. protected void tearDown() throws Exception {
  76. for (int i = 0; i < nThreads; i++) if (workers[i] != null) workers[i].shutdownNow();
  77. super.tearDown();
  78. }
  79. }