Browse Source

test for failing synchronization in LocalVariableTable.unpack

tags/V1_9_8_M1
Dmitry Mikhaylov 2 years ago
parent
commit
c973566f54

+ 10
- 5
bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java View File

@@ -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;
}

+ 94
- 0
bcel-builder/src/test/java/org/aspectj/apache/bcel/classfile/tests/LocalVariableTableConcurrencyTest.java View File

@@ -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();
}
}

Loading…
Cancel
Save