1 /* *******************************************************************
2 * Copyright (c) 2004 IBM
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
10 * Andy Clement - initial implementation
11 * ******************************************************************/
13 package org.aspectj.apache.bcel.classfile.tests;
15 import org.aspectj.apache.bcel.classfile.Code;
16 import org.aspectj.apache.bcel.classfile.JavaClass;
17 import org.aspectj.apache.bcel.classfile.LocalVariableTable;
18 import org.aspectj.apache.bcel.classfile.Method;
19 import org.aspectj.apache.bcel.classfile.tests.BcelTestCase;
21 import java.util.concurrent.CountDownLatch;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.Executors;
24 import java.util.concurrent.Semaphore;
25 import java.util.concurrent.atomic.AtomicReference;
28 public class LocalVariableTableConcurrencyTest extends BcelTestCase {
30 private final int nThreads = Runtime.getRuntime().availableProcessors();
32 private final ExecutorService[] workers = new ExecutorService[nThreads];
34 private LocalVariableTable reference;
36 protected void setUp() throws Exception {
38 for (int i = 0; i < nThreads; i++) workers[i] = Executors.newSingleThreadExecutor();
40 JavaClass clazz = getClassFromJar("SimpleGenericsProgram");
42 Method mainMethod = getMethod(clazz,"main");
43 Code codeAttr = (Code) findAttribute("Code",mainMethod.getAttributes());
46 (LocalVariableTable) findAttribute("LocalVariableTable",codeAttr.getAttributes());
49 private LocalVariableTable createReferenceCopy() {
51 return (LocalVariableTable) reference.clone();
52 } catch (CloneNotSupportedException e) {
53 throw new RuntimeException("Faileed to clone LocalVariableTable", e);
57 public void testLocalVariableTableAttributeConcurrency() throws RuntimeException, InterruptedException {
58 final AtomicReference<RuntimeException> error = new AtomicReference<>();
59 for (int i = 0; i < 100000; i++) {
60 LocalVariableTable sharedInstance = createReferenceCopy();
61 CountDownLatch preStart = new CountDownLatch(nThreads);
62 Semaphore start = new Semaphore(0);
63 CountDownLatch finish = new CountDownLatch(nThreads);
65 for (int j = 0; j < nThreads; j++) {
66 final boolean needsDelay = j > 0;
67 workers[j].execute(() -> {
69 start.acquireUninterruptibly();
70 // trying to trigger concurrent unpacking - one tread should enter unpack() when other is about to leave it
71 if (needsDelay) createReferenceCopy().getTableLength();
73 sharedInstance.getTableLength();
75 catch (RuntimeException ex) {
76 error.compareAndSet(null, ex);
83 start.release(nThreads);
86 if (error.get() != null) throw error.get();
90 protected void tearDown() throws Exception {
91 for (int i = 0; i < nThreads; i++) if (workers[i] != null) workers[i].shutdownNow();