Browse Source

IT reproducing GitHub issue 279

Test "same class woven concurrently in parallel-capable classloader"
reproduces #279. Originally taken and modified from:
https://gitlab.com/urisimchoni/aspectj-parallel-issue

Co-authored-by: Uri Simchoni <urisimchoni@gmail.com>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
tags/V1_9_21_1
Alexander Kriegisch 2 months ago
parent
commit
f9c692f936

+ 44
- 0
tests/bugs1921/github_279/Application.java View File

@@ -0,0 +1,44 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* https://github.com/eclipse-aspectj/aspectj/issues/279
*/
public class Application {
public static AtomicInteger HELLO_COUNT = new AtomicInteger(0);
public static AtomicInteger ASPECT_COUNT = new AtomicInteger(0);

private static final int ROUNDS = 25;
private static final int THREAD_COUNT = 2;
private static final int TOTAL_COUNT = ROUNDS * THREAD_COUNT;
private static final String CLASS_TO_LOAD = "GreeterImpl";

public static void main(String[] args) throws Exception {
for (int round = 0; round < ROUNDS; round++) {
ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
ParallelCapableClassLoader cl = new ParallelCapableClassLoader(Application.class.getClassLoader(), CLASS_TO_LOAD);
for (int i = 0; i < THREAD_COUNT; i++) {
executor.submit(() -> {
try {
Class<?> myClass = Class.forName(CLASS_TO_LOAD, true, cl);
Greeter greeter = (Greeter) myClass.getConstructor(new Class<?>[] {}).newInstance();
greeter.hello();
HELLO_COUNT.incrementAndGet();
}
catch (Exception e) {
throw new RuntimeException(e);
}
});
}
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
}

assert HELLO_COUNT.get() == TOTAL_COUNT
: String.format("Hello count should be %s, but is %s", TOTAL_COUNT, HELLO_COUNT.get());
assert ASPECT_COUNT.get() == TOTAL_COUNT
: String.format("Aspect count should be %s, but is %s", TOTAL_COUNT, ASPECT_COUNT.get());
}
}

+ 3
- 0
tests/bugs1921/github_279/Greeter.java View File

@@ -0,0 +1,3 @@
public interface Greeter {
String hello();
}

+ 6
- 0
tests/bugs1921/github_279/GreeterImpl.java View File

@@ -0,0 +1,6 @@
public class GreeterImpl implements Greeter {
@Override
public String hello() {
return "World!";
}
}

+ 12
- 0
tests/bugs1921/github_279/HelloInterceptor.java View File

@@ -0,0 +1,12 @@
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class HelloInterceptor {
@Around("execution(public String Greeter.hello())")
public Object interceptHello(ProceedingJoinPoint pjp) throws Throwable {
Application.ASPECT_COUNT.incrementAndGet();
return pjp.proceed();
}
}

+ 56
- 0
tests/bugs1921/github_279/ParallelCapableClassLoader.java View File

@@ -0,0 +1,56 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class ParallelCapableClassLoader extends ClassLoader {
private final ClassLoader delegate;
private final String classNameToHandle;

static {
if (!ClassLoader.registerAsParallelCapable())
throw new RuntimeException("Failed to register " + ParallelCapableClassLoader.class.getName() + " as parallel-capable");
}

public ParallelCapableClassLoader(ClassLoader delegate, String classNameToHandle) {
this.delegate = delegate;
this.classNameToHandle = classNameToHandle;
}

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> c = this.findLoadedClass(name);
if (c == null && name.equals(classNameToHandle)) {
byte[] bytes = getClassBytes(name);
try {
c = defineClass(name, bytes, 0, bytes.length);
}
catch (LinkageError e) {
c = findLoadedClass(name);
if (c == null)
throw e;
}
}
if (c == null)
c = delegate.loadClass(name);
if (resolve)
this.resolveClass(c);
return c;
}

private byte[] getClassBytes(String name) {
String classFilePath = name.replace('.', File.separatorChar) + ".class";
try (InputStream inputStream = delegate.getResourceAsStream(classFilePath)) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int bytesRead;
byte[] buffer = new byte[4096];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
return outputStream.toByteArray();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}

+ 15
- 0
tests/bugs1921/github_279/ant.xml View File

@@ -0,0 +1,15 @@
<!-- ajc-ant script, not to be used from Ant commant line - see AntSpec -->
<project name="ltw">
<target name="same class woven concurrently in parallel-capable classloader">
<copy file="${aj.root}/tests/bugs1921/github_279/aop.xml" tofile="${aj.sandbox}/META-INF/aop.xml"/>
<java fork="yes" classname="Application" failonerror="yes">
<classpath refid="aj.path"/>
<jvmarg value="-ea"/>
<!-- use META-INF/aop.xml style -->
<jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
<!--<jvmarg value="${aj.addOpensKey}"/>-->
<!--<jvmarg value="${aj.addOpensValue}"/>-->
</java>
</target>

</project>

+ 5
- 0
tests/bugs1921/github_279/aop.xml View File

@@ -0,0 +1,5 @@
<aspectj>
<aspects>
<aspect name="HelloInterceptor"/>
</aspects>
</aspectj>

+ 2
- 2
tests/src/test/java/org/aspectj/systemtest/ajc1921/Bugs1921Tests.java View File

@@ -15,8 +15,8 @@ import org.aspectj.testing.XMLBasedAjcTestCase;
*/
public class Bugs1921Tests extends XMLBasedAjcTestCase {

public void testDummy() {
//runTest("dummy");
public void testGitHub_279() {
runTest("same class woven concurrently in parallel-capable classloader");
}

public static Test suite() {

+ 8
- 0
tests/src/test/resources/org/aspectj/systemtest/ajc1921/ajc1921.xml View File

@@ -333,4 +333,12 @@
</run>
</ajc-test>

<!-- https://github.com/eclipse-aspectj/aspectj/issues/279 -->
<ajc-test dir="bugs1921/github_279" vm="8" title="same class woven concurrently in parallel-capable classloader">
<compile files="Application.java Greeter.java GreeterImpl.java ParallelCapableClassLoader.java" options="-8"/>
<compile files="HelloInterceptor.java" options="-8 -Xlint:ignore"/>
<!-- Problem only reproduces in forked JVM with java agent, hence Ant build -->
<ant file="ant.xml" target="same class woven concurrently in parallel-capable classloader" verbose="true"/>
</ajc-test>

</suite>

Loading…
Cancel
Save