Skip to content

Commit

Permalink
Improve locking on JavacCompiler
Browse files Browse the repository at this point in the history
- the code synchonizes on the CopyOnWriteArrayList which is a concurrent collection
- the double check locking pattern is badly written and does not actually double checks
  • Loading branch information
gnodet committed Oct 28, 2023
1 parent b7cc076 commit 3dc1ca7
Showing 1 changed file with 17 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentLinkedDeque;

import org.codehaus.plexus.compiler.AbstractCompiler;
import org.codehaus.plexus.compiler.CompilerConfiguration;
Expand Down Expand Up @@ -102,9 +103,9 @@ public class JavacCompiler extends AbstractCompiler {

private static final String JAVAC_CLASSNAME = "com.sun.tools.javac.Main";

private static volatile Class<?> JAVAC_CLASS;
private volatile Class<?> javacClass;

private final List<Class<?>> javaccClasses = new CopyOnWriteArrayList<>();
private final Deque<Class<?>> javacClasses = new ConcurrentLinkedDeque<>();

@Inject
private InProcessCompiler inProcessCompiler;
Expand Down Expand Up @@ -955,7 +956,7 @@ private static String getJavacExecutable() throws IOException {
private void releaseJavaccClass(Class<?> javaccClass, CompilerConfiguration compilerConfiguration) {
if (compilerConfiguration.getCompilerReuseStrategy()
== CompilerConfiguration.CompilerReuseStrategy.ReuseCreated) {
javaccClasses.add(javaccClass);
javacClasses.add(javaccClass);
}
}

Expand All @@ -966,32 +967,28 @@ private void releaseJavaccClass(Class<?> javaccClass, CompilerConfiguration comp
* @throws CompilerException if the class has not been found.
*/
private Class<?> getJavacClass(CompilerConfiguration compilerConfiguration) throws CompilerException {
Class<?> c = null;
Class<?> c;
switch (compilerConfiguration.getCompilerReuseStrategy()) {
case AlwaysNew:
return createJavacClass();
case ReuseCreated:
synchronized (javaccClasses) {
if (javaccClasses.size() > 0) {
c = javaccClasses.get(0);
javaccClasses.remove(c);
return c;
}
c = javacClasses.poll();
if (c == null) {
c = createJavacClass();
}
c = createJavacClass();
return c;
case ReuseSame:
default:
c = JavacCompiler.JAVAC_CLASS;
if (c != null) {
return c;
}
synchronized (JavacCompiler.LOCK) {
if (c == null) {
JavacCompiler.JAVAC_CLASS = c = createJavacClass();
c = javacClass;
if (c == null) {
synchronized (this) {
c = javacClass;
if (c == null) {
javacClass = c = createJavacClass();
}
}
return c;
}
return c;
}
}

Expand Down

0 comments on commit 3dc1ca7

Please sign in to comment.