aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Mikhaylov <dmitry@smallgiantgames.com>2021-06-28 17:38:28 +0300
committerDmitry Mikhaylov <dmitry@smallgiantgames.com>2021-06-28 17:38:28 +0300
commitc973566f543122c56b06b82fae4671dc880dc05f (patch)
tree1d453cfbd75e8b578e12c7371fa233936e0b5a3c
parent82df3f0fc9842758f15f12299c9113e48f1ccb5c (diff)
downloadaspectj-c973566f543122c56b06b82fae4671dc880dc05f.tar.gz
aspectj-c973566f543122c56b06b82fae4671dc880dc05f.zip
test for failing synchronization in LocalVariableTable.unpack
-rw-r--r--bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java15
-rw-r--r--bcel-builder/src/test/java/org/aspectj/apache/bcel/classfile/tests/LocalVariableTableConcurrencyTest.java94
2 files changed, 104 insertions, 5 deletions
diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java
index e6415dae6..545227050 100644
--- a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java
+++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java
@@ -63,7 +63,7 @@ import org.aspectj.apache.bcel.Constants;
/**
* This class represents collection of local variables in a method. This attribute is contained in the <em>Code</em> attribute.
- *
+ *
* @version $Id: LocalVariableTable.java,v 1.8 2009/09/15 19:40:12 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @see Code
@@ -99,7 +99,7 @@ public class LocalVariableTable extends Attribute {
/**
* Construct object from file stream.
- *
+ *
* @param name_index Index in constant pool
* @param length Content length in bytes
* @param file Input stream
@@ -117,7 +117,7 @@ public class LocalVariableTable extends Attribute {
/**
* Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class. I.e., the
* hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
- *
+ *
* @param v Visitor object
*/
@Override
@@ -128,7 +128,7 @@ public class LocalVariableTable extends Attribute {
/**
* Dump local variable table attribute to file stream in binary format.
- *
+ *
* @param file Output file stream
* @throws IOException
*/
@@ -189,6 +189,11 @@ public class LocalVariableTable extends Attribute {
return buf.toString();
}
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
/**
* @return deep copy of this attribute
*/
@@ -223,7 +228,7 @@ public class LocalVariableTable extends Attribute {
dis.close();
data = null; // throw it away now
} catch (IOException e) {
- throw new RuntimeException("Unpacking of LocalVariableTable attribute failed");
+ throw new RuntimeException("Unpacking of LocalVariableTable attribute failed", e);
}
isInPackedState = false;
}
diff --git a/bcel-builder/src/test/java/org/aspectj/apache/bcel/classfile/tests/LocalVariableTableConcurrencyTest.java b/bcel-builder/src/test/java/org/aspectj/apache/bcel/classfile/tests/LocalVariableTableConcurrencyTest.java
new file mode 100644
index 000000000..da9b8c296
--- /dev/null
+++ b/bcel-builder/src/test/java/org/aspectj/apache/bcel/classfile/tests/LocalVariableTableConcurrencyTest.java
@@ -0,0 +1,94 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - initial implementation
+ * ******************************************************************/
+
+package org.aspectj.apache.bcel.classfile.tests;
+
+import org.aspectj.apache.bcel.classfile.Code;
+import org.aspectj.apache.bcel.classfile.JavaClass;
+import org.aspectj.apache.bcel.classfile.LocalVariableTable;
+import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.tests.BcelTestCase;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+public class LocalVariableTableConcurrencyTest extends BcelTestCase {
+
+ private final int nThreads = Runtime.getRuntime().availableProcessors();
+
+ private final ExecutorService[] workers = new ExecutorService[nThreads];
+
+ private LocalVariableTable reference;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ for (int i = 0; i < nThreads; i++) workers[i] = Executors.newSingleThreadExecutor();
+
+ JavaClass clazz = getClassFromJar("SimpleGenericsProgram");
+
+ Method mainMethod = getMethod(clazz,"main");
+ Code codeAttr = (Code) findAttribute("Code",mainMethod.getAttributes());
+
+ reference =
+ (LocalVariableTable) findAttribute("LocalVariableTable",codeAttr.getAttributes());
+ }
+
+ private LocalVariableTable createReferenceCopy() {
+ try {
+ return (LocalVariableTable) reference.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("Faileed to clone LocalVariableTable", e);
+ }
+ }
+
+ public void testLocalVariableTableAttributeConcurrency() throws RuntimeException, InterruptedException {
+ final AtomicReference<RuntimeException> error = new AtomicReference<>();
+ for (int i = 0; i < 100000; i++) {
+ LocalVariableTable sharedInstance = createReferenceCopy();
+ CountDownLatch preStart = new CountDownLatch(nThreads);
+ Semaphore start = new Semaphore(0);
+ CountDownLatch finish = new CountDownLatch(nThreads);
+
+ for (int j = 0; j < nThreads; j++) {
+ final boolean needsDelay = j > 0;
+ workers[j].execute(() -> {
+ preStart.countDown();
+ start.acquireUninterruptibly();
+ // trying to trigger concurrent unpacking - one tread should enter unpack() when other is about to leave it
+ if (needsDelay) createReferenceCopy().getTableLength();
+ try {
+ sharedInstance.getTableLength();
+ }
+ catch (RuntimeException ex) {
+ error.compareAndSet(null, ex);
+ }
+ finish.countDown();
+ });
+ }
+
+ preStart.await();
+ start.release(nThreads);
+ finish.await();
+
+ if (error.get() != null) throw error.get();
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ for (int i = 0; i < nThreads; i++) if (workers[i] != null) workers[i].shutdownNow();
+ super.tearDown();
+ }
+}